Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

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