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