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