Lee Shen / FTHR_USB_serial_qSPI
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_retarget.cpp Source File

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(-ENODEV, 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(-ENODEV, 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 = ENODEV;
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 = ENODEV;
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 = ENODEV;
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) {
00681         errno = ENODEV;
00682         return -1;
00683     }
00684 
00685     int err = fs->mkdir(fp.fileName(), mode);
00686     if (err < 0) {
00687         errno = -err;
00688         return -1;
00689     } else {
00690         return 0;
00691     }
00692 }
00693 
00694 extern "C" int stat(const char *path, struct stat *st) {
00695     FilePath fp(path);
00696     FileSystemHandle *fs = fp.fileSystem();
00697     if (fs == NULL) {
00698         errno = ENODEV;
00699         return -1;
00700     }
00701 
00702     int err = fs->stat(fp.fileName(), st);
00703     if (err < 0) {
00704         errno = -err;
00705         return -1;
00706     } else {
00707         return 0;
00708     }
00709 }
00710 
00711 #if defined(TOOLCHAIN_GCC)
00712 /* prevents the exception handling name demangling code getting pulled in */
00713 #include "mbed_error.h"
00714 namespace __gnu_cxx {
00715     void __verbose_terminate_handler() {
00716         error("Exception");
00717     }
00718 }
00719 extern "C" WEAK void __cxa_pure_virtual(void);
00720 extern "C" WEAK void __cxa_pure_virtual(void) {
00721     exit(1);
00722 }
00723 
00724 #endif
00725 
00726 // Provide implementation of _sbrk (low-level dynamic memory allocation
00727 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
00728 // SP.  This make it compatible with RTX RTOS thread stacks.
00729 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
00730 
00731 #if defined(TARGET_CORTEX_A)
00732 extern "C" uint32_t  __HeapLimit;
00733 #endif
00734 
00735 // Turn off the errno macro and use actual global variable instead.
00736 #undef errno
00737 extern "C" int errno;
00738 
00739 // Dynamic memory allocation related syscall.
00740 #if defined(TARGET_NUVOTON)
00741 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
00742 // __wrap__sbrk() is implemented in:
00743 // TARGET_NUMAKER_PFM_NUC472    targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c
00744 // TARGET_NUMAKER_PFM_M453      targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/m451_retarget.c
00745 extern "C" void *__wrap__sbrk(int incr);
00746 extern "C" caddr_t _sbrk(int incr) {
00747     return (caddr_t) __wrap__sbrk(incr);
00748 }
00749 #else
00750 // Linker defined symbol used by _sbrk to indicate where heap should start.
00751 extern "C" uint32_t __end__;
00752 extern "C" caddr_t _sbrk(int incr) {
00753     static unsigned char* heap = (unsigned char*)&__end__;
00754     unsigned char*        prev_heap = heap;
00755     unsigned char*        new_heap = heap + incr;
00756 
00757 #if defined(TARGET_CORTEX_A)
00758     if (new_heap >= (unsigned char*)&__HeapLimit) {     /* __HeapLimit is end of heap section */
00759 #else
00760     if (new_heap >= (unsigned char*)__get_MSP()) {
00761 #endif
00762         errno = ENOMEM;
00763         return (caddr_t)-1;
00764     }
00765 
00766     // Additional heap checking if set
00767     if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
00768         errno = ENOMEM;
00769         return (caddr_t)-1;
00770     }
00771 
00772     heap = new_heap;
00773     return (caddr_t) prev_heap;
00774 }
00775 #endif
00776 #endif
00777 
00778 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
00779 extern "C" void _exit(int return_code) {
00780 #else
00781 namespace std {
00782 extern "C" void exit(int return_code) {
00783 #endif
00784 
00785 #if DEVICE_STDIO_MESSAGES
00786 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
00787     fflush(stdout);
00788     fflush(stderr);
00789 #endif
00790 #endif
00791 
00792 #if DEVICE_SEMIHOST
00793     if (mbed_interface_connected()) {
00794         semihost_exit();
00795     }
00796 #endif
00797     if (return_code) {
00798         mbed_die();
00799     }
00800 
00801     while (1);
00802 }
00803 
00804 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
00805 } //namespace std
00806 #endif
00807 
00808 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
00809 
00810 // This series of function disable the registration of global destructors
00811 // in a dynamic table which will be called when the application exit.
00812 // In mbed, program never exit properly, it dies.
00813 // More informations about this topic for ARMCC here:
00814 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
00815 extern "C" {
00816 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) {
00817     return 1;
00818 }
00819 
00820 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) {
00821     return 1;
00822 }
00823 
00824 void __cxa_finalize(void *handle) {
00825 }
00826 
00827 } // end of extern "C"
00828 
00829 #endif
00830 
00831 
00832 #if defined(TOOLCHAIN_GCC)
00833 
00834 /*
00835  * Depending on how newlib is  configured, it is often not enough to define
00836  * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
00837  * behavior regarding the registration of handlers with atexit.
00838  *
00839  * To overcome this limitation, exit and atexit are overriden here.
00840  */
00841 extern "C"{
00842 
00843 /**
00844  * @brief Retarget of exit for GCC.
00845  * @details Unlike the standard version, this function doesn't call any function
00846  * registered with atexit before calling _exit.
00847  */
00848 void __wrap_exit(int return_code) {
00849     _exit(return_code);
00850 }
00851 
00852 /**
00853  * @brief Retarget atexit from GCC.
00854  * @details This function will always fail and never register any handler to be
00855  * called at exit.
00856  */
00857 int __wrap_atexit(void (*func)()) {
00858     return 1;
00859 }
00860 
00861 }
00862 
00863 #endif
00864 
00865 
00866 
00867 namespace mbed {
00868 
00869 void mbed_set_unbuffered_stream(std::FILE *_file) {
00870 #if defined (__ICCARM__)
00871     char buf[2];
00872     std::setvbuf(_file,buf,_IONBF,NULL);
00873 #else
00874     setbuf(_file, NULL);
00875 #endif
00876 }
00877 
00878 /* Applications are expected to use fdopen()
00879  * not this function directly. This code had to live here because FILE and FileHandle
00880  * processes are all linked together here.
00881  */
00882 std::FILE *mbed_fdopen(FileHandle *fh, const char *mode)
00883 {
00884     // This is to avoid scanf(buf, ":%.4s", fh) and the bloat it brings.
00885     char buf[1 + sizeof(fh)]; /* :(pointer) */
00886     MBED_STATIC_ASSERT(sizeof(buf) == 5, "Pointers should be 4 bytes.");
00887     buf[0] = ':';
00888     memcpy(buf + 1, &fh, sizeof(fh));
00889 
00890     std::FILE *stream = std::fopen(buf, mode);
00891     /* newlib-nano doesn't appear to ever call _isatty itself, so
00892      * happily fully buffers an interactive stream. Deal with that here.
00893      */
00894     if (stream && fh->isatty()) {
00895         mbed_set_unbuffered_stream(stream);
00896     }
00897     return stream;
00898 }
00899 
00900 int mbed_getc(std::FILE *_file){
00901 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
00902     /*This is only valid for unbuffered streams*/
00903     int res = std::fgetc(_file);
00904     if (res>=0){
00905         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
00906         _file->_Rend = _file->_Wend;
00907         _file->_Next = _file->_Wend;
00908     }
00909     return res;
00910 #else
00911     return std::fgetc(_file);
00912 #endif
00913 }
00914 
00915 char* mbed_gets(char*s, int size, std::FILE *_file){
00916 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
00917     /*This is only valid for unbuffered streams*/
00918     char *str = fgets(s,size,_file);
00919     if (str!=NULL){
00920         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
00921         _file->_Rend = _file->_Wend;
00922         _file->_Next = _file->_Wend;
00923     }
00924     return str;
00925 #else
00926     return std::fgets(s,size,_file);
00927 #endif
00928 }
00929 
00930 } // namespace mbed
00931 
00932 #if defined (__ICCARM__)
00933 // Stub out locks when an rtos is not present
00934 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
00935 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
00936 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
00937 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
00938 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
00939 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
00940 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
00941 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
00942 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
00943 extern "C" WEAK void *__aeabi_read_tp (void) { return NULL ;}
00944 #endif
00945 #elif defined(__CC_ARM)
00946 // Do nothing
00947 #elif defined (__GNUC__)
00948 struct _reent;
00949 // Stub out locks when an rtos is not present
00950 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {}
00951 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {}
00952 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {}
00953 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {}
00954 
00955 extern "C" void __malloc_lock( struct _reent *_r )
00956 {
00957     __rtos_malloc_lock(_r);
00958 }
00959 
00960 extern "C" void __malloc_unlock( struct _reent *_r )
00961 {
00962     __rtos_malloc_unlock(_r);
00963 }
00964 
00965 extern "C" void __env_lock( struct _reent *_r )
00966 {
00967     __rtos_env_lock(_r);
00968 }
00969 
00970 extern "C" void __env_unlock( struct _reent *_r )
00971 {
00972     __rtos_env_unlock(_r);
00973 }
00974 
00975 #define CXA_GUARD_INIT_DONE             (1 << 0)
00976 #define CXA_GUARD_INIT_IN_PROGRESS      (1 << 1)
00977 #define CXA_GUARD_MASK                  (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
00978 
00979 extern "C" int __cxa_guard_acquire(int *guard_object_p)
00980 {
00981     uint8_t *guard_object = (uint8_t *)guard_object_p;
00982     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
00983         return 0;
00984     }
00985     singleton_lock();
00986     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
00987         singleton_unlock();
00988         return 0;
00989     }
00990     MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
00991     *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
00992     return 1;
00993 }
00994 
00995 extern "C" void __cxa_guard_release(int *guard_object_p)
00996 {
00997     uint8_t *guard_object = (uint8_t *)guard_object_p;
00998     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
00999     *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
01000     singleton_unlock();
01001 }
01002 
01003 extern "C" void __cxa_guard_abort(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_INIT_IN_PROGRESS;
01008     singleton_unlock();
01009 }
01010 
01011 #endif
01012 
01013 void *operator new(std::size_t count)
01014 {
01015     void *buffer = malloc(count);
01016     if (NULL == buffer) {
01017         error("Operator new out of memory\r\n");
01018     }
01019     return buffer;
01020 }
01021 
01022 void *operator new[](std::size_t count)
01023 {
01024     void *buffer = malloc(count);
01025     if (NULL == buffer) {
01026         error("Operator new[] out of memory\r\n");
01027     }
01028     return buffer;
01029 }
01030 
01031 void *operator new(std::size_t count, const std::nothrow_t& tag)
01032 {
01033     return malloc(count);
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 delete(void *ptr)
01042 {
01043     if (ptr != NULL) {
01044         free(ptr);
01045     }
01046 }
01047 void operator delete[](void *ptr)
01048 {
01049     if (ptr != NULL) {
01050         free(ptr);
01051     }
01052 }
01053 
01054 /* @brief   standard c library clock() function.
01055  *
01056  * This function returns the number of clock ticks elapsed since the start of the program.
01057  *
01058  * @note Synchronization level: Thread safe
01059  *
01060  * @return
01061  *  the number of clock ticks elapsed since the start of the program.
01062  *
01063  * */
01064 extern "C" clock_t clock()
01065 {
01066     _mutex->lock();
01067     clock_t t = ticker_read(get_us_ticker_data());
01068     t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time
01069     _mutex->unlock();
01070     return t;
01071 }