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