forked

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