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