Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-STM32F103C8_org by
mbed_retarget.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "platform/platform.h" 00017 #include "drivers/FilePath.h" 00018 #include "hal/serial_api.h" 00019 #include "platform/mbed_toolchain.h" 00020 #include "platform/mbed_semihost_api.h" 00021 #include "platform/mbed_interface.h" 00022 #include "platform/SingletonPtr.h" 00023 #include "platform/PlatformMutex.h" 00024 #include "platform/mbed_error.h" 00025 #include "platform/mbed_stats.h" 00026 #if MBED_CONF_FILESYSTEM_PRESENT 00027 #include "filesystem/FileSystem.h" 00028 #include "filesystem/File.h" 00029 #include "filesystem/Dir.h" 00030 #endif 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #if DEVICE_STDIO_MESSAGES 00034 #include <stdio.h> 00035 #endif 00036 #include <errno.h> 00037 #include "platform/mbed_retarget.h" 00038 00039 00040 #if defined(__ARMCC_VERSION) 00041 # include <rt_sys.h> 00042 # define PREFIX(x) _sys##x 00043 # define OPEN_MAX _SYS_OPEN 00044 # ifdef __MICROLIB 00045 # pragma import(__use_full_stdio) 00046 # endif 00047 00048 #elif defined(__ICCARM__) 00049 # include <yfuns.h> 00050 # define PREFIX(x) _##x 00051 # define OPEN_MAX 16 00052 00053 # define STDIN_FILENO 0 00054 # define STDOUT_FILENO 1 00055 # define STDERR_FILENO 2 00056 00057 #else 00058 # include <sys/stat.h> 00059 # include <sys/syslimits.h> 00060 # define PREFIX(x) x 00061 #endif 00062 00063 #define FILE_HANDLE_RESERVED 0xFFFFFFFF 00064 00065 using namespace mbed; 00066 00067 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00068 // Before version 5.03, we were using a patched version of microlib with proper names 00069 extern const char __stdin_name[] = ":tt"; 00070 extern const char __stdout_name[] = ":tt"; 00071 extern const char __stderr_name[] = ":tt"; 00072 00073 #else 00074 extern const char __stdin_name[] = "/stdin"; 00075 extern const char __stdout_name[] = "/stdout"; 00076 extern const char __stderr_name[] = "/stderr"; 00077 #endif 00078 00079 // Heap limits - only used if set 00080 unsigned char *mbed_heap_start = 0; 00081 uint32_t mbed_heap_size = 0; 00082 00083 /* newlib has the filehandle field in the FILE struct as a short, so 00084 * we can't just return a Filehandle* from _open and instead have to 00085 * put it in a filehandles array and return the index into that array 00086 * (or rather index+3, as filehandles 0-2 are stdin/out/err). 00087 */ 00088 static FileLike *filehandles[OPEN_MAX]; 00089 static SingletonPtr<PlatformMutex> filehandle_mutex; 00090 00091 namespace mbed { 00092 void remove_filehandle(FileLike *file) { 00093 filehandle_mutex->lock(); 00094 /* Remove all open filehandles for this */ 00095 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00096 if (filehandles[fh_i] == file) { 00097 filehandles[fh_i] = NULL; 00098 } 00099 } 00100 filehandle_mutex->unlock(); 00101 } 00102 } 00103 00104 #if DEVICE_SERIAL 00105 extern int stdio_uart_inited; 00106 extern serial_t stdio_uart; 00107 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00108 static char stdio_in_prev; 00109 static char stdio_out_prev; 00110 #endif 00111 #endif 00112 00113 static void init_serial() { 00114 #if DEVICE_SERIAL 00115 if (stdio_uart_inited) return; 00116 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); 00117 #if MBED_CONF_PLATFORM_STDIO_BAUD_RATE 00118 serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE); 00119 #endif 00120 #endif 00121 } 00122 00123 static inline int openmode_to_posix(int openmode) { 00124 int posix = openmode; 00125 #ifdef __ARMCC_VERSION 00126 if (openmode & OPEN_PLUS) { 00127 posix = O_RDWR; 00128 } else if(openmode & OPEN_W) { 00129 posix = O_WRONLY; 00130 } else if(openmode & OPEN_A) { 00131 posix = O_WRONLY|O_APPEND; 00132 } else { 00133 posix = O_RDONLY; 00134 } 00135 /* a, w, a+, w+ all create if file does not already exist */ 00136 if (openmode & (OPEN_A|OPEN_W)) { 00137 posix |= O_CREAT; 00138 } 00139 /* w and w+ truncate */ 00140 if (openmode & OPEN_W) { 00141 posix |= O_TRUNC; 00142 } 00143 #elif defined(__ICCARM__) 00144 switch (openmode & _LLIO_RDWRMASK) { 00145 case _LLIO_RDONLY: posix = O_RDONLY; break; 00146 case _LLIO_WRONLY: posix = O_WRONLY; break; 00147 case _LLIO_RDWR : posix = O_RDWR ; break; 00148 } 00149 if (openmode & _LLIO_CREAT ) posix |= O_CREAT; 00150 if (openmode & _LLIO_APPEND) posix |= O_APPEND; 00151 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC; 00152 #elif defined(TOOLCHAIN_GCC) 00153 posix &= ~O_BINARY; 00154 #endif 00155 return posix; 00156 } 00157 00158 extern "C" WEAK void mbed_sdk_init(void); 00159 extern "C" WEAK void mbed_sdk_init(void) { 00160 } 00161 00162 #if MBED_CONF_FILESYSTEM_PRESENT 00163 // Internally used file objects with managed memory on close 00164 class ManagedFile : public File { 00165 public: 00166 virtual int close() { 00167 int err = File::close(); 00168 delete this; 00169 return err; 00170 } 00171 }; 00172 00173 class ManagedDir : public Dir { 00174 public: 00175 virtual int close() { 00176 int err = Dir::close(); 00177 delete this; 00178 return err; 00179 } 00180 }; 00181 #endif 00182 00183 /* @brief standard c library fopen() retargeting function. 00184 * 00185 * This function is invoked by the standard c library retargeting to handle fopen() 00186 * 00187 * @return 00188 * On success, a valid FILEHANDLE is returned. 00189 * On failure, -1 is returned and errno is set to an appropriate value e.g. 00190 * EBADF a bad file descriptor was found (default errno setting) 00191 * EMFILE the maximum number of open files was exceeded. 00192 * 00193 * */ 00194 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { 00195 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00196 // Before version 5.03, we were using a patched version of microlib with proper names 00197 // This is the workaround that the microlib author suggested us 00198 static int n = 0; 00199 static int mbed_sdk_inited = 0; 00200 if (!mbed_sdk_inited) { 00201 mbed_sdk_inited = 1; 00202 mbed_sdk_init(); 00203 } 00204 if (!std::strcmp(name, ":tt")) return n++; 00205 #else 00206 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00207 */ 00208 if (std::strcmp(name, __stdin_name) == 0) { 00209 init_serial(); 00210 return 0; 00211 } else if (std::strcmp(name, __stdout_name) == 0) { 00212 init_serial(); 00213 return 1; 00214 } else if (std::strcmp(name, __stderr_name) == 0) { 00215 init_serial(); 00216 return 2; 00217 } 00218 #endif 00219 00220 /* if something goes wrong and errno is not explicly set, errno will be set to EBADF */ 00221 errno = EBADF; 00222 00223 // find the first empty slot in filehandles 00224 filehandle_mutex->lock(); 00225 unsigned int fh_i; 00226 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00227 /* Take a next free filehandle slot available. */ 00228 if (filehandles[fh_i] == NULL) break; 00229 } 00230 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { 00231 /* Too many file handles have been opened */ 00232 errno = EMFILE; 00233 filehandle_mutex->unlock(); 00234 return -1; 00235 } 00236 filehandles[fh_i] = (FileLike*)FILE_HANDLE_RESERVED; 00237 filehandle_mutex->unlock(); 00238 00239 FileLike *res = NULL; 00240 00241 /* FILENAME: ":0x12345678" describes a FileLike* */ 00242 if (name[0] == ':') { 00243 void *p; 00244 sscanf(name, ":%p", &p); 00245 res = (FileLike*)p; 00246 00247 /* FILENAME: "/file_system/file_name" */ 00248 } else { 00249 FilePath path(name); 00250 00251 if (!path.exists()) { 00252 /* The first part of the filename (between first 2 '/') is not a 00253 * registered mount point in the namespace. 00254 * Free file handle. 00255 */ 00256 filehandles[fh_i] = NULL; 00257 errno = ENOENT; 00258 return -1; 00259 } else if (path.isFile()) { 00260 res = path.file(); 00261 #if MBED_CONF_FILESYSTEM_PRESENT 00262 } else { 00263 FileSystem *fs = path.fileSystem(); 00264 if (fs == NULL) { 00265 /* The filesystem instance managing the namespace under the mount point 00266 * has not been found. Free file handle */ 00267 errno = ENOENT; 00268 filehandles[fh_i] = NULL; 00269 return -1; 00270 } 00271 int posix_mode = openmode_to_posix(openmode); 00272 File *file = new ManagedFile; 00273 int err = file->open(fs, path.fileName(), posix_mode); 00274 if (err < 0) { 00275 errno = -err; 00276 delete file; 00277 } else { 00278 res = file; 00279 } 00280 #endif 00281 } 00282 } 00283 00284 if (res == NULL) { 00285 // Free file handle 00286 filehandles[fh_i] = NULL; 00287 return -1; 00288 } 00289 filehandles[fh_i] = res; 00290 00291 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err 00292 } 00293 00294 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00295 if (fh < 3) return 0; 00296 00297 errno = EBADF; 00298 FileLike* fhc = filehandles[fh-3]; 00299 filehandles[fh-3] = NULL; 00300 if (fhc == NULL) return -1; 00301 00302 int err = fhc->close(); 00303 if (err < 0) { 00304 errno = -err; 00305 return -1; 00306 } else { 00307 return 0; 00308 } 00309 } 00310 00311 #if defined(__ICCARM__) 00312 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00313 #else 00314 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00315 #endif 00316 int n; // n is the number of bytes written 00317 00318 errno = EBADF; 00319 if (fh < 3) { 00320 #if DEVICE_SERIAL 00321 if (!stdio_uart_inited) init_serial(); 00322 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00323 for (unsigned int i = 0; i < length; i++) { 00324 if (buffer[i] == '\n' && stdio_out_prev != '\r') { 00325 serial_putc(&stdio_uart, '\r'); 00326 } 00327 serial_putc(&stdio_uart, buffer[i]); 00328 stdio_out_prev = buffer[i]; 00329 } 00330 #else 00331 for (unsigned int i = 0; i < length; i++) { 00332 serial_putc(&stdio_uart, buffer[i]); 00333 } 00334 #endif 00335 #endif 00336 n = length; 00337 } else { 00338 FileLike* fhc = filehandles[fh-3]; 00339 if (fhc == NULL) return -1; 00340 00341 n = fhc->write(buffer, length); 00342 if (n < 0) { 00343 errno = -n; 00344 } 00345 } 00346 #ifdef __ARMCC_VERSION 00347 return length-n; 00348 #else 00349 return n; 00350 #endif 00351 } 00352 00353 #if defined(__ICCARM__) 00354 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00355 #else 00356 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00357 #endif 00358 int n; // n is the number of bytes read 00359 00360 errno = EBADF; 00361 if (fh < 3) { 00362 // only read a character at a time from stdin 00363 #if DEVICE_SERIAL 00364 if (!stdio_uart_inited) init_serial(); 00365 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00366 while (true) { 00367 char c = serial_getc(&stdio_uart); 00368 if ((c == '\r' && stdio_in_prev != '\n') || 00369 (c == '\n' && stdio_in_prev != '\r')) { 00370 stdio_in_prev = c; 00371 *buffer = '\n'; 00372 break; 00373 } else if ((c == '\r' && stdio_in_prev == '\n') || 00374 (c == '\n' && stdio_in_prev == '\r')) { 00375 stdio_in_prev = c; 00376 // onto next character 00377 continue; 00378 } else { 00379 stdio_in_prev = c; 00380 *buffer = c; 00381 break; 00382 } 00383 } 00384 #else 00385 *buffer = serial_getc(&stdio_uart); 00386 #endif 00387 #endif 00388 n = 1; 00389 } else { 00390 FileLike* fhc = filehandles[fh-3]; 00391 if (fhc == NULL) return -1; 00392 00393 n = fhc->read(buffer, length); 00394 if (n < 0) { 00395 errno = -n; 00396 } 00397 } 00398 #ifdef __ARMCC_VERSION 00399 return length-n; 00400 #else 00401 return n; 00402 #endif 00403 } 00404 00405 #ifdef __ARMCC_VERSION 00406 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00407 #else 00408 extern "C" int _isatty(FILEHANDLE fh) 00409 #endif 00410 { 00411 errno = EBADF; 00412 /* stdin, stdout and stderr should be tty */ 00413 if (fh < 3) return 1; 00414 00415 FileLike* fhc = filehandles[fh-3]; 00416 if (fhc == NULL) return -1; 00417 00418 int err = fhc->isatty(); 00419 if (err < 0) { 00420 errno = -err; 00421 return -1; 00422 } else { 00423 return 0; 00424 } 00425 } 00426 00427 extern "C" 00428 #if defined(__ARMCC_VERSION) 00429 int _sys_seek(FILEHANDLE fh, long position) 00430 #elif defined(__ICCARM__) 00431 long __lseek(int fh, long offset, int whence) 00432 #else 00433 int _lseek(FILEHANDLE fh, int offset, int whence) 00434 #endif 00435 { 00436 errno = EBADF; 00437 if (fh < 3) return 0; 00438 00439 FileLike* fhc = filehandles[fh-3]; 00440 if (fhc == NULL) return -1; 00441 00442 #if defined(__ARMCC_VERSION) 00443 return fhc->seek(position, SEEK_SET); 00444 #else 00445 return fhc->seek(offset, whence); 00446 #endif 00447 } 00448 00449 #ifdef __ARMCC_VERSION 00450 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00451 errno = EBADF; 00452 if (fh < 3) return 0; 00453 00454 FileLike* fhc = filehandles[fh-3]; 00455 if (fhc == NULL) return -1; 00456 00457 int err = fhc->sync(); 00458 if (err < 0) { 00459 errno = -err; 00460 return -1; 00461 } else { 00462 return 0; 00463 } 00464 } 00465 00466 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00467 errno = EBADF; 00468 if (fh < 3) return 0; 00469 00470 FileLike* fhc = filehandles[fh-3]; 00471 if (fhc == NULL) return -1; 00472 00473 return fhc->size(); 00474 } 00475 #endif 00476 00477 00478 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00479 extern "C" int _fstat(int fd, struct stat *st) { 00480 if (fd < 3) { 00481 st->st_mode = S_IFCHR; 00482 return 0; 00483 } 00484 errno = EBADF; 00485 return -1; 00486 } 00487 #endif 00488 00489 namespace std { 00490 extern "C" int remove(const char *path) { 00491 #if MBED_CONF_FILESYSTEM_PRESENT 00492 errno = EBADF; 00493 FilePath fp(path); 00494 FileSystem *fs = fp.fileSystem(); 00495 if (fs == NULL) return -1; 00496 00497 int err = fs->remove(fp.fileName()); 00498 if (err < 0) { 00499 errno = -err; 00500 return -1; 00501 } else { 00502 return 0; 00503 } 00504 #else 00505 errno = ENOSYS; 00506 return -1; 00507 #endif 00508 } 00509 00510 extern "C" int rename(const char *oldname, const char *newname) { 00511 #if MBED_CONF_FILESYSTEM_PRESENT 00512 errno = EBADF; 00513 FilePath fpOld(oldname); 00514 FilePath fpNew(newname); 00515 FileSystem *fsOld = fpOld.fileSystem(); 00516 FileSystem *fsNew = fpNew.fileSystem(); 00517 00518 /* rename only if both files are on the same FS */ 00519 if (fsOld != fsNew || fsOld == NULL) return -1; 00520 00521 int err = fsOld->rename(fpOld.fileName(), fpNew.fileName()); 00522 if (err < 0) { 00523 errno = -err; 00524 return -1; 00525 } else { 00526 return 0; 00527 } 00528 #else 00529 errno = ENOSYS; 00530 return -1; 00531 #endif 00532 } 00533 00534 extern "C" char *tmpnam(char *s) { 00535 errno = EBADF; 00536 return NULL; 00537 } 00538 00539 extern "C" FILE *tmpfile() { 00540 errno = EBADF; 00541 return NULL; 00542 } 00543 } // namespace std 00544 00545 #ifdef __ARMCC_VERSION 00546 extern "C" char *_sys_command_string(char *cmd, int len) { 00547 return NULL; 00548 } 00549 #endif 00550 00551 extern "C" DIR *opendir(const char *path) { 00552 #if MBED_CONF_FILESYSTEM_PRESENT 00553 errno = EBADF; 00554 00555 FilePath fp(path); 00556 FileSystem* fs = fp.fileSystem(); 00557 if (fs == NULL) return NULL; 00558 00559 Dir *dir = new ManagedDir; 00560 int err = dir->open(fs, fp.fileName()); 00561 if (err < 0) { 00562 errno = -err; 00563 delete dir; 00564 dir = NULL; 00565 } 00566 00567 return dir; 00568 #else 00569 errno = ENOSYS; 00570 return 0; 00571 #endif 00572 } 00573 00574 extern "C" struct dirent *readdir(DIR *dir) { 00575 #if MBED_CONF_FILESYSTEM_PRESENT 00576 static struct dirent ent; 00577 int err = dir->read(&ent); 00578 if (err < 1) { 00579 if (err < 0) { 00580 errno = -err; 00581 } 00582 return NULL; 00583 } 00584 00585 return &ent; 00586 #else 00587 errno = ENOSYS; 00588 return 0; 00589 #endif 00590 } 00591 00592 extern "C" int closedir(DIR *dir) { 00593 #if MBED_CONF_FILESYSTEM_PRESENT 00594 int err = dir->close(); 00595 if (err < 0) { 00596 errno = -err; 00597 return -1; 00598 } else { 00599 return 0; 00600 } 00601 #else 00602 errno = ENOSYS; 00603 return -1; 00604 #endif 00605 } 00606 00607 extern "C" void rewinddir(DIR *dir) { 00608 #if MBED_CONF_FILESYSTEM_PRESENT 00609 dir->rewind(); 00610 #else 00611 errno = ENOSYS; 00612 #endif 00613 } 00614 00615 extern "C" off_t telldir(DIR *dir) { 00616 #if MBED_CONF_FILESYSTEM_PRESENT 00617 return dir->tell(); 00618 #else 00619 errno = ENOSYS; 00620 return 0; 00621 #endif 00622 } 00623 00624 extern "C" void seekdir(DIR *dir, off_t off) { 00625 #if MBED_CONF_FILESYSTEM_PRESENT 00626 dir->seek(off); 00627 #else 00628 errno = ENOSYS; 00629 #endif 00630 } 00631 00632 extern "C" int mkdir(const char *path, mode_t mode) { 00633 #if MBED_CONF_FILESYSTEM_PRESENT 00634 FilePath fp(path); 00635 FileSystem *fs = fp.fileSystem(); 00636 if (fs == NULL) return -1; 00637 00638 int err = fs->mkdir(fp.fileName(), mode); 00639 if (err < 0) { 00640 errno = -err; 00641 return -1; 00642 } else { 00643 return 0; 00644 } 00645 #else 00646 errno = ENOSYS; 00647 return -1; 00648 #endif 00649 } 00650 00651 extern "C" int stat(const char *path, struct stat *st) { 00652 #if MBED_CONF_FILESYSTEM_PRESENT 00653 FilePath fp(path); 00654 FileSystem *fs = fp.fileSystem(); 00655 if (fs == NULL) return -1; 00656 00657 int err = fs->stat(fp.fileName(), st); 00658 if (err < 0) { 00659 errno = -err; 00660 return -1; 00661 } else { 00662 return 0; 00663 } 00664 #else 00665 errno = ENOSYS; 00666 return -1; 00667 #endif 00668 } 00669 00670 #if defined(TOOLCHAIN_GCC) 00671 /* prevents the exception handling name demangling code getting pulled in */ 00672 #include "mbed_error.h" 00673 namespace __gnu_cxx { 00674 void __verbose_terminate_handler() { 00675 error("Exception"); 00676 } 00677 } 00678 extern "C" WEAK void __cxa_pure_virtual(void); 00679 extern "C" WEAK void __cxa_pure_virtual(void) { 00680 exit(1); 00681 } 00682 00683 #endif 00684 00685 #if defined(TOOLCHAIN_GCC) 00686 00687 #ifdef FEATURE_UVISOR 00688 #include "uvisor-lib/uvisor-lib.h" 00689 #endif/* FEATURE_UVISOR */ 00690 00691 00692 extern "C" WEAK void software_init_hook_rtos(void) 00693 { 00694 // Do nothing by default. 00695 } 00696 00697 extern "C" void software_init_hook(void) 00698 { 00699 #ifdef FEATURE_UVISOR 00700 int return_code; 00701 00702 return_code = uvisor_lib_init(); 00703 if (return_code) { 00704 mbed_die(); 00705 } 00706 #endif/* FEATURE_UVISOR */ 00707 mbed_sdk_init(); 00708 software_init_hook_rtos(); 00709 } 00710 #endif 00711 00712 // **************************************************************************** 00713 // mbed_main is a function that is called before main() 00714 // mbed_sdk_init() is also a function that is called before main(), but unlike 00715 // mbed_main(), it is not meant for user code, but for the SDK itself to perform 00716 // initializations before main() is called. 00717 00718 extern "C" WEAK void mbed_main(void); 00719 extern "C" WEAK void mbed_main(void) { 00720 } 00721 00722 #if defined(TOOLCHAIN_ARM) 00723 extern "C" int $Super$$main(void); 00724 00725 extern "C" int $Sub$$main(void) { 00726 mbed_main(); 00727 return $Super$$main(); 00728 } 00729 00730 extern "C" void _platform_post_stackheap_init (void) { 00731 mbed_sdk_init(); 00732 } 00733 00734 #elif defined(TOOLCHAIN_GCC) 00735 extern "C" int __real_main(void); 00736 00737 extern "C" int __wrap_main(void) { 00738 mbed_main(); 00739 return __real_main(); 00740 } 00741 #elif defined(TOOLCHAIN_IAR) 00742 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent 00743 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting 00744 // 'main' to another symbol looses the original 'main' symbol. However, its startup 00745 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined. 00746 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main. 00747 extern "C" void __iar_argc_argv() { 00748 mbed_main(); 00749 } 00750 #endif 00751 00752 // Provide implementation of _sbrk (low-level dynamic memory allocation 00753 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 00754 // SP. This make it compatible with RTX RTOS thread stacks. 00755 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 00756 // Linker defined symbol used by _sbrk to indicate where heap should start. 00757 extern "C" int __end__; 00758 00759 #if defined(TARGET_CORTEX_A) 00760 extern "C" uint32_t __HeapLimit; 00761 #endif 00762 00763 // Turn off the errno macro and use actual global variable instead. 00764 #undef errno 00765 extern "C" int errno; 00766 00767 // For ARM7 only 00768 register unsigned char * stack_ptr __asm ("sp"); 00769 00770 // Dynamic memory allocation related syscall. 00771 #if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453) 00772 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions). 00773 // __wrap__sbrk() is implemented in: 00774 // TARGET_NUMAKER_PFM_NUC472 hal/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/retarget.c 00775 // TARGET_NUMAKER_PFM_M453 hal/targets/cmsis/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/retarget.c 00776 extern "C" void *__wrap__sbrk(int incr); 00777 extern "C" caddr_t _sbrk(int incr) { 00778 return (caddr_t) __wrap__sbrk(incr); 00779 } 00780 #else 00781 extern "C" caddr_t _sbrk(int incr) { 00782 static unsigned char* heap = (unsigned char*)&__end__; 00783 unsigned char* prev_heap = heap; 00784 unsigned char* new_heap = heap + incr; 00785 00786 #if defined(TARGET_ARM7) 00787 if (new_heap >= stack_ptr) { 00788 #elif defined(TARGET_CORTEX_A) 00789 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */ 00790 #else 00791 if (new_heap >= (unsigned char*)__get_MSP()) { 00792 #endif 00793 errno = ENOMEM; 00794 return (caddr_t)-1; 00795 } 00796 00797 // Additional heap checking if set 00798 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) { 00799 errno = ENOMEM; 00800 return (caddr_t)-1; 00801 } 00802 00803 heap = new_heap; 00804 return (caddr_t) prev_heap; 00805 } 00806 #endif 00807 #endif 00808 00809 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 00810 extern "C" void _exit(int return_code) { 00811 #else 00812 namespace std { 00813 extern "C" void exit(int return_code) { 00814 #endif 00815 00816 #if DEVICE_STDIO_MESSAGES 00817 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT 00818 fflush(stdout); 00819 fflush(stderr); 00820 #endif 00821 #endif 00822 00823 #if DEVICE_SEMIHOST 00824 if (mbed_interface_connected()) { 00825 semihost_exit(); 00826 } 00827 #endif 00828 if (return_code) { 00829 mbed_die(); 00830 } 00831 00832 while (1); 00833 } 00834 00835 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR) 00836 } //namespace std 00837 #endif 00838 00839 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC) 00840 00841 // This series of function disable the registration of global destructors 00842 // in a dynamic table which will be called when the application exit. 00843 // In mbed, program never exit properly, it dies. 00844 // More informations about this topic for ARMCC here: 00845 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html 00846 extern "C" { 00847 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) { 00848 return 1; 00849 } 00850 00851 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) { 00852 return 1; 00853 } 00854 00855 void __cxa_finalize(void *handle) { 00856 } 00857 00858 } // end of extern "C" 00859 00860 #endif 00861 00862 00863 #if defined(TOOLCHAIN_GCC) 00864 00865 /* 00866 * Depending on how newlib is configured, it is often not enough to define 00867 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the 00868 * behavior regarding the registration of handlers with atexit. 00869 * 00870 * To overcome this limitation, exit and atexit are overriden here. 00871 */ 00872 extern "C"{ 00873 00874 /** 00875 * @brief Retarget of exit for GCC. 00876 * @details Unlike the standard version, this function doesn't call any function 00877 * registered with atexit before calling _exit. 00878 */ 00879 void __wrap_exit(int return_code) { 00880 _exit(return_code); 00881 } 00882 00883 /** 00884 * @brief Retarget atexit from GCC. 00885 * @details This function will always fail and never register any handler to be 00886 * called at exit. 00887 */ 00888 int __wrap_atexit(void (*func)()) { 00889 return 1; 00890 } 00891 00892 } 00893 00894 #endif 00895 00896 00897 00898 namespace mbed { 00899 00900 void mbed_set_unbuffered_stream(FILE *_file) { 00901 #if defined (__ICCARM__) 00902 char buf[2]; 00903 std::setvbuf(_file,buf,_IONBF,NULL); 00904 #else 00905 setbuf(_file, NULL); 00906 #endif 00907 } 00908 00909 int mbed_getc(FILE *_file){ 00910 #if defined (__ICCARM__) 00911 /*This is only valid for unbuffered streams*/ 00912 int res = std::fgetc(_file); 00913 if (res>=0){ 00914 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 00915 _file->_Rend = _file->_Wend; 00916 _file->_Next = _file->_Wend; 00917 } 00918 return res; 00919 #else 00920 return std::fgetc(_file); 00921 #endif 00922 } 00923 00924 char* mbed_gets(char*s, int size, FILE *_file){ 00925 #if defined (__ICCARM__) 00926 /*This is only valid for unbuffered streams*/ 00927 char *str = fgets(s,size,_file); 00928 if (str!=NULL){ 00929 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 00930 _file->_Rend = _file->_Wend; 00931 _file->_Next = _file->_Wend; 00932 } 00933 return str; 00934 #else 00935 return std::fgets(s,size,_file); 00936 #endif 00937 } 00938 00939 } // namespace mbed 00940 00941 #if defined (__ICCARM__) 00942 // Stub out locks when an rtos is not present 00943 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {} 00944 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {} 00945 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {} 00946 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {} 00947 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {} 00948 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {} 00949 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {} 00950 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {} 00951 #elif defined(__CC_ARM) 00952 // Do nothing 00953 #elif defined (__GNUC__) 00954 struct _reent; 00955 // Stub out locks when an rtos is not present 00956 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {} 00957 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {} 00958 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {} 00959 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {} 00960 00961 extern "C" void __malloc_lock( struct _reent *_r ) 00962 { 00963 __rtos_malloc_lock(_r); 00964 } 00965 00966 extern "C" void __malloc_unlock( struct _reent *_r ) 00967 { 00968 __rtos_malloc_unlock(_r); 00969 } 00970 00971 extern "C" void __env_lock( struct _reent *_r ) 00972 { 00973 __rtos_env_lock(_r); 00974 } 00975 00976 extern "C" void __env_unlock( struct _reent *_r ) 00977 { 00978 __rtos_env_unlock(_r); 00979 } 00980 00981 #define CXA_GUARD_INIT_DONE (1 << 0) 00982 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1) 00983 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS) 00984 00985 extern "C" int __cxa_guard_acquire(int *guard_object_p) 00986 { 00987 uint8_t *guard_object = (uint8_t *)guard_object_p; 00988 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 00989 return 0; 00990 } 00991 singleton_lock(); 00992 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 00993 singleton_unlock(); 00994 return 0; 00995 } 00996 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK)); 00997 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS; 00998 return 1; 00999 } 01000 01001 extern "C" void __cxa_guard_release(int *guard_object_p) 01002 { 01003 uint8_t *guard_object = (uint8_t *)guard_object_p; 01004 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01005 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE; 01006 singleton_unlock(); 01007 } 01008 01009 extern "C" void __cxa_guard_abort(int *guard_object_p) 01010 { 01011 uint8_t *guard_object = (uint8_t *)guard_object_p; 01012 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01013 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS; 01014 singleton_unlock(); 01015 } 01016 01017 #endif 01018 01019 void *operator new(std::size_t count) 01020 { 01021 void *buffer = malloc(count); 01022 if (NULL == buffer) { 01023 error("Operator new out of memory\r\n"); 01024 } 01025 return buffer; 01026 } 01027 01028 void *operator new[](std::size_t count) 01029 { 01030 void *buffer = malloc(count); 01031 if (NULL == buffer) { 01032 error("Operator new[] out of memory\r\n"); 01033 } 01034 return buffer; 01035 } 01036 01037 void operator delete(void *ptr) 01038 { 01039 if (ptr != NULL) { 01040 free(ptr); 01041 } 01042 } 01043 void operator delete[](void *ptr) 01044 { 01045 if (ptr != NULL) { 01046 free(ptr); 01047 } 01048 }
Generated on Tue Jul 12 2022 16:30:32 by
1.7.2
