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