lib
Fork of mbed-dev by
Embed:
(wiki syntax)
Show/hide line numbers
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/FileHandle.h" 00018 #include "drivers/FileSystemLike.h" 00019 #include "drivers/FilePath.h" 00020 #include "hal/serial_api.h" 00021 #include "platform/toolchain.h" 00022 #include "platform/semihost_api.h" 00023 #include "platform/mbed_interface.h" 00024 #include "platform/SingletonPtr.h" 00025 #include "platform/PlatformMutex.h" 00026 #include "platform/mbed_error.h" 00027 #include "platform/mbed_stats.h" 00028 #include <stdlib.h> 00029 #include <string.h> 00030 #if DEVICE_STDIO_MESSAGES 00031 #include <stdio.h> 00032 #endif 00033 #include <errno.h> 00034 00035 #if defined(__ARMCC_VERSION) 00036 # include <rt_sys.h> 00037 # define PREFIX(x) _sys##x 00038 # define OPEN_MAX _SYS_OPEN 00039 # ifdef __MICROLIB 00040 # pragma import(__use_full_stdio) 00041 # endif 00042 00043 #elif defined(__ICCARM__) 00044 # include <yfuns.h> 00045 # define PREFIX(x) _##x 00046 # define OPEN_MAX 16 00047 00048 # define STDIN_FILENO 0 00049 # define STDOUT_FILENO 1 00050 # define STDERR_FILENO 2 00051 00052 #else 00053 # include <sys/stat.h> 00054 # include <sys/unistd.h> 00055 # include <sys/syslimits.h> 00056 # define PREFIX(x) x 00057 #endif 00058 00059 #define FILE_HANDLE_RESERVED 0xFFFFFFFF 00060 00061 using namespace mbed; 00062 00063 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00064 // Before version 5.03, we were using a patched version of microlib with proper names 00065 extern const char __stdin_name[] = ":tt"; 00066 extern const char __stdout_name[] = ":tt"; 00067 extern const char __stderr_name[] = ":tt"; 00068 00069 #else 00070 extern const char __stdin_name[] = "/stdin"; 00071 extern const char __stdout_name[] = "/stdout"; 00072 extern const char __stderr_name[] = "/stderr"; 00073 #endif 00074 00075 // Heap limits - only used if set 00076 unsigned char *mbed_heap_start = 0; 00077 uint32_t mbed_heap_size = 0; 00078 00079 /* newlib has the filehandle field in the FILE struct as a short, so 00080 * we can't just return a Filehandle* from _open and instead have to 00081 * put it in a filehandles array and return the index into that array 00082 * (or rather index+3, as filehandles 0-2 are stdin/out/err). 00083 */ 00084 static FileHandle *filehandles[OPEN_MAX]; 00085 static SingletonPtr<PlatformMutex> filehandle_mutex; 00086 00087 FileHandle::~FileHandle() { 00088 filehandle_mutex->lock(); 00089 /* Remove all open filehandles for this */ 00090 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00091 if (filehandles[fh_i] == this) { 00092 filehandles[fh_i] = NULL; 00093 } 00094 } 00095 filehandle_mutex->unlock(); 00096 } 00097 00098 #if DEVICE_SERIAL 00099 extern int stdio_uart_inited; 00100 extern serial_t stdio_uart; 00101 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00102 static char stdio_in_prev; 00103 static char stdio_out_prev; 00104 #endif 00105 #endif 00106 00107 static void init_serial() { 00108 #if DEVICE_SERIAL 00109 if (stdio_uart_inited) return; 00110 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); 00111 #if MBED_CONF_PLATFORM_STDIO_BAUD_RATE 00112 serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE); 00113 #endif 00114 #endif 00115 } 00116 00117 static inline int openmode_to_posix(int openmode) { 00118 int posix = openmode; 00119 #ifdef __ARMCC_VERSION 00120 if (openmode & OPEN_PLUS) { 00121 posix = O_RDWR; 00122 } else if(openmode & OPEN_W) { 00123 posix = O_WRONLY; 00124 } else if(openmode & OPEN_A) { 00125 posix = O_WRONLY|O_APPEND; 00126 } else { 00127 posix = O_RDONLY; 00128 } 00129 /* a, w, a+, w+ all create if file does not already exist */ 00130 if (openmode & (OPEN_A|OPEN_W)) { 00131 posix |= O_CREAT; 00132 } 00133 /* w and w+ truncate */ 00134 if (openmode & OPEN_W) { 00135 posix |= O_TRUNC; 00136 } 00137 #elif defined(__ICCARM__) 00138 switch (openmode & _LLIO_RDWRMASK) { 00139 case _LLIO_RDONLY: posix = O_RDONLY; break; 00140 case _LLIO_WRONLY: posix = O_WRONLY; break; 00141 case _LLIO_RDWR : posix = O_RDWR ; break; 00142 } 00143 if (openmode & _LLIO_CREAT ) posix |= O_CREAT; 00144 if (openmode & _LLIO_APPEND) posix |= O_APPEND; 00145 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC; 00146 #elif defined(TOOLCHAIN_GCC) 00147 posix &= ~O_BINARY; 00148 #endif 00149 return posix; 00150 } 00151 00152 extern "C" WEAK void mbed_sdk_init(void); 00153 extern "C" WEAK void mbed_sdk_init(void) { 00154 } 00155 00156 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { 00157 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00158 // Before version 5.03, we were using a patched version of microlib with proper names 00159 // This is the workaround that the microlib author suggested us 00160 static int n = 0; 00161 static int mbed_sdk_inited = 0; 00162 if (!mbed_sdk_inited) { 00163 mbed_sdk_inited = 1; 00164 mbed_sdk_init(); 00165 } 00166 if (!std::strcmp(name, ":tt")) return n++; 00167 #else 00168 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00169 */ 00170 if (std::strcmp(name, __stdin_name) == 0) { 00171 init_serial(); 00172 return 0; 00173 } else if (std::strcmp(name, __stdout_name) == 0) { 00174 init_serial(); 00175 return 1; 00176 } else if (std::strcmp(name, __stderr_name) == 0) { 00177 init_serial(); 00178 return 2; 00179 } 00180 #endif 00181 00182 // find the first empty slot in filehandles 00183 filehandle_mutex->lock(); 00184 unsigned int fh_i; 00185 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00186 if (filehandles[fh_i] == NULL) break; 00187 } 00188 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { 00189 filehandle_mutex->unlock(); 00190 return -1; 00191 } 00192 filehandles[fh_i] = (FileHandle*)FILE_HANDLE_RESERVED; 00193 filehandle_mutex->unlock(); 00194 00195 FileHandle *res; 00196 00197 /* FILENAME: ":0x12345678" describes a FileLike* */ 00198 if (name[0] == ':') { 00199 void *p; 00200 sscanf(name, ":%p", &p); 00201 res = (FileHandle*)p; 00202 00203 /* FILENAME: "/file_system/file_name" */ 00204 } else { 00205 FilePath path(name); 00206 00207 if (!path.exists()) { 00208 // Free file handle 00209 filehandles[fh_i] = NULL; 00210 return -1; 00211 } else if (path.isFile()) { 00212 res = path.file(); 00213 } else { 00214 FileSystemLike *fs = path.fileSystem(); 00215 if (fs == NULL) { 00216 // Free file handle 00217 filehandles[fh_i] = NULL; 00218 return -1; 00219 } 00220 int posix_mode = openmode_to_posix(openmode); 00221 res = fs->open(path.fileName(), posix_mode); /* NULL if fails */ 00222 } 00223 } 00224 00225 if (res == NULL) { 00226 // Free file handle 00227 filehandles[fh_i] = NULL; 00228 return -1; 00229 } 00230 filehandles[fh_i] = res; 00231 00232 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err 00233 } 00234 00235 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00236 if (fh < 3) return 0; 00237 00238 FileHandle* fhc = filehandles[fh-3]; 00239 filehandles[fh-3] = NULL; 00240 if (fhc == NULL) return -1; 00241 00242 return fhc->close(); 00243 } 00244 00245 #if defined(__ICCARM__) 00246 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00247 #else 00248 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00249 #endif 00250 int n; // n is the number of bytes written 00251 if (fh < 3) { 00252 #if DEVICE_SERIAL 00253 if (!stdio_uart_inited) init_serial(); 00254 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00255 for (unsigned int i = 0; i < length; i++) { 00256 if (buffer[i] == '\n' && stdio_out_prev != '\r') { 00257 serial_putc(&stdio_uart, '\r'); 00258 } 00259 serial_putc(&stdio_uart, buffer[i]); 00260 stdio_out_prev = buffer[i]; 00261 } 00262 #else 00263 for (unsigned int i = 0; i < length; i++) { 00264 serial_putc(&stdio_uart, buffer[i]); 00265 } 00266 #endif 00267 #endif 00268 n = length; 00269 } else { 00270 FileHandle* fhc = filehandles[fh-3]; 00271 if (fhc == NULL) return -1; 00272 00273 n = fhc->write(buffer, length); 00274 } 00275 #ifdef __ARMCC_VERSION 00276 return length-n; 00277 #else 00278 return n; 00279 #endif 00280 } 00281 00282 #if defined(__ICCARM__) 00283 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00284 #else 00285 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00286 #endif 00287 int n; // n is the number of bytes read 00288 if (fh < 3) { 00289 // only read a character at a time from stdin 00290 #if DEVICE_SERIAL 00291 if (!stdio_uart_inited) init_serial(); 00292 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00293 while (true) { 00294 char c = serial_getc(&stdio_uart); 00295 if ((c == '\r' && stdio_in_prev != '\n') || 00296 (c == '\n' && stdio_in_prev != '\r')) { 00297 stdio_in_prev = c; 00298 *buffer = '\n'; 00299 break; 00300 } else if ((c == '\r' && stdio_in_prev == '\n') || 00301 (c == '\n' && stdio_in_prev == '\r')) { 00302 stdio_in_prev = c; 00303 // onto next character 00304 continue; 00305 } else { 00306 stdio_in_prev = c; 00307 *buffer = c; 00308 break; 00309 } 00310 } 00311 #else 00312 *buffer = serial_getc(&stdio_uart); 00313 #endif 00314 #endif 00315 n = 1; 00316 } else { 00317 FileHandle* fhc = filehandles[fh-3]; 00318 if (fhc == NULL) return -1; 00319 00320 n = fhc->read(buffer, length); 00321 } 00322 #ifdef __ARMCC_VERSION 00323 return length-n; 00324 #else 00325 return n; 00326 #endif 00327 } 00328 00329 #ifdef __ARMCC_VERSION 00330 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00331 #else 00332 extern "C" int _isatty(FILEHANDLE fh) 00333 #endif 00334 { 00335 /* stdin, stdout and stderr should be tty */ 00336 if (fh < 3) return 1; 00337 00338 FileHandle* fhc = filehandles[fh-3]; 00339 if (fhc == NULL) return -1; 00340 00341 return fhc->isatty(); 00342 } 00343 00344 extern "C" 00345 #if defined(__ARMCC_VERSION) 00346 int _sys_seek(FILEHANDLE fh, long position) 00347 #elif defined(__ICCARM__) 00348 long __lseek(int fh, long offset, int whence) 00349 #else 00350 int _lseek(FILEHANDLE fh, int offset, int whence) 00351 #endif 00352 { 00353 if (fh < 3) return 0; 00354 00355 FileHandle* fhc = filehandles[fh-3]; 00356 if (fhc == NULL) return -1; 00357 00358 #if defined(__ARMCC_VERSION) 00359 return fhc->lseek(position, SEEK_SET); 00360 #else 00361 return fhc->lseek(offset, whence); 00362 #endif 00363 } 00364 00365 #ifdef __ARMCC_VERSION 00366 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00367 if (fh < 3) return 0; 00368 00369 FileHandle* fhc = filehandles[fh-3]; 00370 if (fhc == NULL) return -1; 00371 00372 return fhc->fsync(); 00373 } 00374 00375 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00376 if (fh < 3) return 0; 00377 00378 FileHandle* fhc = filehandles[fh-3]; 00379 if (fhc == NULL) return -1; 00380 00381 return fhc->flen(); 00382 } 00383 #endif 00384 00385 00386 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00387 extern "C" int _fstat(int fd, struct stat *st) { 00388 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { 00389 st->st_mode = S_IFCHR; 00390 return 0; 00391 } 00392 00393 errno = EBADF; 00394 return -1; 00395 } 00396 #endif 00397 00398 namespace std { 00399 extern "C" int remove(const char *path) { 00400 FilePath fp(path); 00401 FileSystemLike *fs = fp.fileSystem(); 00402 if (fs == NULL) return -1; 00403 00404 return fs->remove(fp.fileName()); 00405 } 00406 00407 extern "C" int rename(const char *oldname, const char *newname) { 00408 FilePath fpOld(oldname); 00409 FilePath fpNew(newname); 00410 FileSystemLike *fsOld = fpOld.fileSystem(); 00411 FileSystemLike *fsNew = fpNew.fileSystem(); 00412 00413 /* rename only if both files are on the same FS */ 00414 if (fsOld != fsNew || fsOld == NULL) return -1; 00415 00416 return fsOld->rename(fpOld.fileName(), fpNew.fileName()); 00417 } 00418 00419 extern "C" char *tmpnam(char *s) { 00420 return NULL; 00421 } 00422 00423 extern "C" FILE *tmpfile() { 00424 return NULL; 00425 } 00426 } // namespace std 00427 00428 #ifdef __ARMCC_VERSION 00429 extern "C" char *_sys_command_string(char *cmd, int len) { 00430 return NULL; 00431 } 00432 #endif 00433 00434 extern "C" DIR *opendir(const char *path) { 00435 /* root dir is FileSystemLike */ 00436 if (path[0] == '/' && path[1] == 0) { 00437 return FileSystemLike::opendir(); 00438 } 00439 00440 FilePath fp(path); 00441 FileSystemLike* fs = fp.fileSystem(); 00442 if (fs == NULL) return NULL; 00443 00444 return fs->opendir(fp.fileName()); 00445 } 00446 00447 extern "C" struct dirent *readdir(DIR *dir) { 00448 return dir->readdir(); 00449 } 00450 00451 extern "C" int closedir(DIR *dir) { 00452 return dir->closedir(); 00453 } 00454 00455 extern "C" void rewinddir(DIR *dir) { 00456 dir->rewinddir(); 00457 } 00458 00459 extern "C" off_t telldir(DIR *dir) { 00460 return dir->telldir(); 00461 } 00462 00463 extern "C" void seekdir(DIR *dir, off_t off) { 00464 dir->seekdir(off); 00465 } 00466 00467 extern "C" int mkdir(const char *path, mode_t mode) { 00468 FilePath fp(path); 00469 FileSystemLike *fs = fp.fileSystem(); 00470 if (fs == NULL) return -1; 00471 00472 return fs->mkdir(fp.fileName(), mode); 00473 } 00474 00475 #if defined(TOOLCHAIN_GCC) 00476 /* prevents the exception handling name demangling code getting pulled in */ 00477 #include "mbed_error.h" 00478 namespace __gnu_cxx { 00479 void __verbose_terminate_handler() { 00480 error("Exception"); 00481 } 00482 } 00483 extern "C" WEAK void __cxa_pure_virtual(void); 00484 extern "C" WEAK void __cxa_pure_virtual(void) { 00485 exit(1); 00486 } 00487 00488 #endif 00489 00490 #if defined(TOOLCHAIN_GCC) 00491 00492 #ifdef FEATURE_UVISOR 00493 #include "uvisor-lib/uvisor-lib.h" 00494 #endif/* FEATURE_UVISOR */ 00495 00496 00497 extern "C" WEAK void software_init_hook_rtos(void) 00498 { 00499 // Do nothing by default. 00500 } 00501 00502 extern "C" void software_init_hook(void) 00503 { 00504 #ifdef FEATURE_UVISOR 00505 int return_code; 00506 00507 return_code = uvisor_lib_init(); 00508 if (return_code) { 00509 mbed_die(); 00510 } 00511 #endif/* FEATURE_UVISOR */ 00512 mbed_sdk_init(); 00513 software_init_hook_rtos(); 00514 } 00515 #endif 00516 00517 // **************************************************************************** 00518 // mbed_main is a function that is called before main() 00519 // mbed_sdk_init() is also a function that is called before main(), but unlike 00520 // mbed_main(), it is not meant for user code, but for the SDK itself to perform 00521 // initializations before main() is called. 00522 00523 extern "C" WEAK void mbed_main(void); 00524 extern "C" WEAK void mbed_main(void) { 00525 } 00526 00527 #if defined(TOOLCHAIN_ARM) 00528 extern "C" int $Super$$main(void); 00529 00530 extern "C" int $Sub$$main(void) { 00531 mbed_main(); 00532 return $Super$$main(); 00533 } 00534 00535 extern "C" void _platform_post_stackheap_init (void) { 00536 mbed_sdk_init(); 00537 } 00538 00539 #elif defined(TOOLCHAIN_GCC) 00540 extern "C" int __real_main(void); 00541 00542 extern "C" int __wrap_main(void) { 00543 mbed_main(); 00544 return __real_main(); 00545 } 00546 #elif defined(TOOLCHAIN_IAR) 00547 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent 00548 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting 00549 // 'main' to another symbol looses the original 'main' symbol. However, its startup 00550 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined. 00551 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main. 00552 extern "C" void __iar_argc_argv() { 00553 mbed_main(); 00554 } 00555 #endif 00556 00557 // Provide implementation of _sbrk (low-level dynamic memory allocation 00558 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 00559 // SP. This make it compatible with RTX RTOS thread stacks. 00560 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 00561 // Linker defined symbol used by _sbrk to indicate where heap should start. 00562 extern "C" int __end__; 00563 00564 #if defined(TARGET_CORTEX_A) 00565 extern "C" uint32_t __HeapLimit; 00566 #endif 00567 00568 // Turn off the errno macro and use actual global variable instead. 00569 #undef errno 00570 extern "C" int errno; 00571 00572 // For ARM7 only 00573 register unsigned char * stack_ptr __asm ("sp"); 00574 00575 // Dynamic memory allocation related syscall. 00576 #if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453) 00577 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions). 00578 // __wrap__sbrk() is implemented in: 00579 // TARGET_NUMAKER_PFM_NUC472 hal/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/retarget.c 00580 // TARGET_NUMAKER_PFM_M453 hal/targets/cmsis/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/retarget.c 00581 extern "C" void *__wrap__sbrk(int incr); 00582 extern "C" caddr_t _sbrk(int incr) { 00583 return (caddr_t) __wrap__sbrk(incr); 00584 } 00585 #else 00586 extern "C" caddr_t _sbrk(int incr) { 00587 static unsigned char* heap = (unsigned char*)&__end__; 00588 unsigned char* prev_heap = heap; 00589 unsigned char* new_heap = heap + incr; 00590 00591 #if defined(TARGET_ARM7) 00592 if (new_heap >= stack_ptr) { 00593 #elif defined(TARGET_CORTEX_A) 00594 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */ 00595 #else 00596 if (new_heap >= (unsigned char*)__get_MSP()) { 00597 #endif 00598 errno = ENOMEM; 00599 return (caddr_t)-1; 00600 } 00601 00602 // Additional heap checking if set 00603 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) { 00604 errno = ENOMEM; 00605 return (caddr_t)-1; 00606 } 00607 00608 heap = new_heap; 00609 return (caddr_t) prev_heap; 00610 } 00611 #endif 00612 #endif 00613 00614 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 00615 extern "C" void _exit(int return_code) { 00616 #else 00617 namespace std { 00618 extern "C" void exit(int return_code) { 00619 #endif 00620 00621 #if DEVICE_STDIO_MESSAGES 00622 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT 00623 fflush(stdout); 00624 fflush(stderr); 00625 #endif 00626 #endif 00627 00628 #if DEVICE_SEMIHOST 00629 if (mbed_interface_connected()) { 00630 semihost_exit(); 00631 } 00632 #endif 00633 if (return_code) { 00634 mbed_die(); 00635 } 00636 00637 while (1); 00638 } 00639 00640 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR) 00641 } //namespace std 00642 #endif 00643 00644 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC) 00645 00646 // This series of function disable the registration of global destructors 00647 // in a dynamic table which will be called when the application exit. 00648 // In mbed, program never exit properly, it dies. 00649 // More informations about this topic for ARMCC here: 00650 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html 00651 extern "C" { 00652 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) { 00653 return 1; 00654 } 00655 00656 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) { 00657 return 1; 00658 } 00659 00660 void __cxa_finalize(void *handle) { 00661 } 00662 00663 } // end of extern "C" 00664 00665 #endif 00666 00667 00668 #if defined(TOOLCHAIN_GCC) 00669 00670 /* 00671 * Depending on how newlib is configured, it is often not enough to define 00672 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the 00673 * behavior regarding the registration of handlers with atexit. 00674 * 00675 * To overcome this limitation, exit and atexit are overriden here. 00676 */ 00677 extern "C"{ 00678 00679 /** 00680 * @brief Retarget of exit for GCC. 00681 * @details Unlike the standard version, this function doesn't call any function 00682 * registered with atexit before calling _exit. 00683 */ 00684 void __wrap_exit(int return_code) { 00685 _exit(return_code); 00686 } 00687 00688 /** 00689 * @brief Retarget atexit from GCC. 00690 * @details This function will always fail and never register any handler to be 00691 * called at exit. 00692 */ 00693 int __wrap_atexit(void (*func)()) { 00694 return 1; 00695 } 00696 00697 } 00698 00699 #endif 00700 00701 00702 00703 namespace mbed { 00704 00705 void mbed_set_unbuffered_stream(FILE *_file) { 00706 #if defined (__ICCARM__) 00707 char buf[2]; 00708 std::setvbuf(_file,buf,_IONBF,NULL); 00709 #else 00710 setbuf(_file, NULL); 00711 #endif 00712 } 00713 00714 int mbed_getc(FILE *_file){ 00715 #if defined (__ICCARM__) 00716 /*This is only valid for unbuffered streams*/ 00717 int res = std::fgetc(_file); 00718 if (res>=0){ 00719 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 00720 _file->_Rend = _file->_Wend; 00721 _file->_Next = _file->_Wend; 00722 } 00723 return res; 00724 #else 00725 return std::fgetc(_file); 00726 #endif 00727 } 00728 00729 char* mbed_gets(char*s, int size, FILE *_file){ 00730 #if defined (__ICCARM__) 00731 /*This is only valid for unbuffered streams*/ 00732 char *str = fgets(s,size,_file); 00733 if (str!=NULL){ 00734 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 00735 _file->_Rend = _file->_Wend; 00736 _file->_Next = _file->_Wend; 00737 } 00738 return str; 00739 #else 00740 return std::fgets(s,size,_file); 00741 #endif 00742 } 00743 00744 } // namespace mbed 00745 00746 #if defined (__ICCARM__) 00747 // Stub out locks when an rtos is not present 00748 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {} 00749 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {} 00750 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {} 00751 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {} 00752 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {} 00753 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {} 00754 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {} 00755 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {} 00756 #elif defined(__CC_ARM) 00757 // Do nothing 00758 #elif defined (__GNUC__) 00759 struct _reent; 00760 // Stub out locks when an rtos is not present 00761 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {} 00762 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {} 00763 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {} 00764 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {} 00765 00766 extern "C" void __malloc_lock( struct _reent *_r ) 00767 { 00768 __rtos_malloc_lock(_r); 00769 } 00770 00771 extern "C" void __malloc_unlock( struct _reent *_r ) 00772 { 00773 __rtos_malloc_unlock(_r); 00774 } 00775 00776 extern "C" void __env_lock( struct _reent *_r ) 00777 { 00778 __rtos_env_lock(_r); 00779 } 00780 00781 extern "C" void __env_unlock( struct _reent *_r ) 00782 { 00783 __rtos_env_unlock(_r); 00784 } 00785 00786 #define CXA_GUARD_INIT_DONE (1 << 0) 00787 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1) 00788 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS) 00789 00790 extern "C" int __cxa_guard_acquire(int *guard_object_p) 00791 { 00792 uint8_t *guard_object = (uint8_t *)guard_object_p; 00793 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 00794 return 0; 00795 } 00796 singleton_lock(); 00797 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 00798 singleton_unlock(); 00799 return 0; 00800 } 00801 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK)); 00802 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS; 00803 return 1; 00804 } 00805 00806 extern "C" void __cxa_guard_release(int *guard_object_p) 00807 { 00808 uint8_t *guard_object = (uint8_t *)guard_object_p; 00809 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 00810 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE; 00811 singleton_unlock(); 00812 } 00813 00814 extern "C" void __cxa_guard_abort(int *guard_object_p) 00815 { 00816 uint8_t *guard_object = (uint8_t *)guard_object_p; 00817 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 00818 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS; 00819 singleton_unlock(); 00820 } 00821 00822 #endif 00823 00824 void *operator new(std::size_t count) 00825 { 00826 void *buffer = malloc(count); 00827 if (NULL == buffer) { 00828 error("Operator new out of memory\r\n"); 00829 } 00830 return buffer; 00831 } 00832 00833 void *operator new[](std::size_t count) 00834 { 00835 void *buffer = malloc(count); 00836 if (NULL == buffer) { 00837 error("Operator new[] out of memory\r\n"); 00838 } 00839 return buffer; 00840 } 00841 00842 void operator delete(void *ptr) 00843 { 00844 if (ptr != NULL) { 00845 free(ptr); 00846 } 00847 } 00848 void operator delete[](void *ptr) 00849 { 00850 if (ptr != NULL) { 00851 free(ptr); 00852 } 00853 }
Generated on Tue Jul 12 2022 20:00:14 by 1.7.2