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