forked
Embed:
(wiki syntax)
Show/hide line numbers
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 Tue Jul 12 2022 16:02:32 by 1.7.2