Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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/mbed_poll.h"
00030 #include "platform/PlatformMutex.h"
00031 #include "drivers/UARTSerial.h"
00032 #include "us_ticker_api.h"
00033 #include "lp_ticker_api.h"
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <limits.h>
00037 #ifndef SSIZE_MAX
00038 #define SSIZE_MAX INT_MAX
00039 #endif
00040 #include <stdio.h>
00041 #include <errno.h>
00042 #include "platform/mbed_retarget.h"
00043 
00044 static SingletonPtr<PlatformMutex>  _mutex;
00045 
00046 #if defined(__ARMCC_VERSION)
00047 #   if __ARMCC_VERSION >= 6010050
00048 #      include <arm_compat.h>
00049 #   endif
00050 #   include <rt_sys.h>
00051 #   include <rt_misc.h>
00052 #   include <stdint.h>
00053 #   define PREFIX(x)    _sys##x
00054 #   define OPEN_MAX     _SYS_OPEN
00055 #   ifdef __MICROLIB
00056 #       pragma import(__use_full_stdio)
00057 #   endif
00058 
00059 #elif defined(__ICCARM__)
00060 #   include <yfuns.h>
00061 #   define PREFIX(x)        _##x
00062 #   define OPEN_MAX         16
00063 
00064 #   define STDIN_FILENO     0
00065 #   define STDOUT_FILENO    1
00066 #   define STDERR_FILENO    2
00067 
00068 #else
00069 #   include <sys/syslimits.h>
00070 #   define PREFIX(x)    x
00071 #endif
00072 
00073 #define FILE_HANDLE_RESERVED    ((FileHandle*)0xFFFFFFFF)
00074 
00075 using namespace mbed;
00076 
00077 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
00078 // Before version 5.03, we were using a patched version of microlib with proper names
00079 extern const char __stdin_name[]  = ":tt";
00080 extern const char __stdout_name[] = ":tt";
00081 extern const char __stderr_name[] = ":tt";
00082 
00083 #else
00084 extern const char __stdin_name[]  = "/stdin";
00085 extern const char __stdout_name[] = "/stdout";
00086 extern const char __stderr_name[] = "/stderr";
00087 #endif
00088 
00089 unsigned char *mbed_heap_start = 0;
00090 uint32_t mbed_heap_size = 0;
00091 
00092 /* newlib has the filehandle field in the FILE struct as a short, so
00093  * we can't just return a Filehandle* from _open and instead have to
00094  * put it in a filehandles array and return the index into that array
00095  */
00096 static FileHandle *filehandles[OPEN_MAX] = { FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED };
00097 static char stdio_in_prev[OPEN_MAX];
00098 static char stdio_out_prev[OPEN_MAX];
00099 static SingletonPtr<PlatformMutex>  filehandle_mutex;
00100 
00101 namespace mbed {
00102 void mbed_set_unbuffered_stream(std::FILE *_file);
00103 
00104 void remove_filehandle(FileHandle *file) {
00105     filehandle_mutex->lock();
00106     /* Remove all open filehandles for this */
00107     for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
00108         if (filehandles[fh_i] == file) {
00109             filehandles[fh_i] = NULL;
00110         }
00111     }
00112     filehandle_mutex->unlock();
00113 }
00114 }
00115 
00116 #if DEVICE_SERIAL
00117 extern int stdio_uart_inited;
00118 extern serial_t stdio_uart;
00119 #endif
00120 
00121 /* Private FileHandle to implement backwards-compatible functionality of
00122  * direct HAL serial access for default stdin/stdout/stderr.
00123  * This is not a particularly well-behaved FileHandle for a stream, which
00124  * is why it's not public. People should be using UARTSerial.
00125  */
00126 class DirectSerial : public FileHandle {
00127 public:
00128     DirectSerial(PinName tx, PinName rx, int baud);
00129     virtual ssize_t write(const void *buffer, size_t size);
00130     virtual ssize_t read(void *buffer, size_t size);
00131     virtual off_t seek(off_t offset, int whence = SEEK_SET) {
00132         return -ESPIPE;
00133     }
00134     virtual off_t size() {
00135         return -EINVAL;
00136     }
00137     virtual int isatty() {
00138         return true;
00139     }
00140     virtual int close() {
00141         return 0;
00142     }
00143     virtual short poll(short events) const;
00144 };
00145 
00146 DirectSerial::DirectSerial(PinName tx, PinName rx, int baud) {
00147     if (stdio_uart_inited) return;
00148     serial_init(&stdio_uart, tx, rx);
00149     serial_baud(&stdio_uart, baud);
00150 }
00151 
00152 ssize_t DirectSerial::write(const void *buffer, size_t size) {
00153     const unsigned char *buf = static_cast<const unsigned char *>(buffer);
00154     for (size_t i = 0; i < size; i++) {
00155         serial_putc(&stdio_uart, buf[i]);
00156     }
00157     return size;
00158 }
00159 
00160 ssize_t DirectSerial::read(void *buffer, size_t size) {
00161     unsigned char *buf = static_cast<unsigned char *>(buffer);
00162     if (size == 0) {
00163         return 0;
00164     }
00165     buf[0] = serial_getc(&stdio_uart);
00166     return 1;
00167 }
00168 
00169 short DirectSerial::poll(short events) const {
00170     short revents = 0;
00171     if ((events & POLLIN) && serial_readable(&stdio_uart)) {
00172         revents |= POLLIN;
00173     }
00174     if ((events & POLLOUT) && serial_writable(&stdio_uart)) {
00175         revents |= POLLOUT;
00176     }
00177     return revents;
00178 }
00179 
00180 class Sink : public FileHandle {
00181 public:
00182     virtual ssize_t write(const void *buffer, size_t size);
00183     virtual ssize_t read(void *buffer, size_t size);
00184     virtual off_t seek(off_t offset, int whence = SEEK_SET) { return ESPIPE; }
00185     virtual off_t size() { return -EINVAL; }
00186     virtual int isatty() { return true; }
00187     virtual int close() { return 0; }
00188 };
00189 
00190 ssize_t Sink::write(const void *buffer, size_t size) {
00191     // Just swallow the data - this is historical non-DEVICE_SERIAL behaviour
00192     return size;
00193 }
00194 
00195 ssize_t Sink::read(void *buffer, size_t size) {
00196     // Produce 1 zero byte - historical behaviour returned 1 without touching
00197     // the buffer
00198     unsigned char *buf = static_cast<unsigned char *>(buffer);
00199     buf[0] = 0;
00200     return 1;
00201 }
00202 
00203 
00204 MBED_WEAK FileHandle* mbed::mbed_target_override_console(int fd)
00205 {
00206     return NULL;
00207 }
00208 
00209 MBED_WEAK FileHandle* mbed::mbed_override_console(int fd)
00210 {
00211     return NULL;
00212 }
00213 
00214 static FileHandle* default_console()
00215 {
00216 #if DEVICE_SERIAL
00217 #  if MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL
00218     static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
00219 #  else
00220     static DirectSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
00221 #  endif
00222 #else // DEVICE_SERIAL
00223     static Sink console;
00224 #endif
00225     return &console;
00226 }
00227 
00228 /* Locate the default console for stdout, stdin, stderr */
00229 static FileHandle* get_console(int fd) {
00230     FileHandle *fh = mbed_override_console(fd);
00231     if (fh) {
00232         return fh;
00233     }
00234     fh = mbed_target_override_console(fd);
00235     if (fh) {
00236         return fh;
00237     }
00238     return default_console();
00239 }
00240 
00241 /* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
00242 static FileHandle* get_fhc(int fd) {
00243     if (fd >= OPEN_MAX) {
00244         return NULL;
00245     }
00246     FileHandle *fh = filehandles[fd];
00247     if (fh == FILE_HANDLE_RESERVED && fd < 3) {
00248         filehandles[fd] = fh = get_console(fd);
00249     }
00250     return fh;
00251 }
00252 
00253 /**
00254  * Sets errno when file opening fails.
00255  * Wipes out the filehandle too.
00256  *
00257  * @param error is a negative error code returned from an mbed function and
00258  *              will be negated to store a positive error code in errno
00259  */
00260 static int handle_open_errors(int error, unsigned filehandle_idx) {
00261     errno = -error;
00262     // Free file handle
00263     filehandles[filehandle_idx] = NULL;
00264     return -1;
00265 }
00266 
00267 static inline int openflags_to_posix(int openflags) {
00268     int posix = openflags;
00269 #ifdef __ARMCC_VERSION
00270     if (openflags & OPEN_PLUS) {
00271         posix = O_RDWR;
00272     } else if(openflags & OPEN_W) {
00273         posix = O_WRONLY;
00274     } else if(openflags & OPEN_A) {
00275         posix = O_WRONLY|O_APPEND;
00276     } else {
00277         posix = O_RDONLY;
00278     }
00279     /* a, w, a+, w+ all create if file does not already exist */
00280     if (openflags & (OPEN_A|OPEN_W)) {
00281         posix |= O_CREAT;
00282     }
00283     /* w and w+ truncate */
00284     if (openflags & OPEN_W) {
00285         posix |= O_TRUNC;
00286     }
00287 #elif defined(__ICCARM__)
00288     switch (openflags & _LLIO_RDWRMASK) {
00289         case _LLIO_RDONLY: posix = O_RDONLY; break;
00290         case _LLIO_WRONLY: posix = O_WRONLY; break;
00291         case _LLIO_RDWR  : posix = O_RDWR  ; break;
00292     }
00293     if (openflags & _LLIO_CREAT ) posix |= O_CREAT;
00294     if (openflags & _LLIO_APPEND) posix |= O_APPEND;
00295     if (openflags & _LLIO_TRUNC ) posix |= O_TRUNC;
00296 #elif defined(TOOLCHAIN_GCC)
00297     posix &= ~O_BINARY;
00298 #endif
00299     return posix;
00300 }
00301 
00302 static int reserve_filehandle() {
00303     // find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr
00304     filehandle_mutex->lock();
00305     int fh_i;
00306     for (fh_i = 3; fh_i < OPEN_MAX; fh_i++) {
00307         /* Take a next free filehandle slot available. */
00308         if (filehandles[fh_i] == NULL) break;
00309     }
00310     if (fh_i >= OPEN_MAX) {
00311         /* Too many file handles have been opened */
00312         errno = EMFILE;
00313         filehandle_mutex->unlock();
00314         return -1;
00315     }
00316     filehandles[fh_i] = FILE_HANDLE_RESERVED;
00317     filehandle_mutex->unlock();
00318 
00319     return fh_i;
00320 }
00321 
00322 int mbed::bind_to_fd(FileHandle *fh) {
00323     int fh_i = reserve_filehandle();
00324     if (fh_i < 0) {
00325         return fh_i;
00326     }
00327 
00328     filehandles[fh_i] = fh;
00329     stdio_in_prev[fh_i] = 0;
00330     stdio_out_prev[fh_i] = 0;
00331 
00332     return fh_i;
00333 }
00334 
00335 static int unbind_from_fd(int fd, FileHandle *fh) {
00336     if (filehandles[fd] == fh) {
00337         filehandles[fd] = NULL;
00338         return 0;
00339     } else {
00340         errno = EBADF;
00341         return -1;
00342     }
00343 }
00344 
00345 #ifndef __IAR_SYSTEMS_ICC__
00346 /* IAR provides fdopen itself */
00347 extern "C" std::FILE* fdopen(int fildes, const char *mode)
00348 {
00349     // This is to avoid scanf and the bloat it brings.
00350     char buf[1 + sizeof fildes]; /* @(integer) */
00351     MBED_STATIC_ASSERT(sizeof buf == 5, "Integers should be 4 bytes.");
00352     buf[0] = '@';
00353     memcpy(buf + 1, &fildes, sizeof fildes);
00354 
00355     std::FILE *stream = std::fopen(buf, mode);
00356     /* newlib-nano doesn't appear to ever call _isatty itself, so
00357      * happily fully buffers an interactive stream. Deal with that here.
00358      */
00359     if (stream && isatty(fildes)) {
00360         mbed_set_unbuffered_stream(stream);
00361     }
00362     return stream;
00363 }
00364 #endif
00365 
00366 namespace mbed {
00367 std::FILE *fdopen(FileHandle *fh, const char *mode)
00368 {
00369     // First reserve the integer file descriptor
00370     int fd = bind_to_fd(fh);
00371     if (!fd) {
00372         return NULL;
00373     }
00374     // Then bind that to the C stream. If successful, C library
00375     // takes ownership and responsibility to close.
00376     std::FILE *stream = ::fdopen(fd, mode);
00377     if (!stream) {
00378         unbind_from_fd(fd, fh);
00379     }
00380     return stream;
00381 }
00382 }
00383 
00384 /* @brief   standard c library fopen() retargeting function.
00385  *
00386  * This function is invoked by the standard c library retargeting to handle fopen()
00387  *
00388  * @return
00389  *  On success, a valid FILEHANDLE is returned.
00390  *  On failure, -1 is returned and errno is set to an appropriate value e.g.
00391  *   ENOENT     file not found (default errno setting)
00392  *   EMFILE     the maximum number of open files was exceeded.
00393  *
00394  * */
00395 extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags) {
00396 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
00397 #if !defined(MBED_CONF_RTOS_PRESENT)
00398     // valid only for mbed 2
00399     // for ulib, this is invoked after RAM init, prior c++
00400     // used as hook, as post stack/heap is not active there
00401     extern void mbed_copy_nvic(void);
00402     extern void mbed_sdk_init(void);
00403 
00404     static int mbed_sdk_inited = 0;
00405     if (!mbed_sdk_inited) {
00406         mbed_copy_nvic();
00407         mbed_sdk_init();
00408         mbed_sdk_inited = 1;
00409     }
00410 #endif
00411     // Before version 5.03, we were using a patched version of microlib with proper names
00412     // This is the workaround that the microlib author suggested us
00413     static int n = 0;
00414     if (std::strcmp(name, ":tt") == 0 && n < 3) {
00415         return n++;
00416     }
00417 #else
00418     /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
00419      */
00420     if (std::strcmp(name, __stdin_name) == 0) {
00421         get_fhc(STDIN_FILENO);
00422         return STDIN_FILENO;
00423     } else if (std::strcmp(name, __stdout_name) == 0) {
00424         get_fhc(STDOUT_FILENO);
00425         return STDOUT_FILENO;
00426     } else if (std::strcmp(name, __stderr_name) == 0) {
00427         get_fhc(STDERR_FILENO);
00428         return STDERR_FILENO;
00429     }
00430 #endif
00431 #ifndef __IAR_SYSTEMS_ICC__
00432     /* FILENAME: "@(integer)" gives an already-allocated descriptor */
00433     if (name[0] == '@') {
00434         int fd;
00435         memcpy(&fd, name + 1, sizeof fd);
00436         return fd;
00437     }
00438 #endif
00439     return open(name, openflags_to_posix(openflags));
00440 }
00441 
00442 extern "C" int open(const char *name, int oflag, ...) {
00443     int fh_i = reserve_filehandle();
00444     if (fh_i < 0) {
00445         return fh_i;
00446     }
00447 
00448     FileHandle *res = NULL;
00449     FilePath path(name);
00450 
00451     if (!path.exists()) {
00452         /* The first part of the filename (between first 2 '/') is not a
00453          * registered mount point in the namespace.
00454          */
00455         return handle_open_errors(-ENODEV, fh_i);
00456     }
00457 
00458     if (path.isFile()) {
00459         res = path.file();
00460     } else {
00461         FileSystemHandle *fs = path.fileSystem();
00462         if (fs == NULL) {
00463             return handle_open_errors(-ENODEV, fh_i);
00464         }
00465         int err = fs->open(&res, path.fileName(), oflag);
00466         if (err) {
00467             return handle_open_errors(err, fh_i);
00468         }
00469     }
00470 
00471     filehandles[fh_i] = res;
00472     stdio_in_prev[fh_i] = 0;
00473     stdio_out_prev[fh_i] = 0;
00474 
00475     return fh_i;
00476 }
00477 
00478 extern "C" int PREFIX(_close)(FILEHANDLE fh) {
00479     return close(fh);
00480 }
00481 
00482 extern "C" int close(int fh) {
00483     FileHandle* fhc = get_fhc(fh);
00484     filehandles[fh] = NULL;
00485     if (fhc == NULL) {
00486         errno = EBADF;
00487         return -1;
00488     }
00489 
00490     int err = fhc->close();
00491     if (err < 0) {
00492         errno = -err;
00493         return -1;
00494     } else {
00495         return 0;
00496     }
00497 }
00498 
00499 static bool convert_crlf(int fd) {
00500 #if MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
00501     return isatty(fd);
00502 #elif MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
00503     return fd < 3 && isatty(fd);
00504 #else
00505     return false;
00506 #endif
00507 }
00508 
00509 #if defined(__ICCARM__)
00510 extern "C" size_t    __write (int        fh, const unsigned char *buffer, size_t length) {
00511 #else
00512 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) {
00513 #endif
00514 
00515 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
00516     if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
00517         error("Error - writing to a file in an ISR or critical section\r\n");
00518     }
00519 #endif
00520 
00521     if (length > SSIZE_MAX) {
00522         errno = EINVAL;
00523         return -1;
00524     }
00525 
00526     ssize_t slength = length;
00527     ssize_t written = 0;
00528 
00529     if (convert_crlf(fh)) {
00530         // local prev is previous in buffer during seek
00531         // stdio_out_prev[fh] is last thing actually written
00532         char prev = stdio_out_prev[fh];
00533         // Seek for '\n' without preceding '\r'; if found flush
00534         // preceding and insert '\r'. Continue until end of input.
00535         for (ssize_t cur = 0; cur < slength; cur++) {
00536             if (buffer[cur] == '\n' && prev != '\r') {
00537                 ssize_t r;
00538                 // flush stuff preceding the \n
00539                 if (cur > written) {
00540                     r = write(fh, buffer + written, cur - written);
00541                     if (r < 0) {
00542                         return -1;
00543                     }
00544                     written += r;
00545                     if (written < cur) {
00546                         // For some reason, didn't write all - give up now
00547                         goto finish;
00548                     }
00549                     stdio_out_prev[fh] = prev;
00550                 }
00551                 // insert a \r now, leaving the \n still to be written
00552                 r = write(fh, "\r", 1);
00553                 if (r < 0) {
00554                     return -1;
00555                 }
00556                 if (r < 1) {
00557                     goto finish;
00558                 }
00559                 stdio_out_prev[fh] = '\r';
00560             }
00561             prev = buffer[cur];
00562         }
00563     }
00564 
00565     // Flush remaining from conversion, or the whole thing if no conversion
00566     if (written < slength) {
00567         ssize_t r = write(fh, buffer + written, slength - written);
00568         if (r < 0) {
00569             return -1;
00570         }
00571         written += r;
00572         if (written > 0) {
00573             stdio_out_prev[fh] = buffer[written - 1];
00574         }
00575     }
00576 
00577 finish:
00578 #ifdef __ARMCC_VERSION
00579     if (written >= 0) {
00580         return slength - written;
00581     } else {
00582         return written;
00583     }
00584 #else
00585     return written;
00586 #endif
00587 }
00588 
00589 extern "C" ssize_t write(int fh, const void *buf, size_t length) {
00590 
00591     FileHandle* fhc = get_fhc(fh);
00592     if (fhc == NULL) {
00593         errno = EBADF;
00594         return -1;
00595     }
00596 
00597     ssize_t ret = fhc->write(buf, length);
00598     if (ret < 0) {
00599         errno = -ret;
00600         return -1;
00601     } else {
00602         return ret;
00603     }
00604 }
00605 
00606 #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
00607 extern "C" void PREFIX(_exit)(int return_code) {
00608     while(1) {}
00609 }
00610 
00611 extern "C" void _ttywrch(int ch) {
00612     char c = ch;
00613     write(STDOUT_FILENO, &c, 1);
00614 }
00615 #endif
00616 
00617 #if defined(__ICCARM__)
00618 extern "C" size_t    __read (int        fh, unsigned char *buffer, size_t       length) {
00619 #else
00620 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) {
00621 #endif
00622 
00623 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
00624     if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
00625         error("Error - reading from a file in an ISR or critical section\r\n");
00626     }
00627 #endif
00628 
00629     if (length > SSIZE_MAX) {
00630         errno = EINVAL;
00631         return -1;
00632     }
00633 
00634     ssize_t bytes_read = 0;
00635 
00636     if (convert_crlf(fh)) {
00637         while (true) {
00638             char c;
00639             ssize_t r = read(fh, &c, 1);
00640             if (r < 0) {
00641                 return -1;
00642             }
00643             if (r == 0) {
00644                 return bytes_read;
00645             }
00646             if ((c == '\r' && stdio_in_prev[fh] != '\n') ||
00647                 (c == '\n' && stdio_in_prev[fh] != '\r')) {
00648                 stdio_in_prev[fh] = c;
00649                 *buffer = '\n';
00650                 break;
00651             } else if ((c == '\r' && stdio_in_prev[fh] == '\n') ||
00652                        (c == '\n' && stdio_in_prev[fh] == '\r')) {
00653                 stdio_in_prev[fh] = c;
00654                 continue;
00655             } else {
00656                 stdio_in_prev[fh] = c;
00657                 *buffer = c;
00658                 break;
00659             }
00660         }
00661         bytes_read = 1;
00662     } else {
00663         bytes_read = read(fh, buffer, length);
00664     }
00665 
00666 #ifdef __ARMCC_VERSION
00667     if (bytes_read < 0) {
00668         return -1;
00669     } else if (bytes_read == 0) {
00670         return 0x80000000 | length; // weird EOF indication
00671     } else {
00672         return (ssize_t)length - bytes_read;
00673     }
00674 #else
00675     return bytes_read;
00676 #endif
00677 }
00678 
00679 extern "C" ssize_t read(int fh, void *buf, size_t length) {
00680 
00681     FileHandle* fhc = get_fhc(fh);
00682     if (fhc == NULL) {
00683         errno = EBADF;
00684         return -1;
00685     }
00686 
00687     ssize_t ret = fhc->read(buf, length);
00688     if (ret < 0) {
00689         errno = -ret;
00690         return -1;
00691     } else {
00692         return ret;
00693     }
00694 }
00695 
00696 
00697 #ifdef __ARMCC_VERSION
00698 extern "C" int PREFIX(_istty)(FILEHANDLE fh)
00699 #else
00700 extern "C" int _isatty(FILEHANDLE fh)
00701 #endif
00702 {
00703     return isatty(fh);
00704 }
00705 
00706 extern "C" int isatty(int fh) {
00707     FileHandle* fhc = get_fhc(fh);
00708     if (fhc == NULL) {
00709         errno = EBADF;
00710         return 0;
00711     }
00712 
00713     int tty = fhc->isatty();
00714     if (tty < 0) {
00715         errno = -tty;
00716         return 0;
00717     } else {
00718         return tty;
00719     }
00720 }
00721 
00722 extern "C"
00723 #if defined(__ARMCC_VERSION)
00724 int _sys_seek(FILEHANDLE fh, long offset)
00725 #elif defined(__ICCARM__)
00726 long __lseek(int fh, long offset, int whence)
00727 #else
00728 int _lseek(FILEHANDLE fh, int offset, int whence)
00729 #endif
00730 {
00731 #if defined(__ARMCC_VERSION)
00732     int whence = SEEK_SET;
00733 #endif
00734 
00735     off_t off = lseek(fh, offset, whence);
00736     // Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference
00737     if (off > INT_MAX) {
00738         errno = EOVERFLOW;
00739         return -1;
00740     }
00741     return off;
00742 }
00743 
00744 extern "C" off_t lseek(int fh, off_t offset, int whence) {
00745     FileHandle* fhc = get_fhc(fh);
00746     if (fhc == NULL) {
00747         errno = EBADF;
00748         return -1;
00749     }
00750 
00751     off_t off = fhc->seek(offset, whence);
00752     if (off < 0) {
00753         errno = -off;
00754         return -1;
00755     }
00756     return off;
00757 }
00758 
00759 #ifdef __ARMCC_VERSION
00760 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) {
00761     return fsync(fh);
00762 }
00763 #endif
00764 
00765 extern "C" int fsync(int fh) {
00766     FileHandle* fhc = get_fhc(fh);
00767     if (fhc == NULL) {
00768         errno = EBADF;
00769         return -1;
00770     }
00771 
00772     int err = fhc->sync();
00773     if (err < 0) {
00774         errno = -err;
00775         return -1;
00776     } else {
00777         return 0;
00778     }
00779 }
00780 
00781 #ifdef __ARMCC_VERSION
00782 extern "C" long PREFIX(_flen)(FILEHANDLE fh) {
00783     FileHandle* fhc = get_fhc(fh);
00784     if (fhc == NULL) {
00785         errno = EBADF;
00786         return -1;
00787     }
00788 
00789     off_t size = fhc->size();
00790     if (size < 0) {
00791         errno = -size;
00792         return -1;
00793     }
00794     if (size > LONG_MAX) {
00795         errno = EOVERFLOW;
00796         return -1;
00797     }
00798     return size;
00799 }
00800 
00801 extern "C" char Image$$RW_IRAM1$$ZI$$Limit[];
00802 
00803 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)
00804 {
00805     uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
00806     uint32_t sp_limit = __current_sp();
00807 
00808     zi_limit = (zi_limit + 7) & ~0x7;    // ensure zi_limit is 8-byte aligned
00809 
00810     struct __initial_stackheap r;
00811     r.heap_base = zi_limit;
00812     r.heap_limit = sp_limit;
00813     return r;
00814 }
00815 
00816 extern "C" __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
00817     return _mbed_user_setup_stackheap(R0, R1, R2, R3);
00818 }
00819 
00820 #endif
00821 
00822 
00823 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
00824 extern "C" int _fstat(int fh, struct stat *st) {
00825     return fstat(fh, st);
00826 }
00827 #endif
00828 
00829 extern "C" int fstat(int fh, struct stat *st) {
00830     FileHandle* fhc = get_fhc(fh);
00831     if (fhc == NULL) {
00832         errno = EBADF;
00833         return -1;
00834     }
00835 
00836     st->st_mode = fhc->isatty() ? S_IFCHR : S_IFREG;
00837     st->st_size = fhc->size();
00838     return 0;
00839 }
00840 
00841 extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
00842 {
00843     if (nfds > OPEN_MAX) {
00844         errno = EINVAL;
00845         return -1;
00846     }
00847 
00848     struct mbed::pollfh fhs[OPEN_MAX];
00849     for (nfds_t n = 0; n < nfds; n++) {
00850         // Underlying FileHandle poll returns POLLNVAL if given NULL, so
00851         // we don't need to take special action.
00852         fhs[n].fh = get_fhc(fds[n].fd);
00853         fhs[n].events = fds[n].events;
00854     }
00855     int ret = poll(fhs, nfds, timeout);
00856     for (nfds_t n = 0; n < nfds; n++) {
00857         fds[n].revents = fhs[n].revents;
00858     }
00859     return ret;
00860 }
00861 
00862 namespace std {
00863 extern "C" int remove(const char *path) {
00864     FilePath fp(path);
00865     FileSystemHandle *fs = fp.fileSystem();
00866     if (fs == NULL) {
00867         errno = ENODEV;
00868         return -1;
00869     }
00870 
00871     int err = fs->remove(fp.fileName());
00872     if (err < 0) {
00873         errno = -err;
00874         return -1;
00875     } else {
00876         return 0;
00877     }
00878 }
00879 
00880 extern "C" int rename(const char *oldname, const char *newname) {
00881     FilePath fpOld(oldname);
00882     FilePath fpNew(newname);
00883     FileSystemHandle *fsOld = fpOld.fileSystem();
00884     FileSystemHandle *fsNew = fpNew.fileSystem();
00885 
00886     if (fsOld == NULL) {
00887         errno = ENODEV;
00888         return -1;
00889     }
00890 
00891     /* rename only if both files are on the same FS */
00892     if (fsOld != fsNew) {
00893         errno = EXDEV;
00894         return -1;
00895     }
00896 
00897     int err = fsOld->rename(fpOld.fileName(), fpNew.fileName());
00898     if (err < 0) {
00899         errno = -err;
00900         return -1;
00901     } else {
00902         return 0;
00903     }
00904 }
00905 
00906 extern "C" char *tmpnam(char *s) {
00907     errno = EBADF;
00908     return NULL;
00909 }
00910 
00911 extern "C" FILE *tmpfile() {
00912     errno = EBADF;
00913     return NULL;
00914 }
00915 } // namespace std
00916 
00917 #ifdef __ARMCC_VERSION
00918 extern "C" char *_sys_command_string(char *cmd, int len) {
00919     return NULL;
00920 }
00921 #endif
00922 
00923 extern "C" DIR *opendir(const char *path) {
00924     FilePath fp(path);
00925     FileSystemHandle* fs = fp.fileSystem();
00926     if (fs == NULL) {
00927         errno = ENODEV;
00928         return NULL;
00929     }
00930 
00931     DirHandle *dir;
00932     int err = fs->open(&dir, fp.fileName());
00933     if (err < 0) {
00934         errno = -err;
00935         return NULL;
00936     }
00937 
00938     return dir;
00939 }
00940 
00941 extern "C" struct dirent *readdir(DIR *dir) {
00942     static struct dirent ent;
00943     int err = dir->read(&ent);
00944     if (err < 1) {
00945         if (err < 0) {
00946             errno = -err;
00947         }
00948         return NULL;
00949     }
00950 
00951     return &ent;
00952 }
00953 
00954 extern "C" int closedir(DIR *dir) {
00955     int err = dir->close();
00956     if (err < 0) {
00957         errno = -err;
00958         return -1;
00959     } else {
00960         return 0;
00961     }
00962 }
00963 
00964 extern "C" void rewinddir(DIR *dir) {
00965     dir->rewind();
00966 }
00967 
00968 extern "C" off_t telldir(DIR *dir) {
00969     return dir->tell();
00970 }
00971 
00972 extern "C" void seekdir(DIR *dir, off_t off) {
00973     dir->seek(off);
00974 }
00975 
00976 extern "C" int mkdir(const char *path, mode_t mode) {
00977     FilePath fp(path);
00978     FileSystemHandle *fs = fp.fileSystem();
00979     if (fs == NULL) {
00980         errno = ENODEV;
00981         return -1;
00982     }
00983 
00984     int err = fs->mkdir(fp.fileName(), mode);
00985     if (err < 0) {
00986         errno = -err;
00987         return -1;
00988     } else {
00989         return 0;
00990     }
00991 }
00992 
00993 extern "C" int stat(const char *path, struct stat *st) {
00994     FilePath fp(path);
00995     FileSystemHandle *fs = fp.fileSystem();
00996     if (fs == NULL) {
00997         errno = ENODEV;
00998         return -1;
00999     }
01000 
01001     int err = fs->stat(fp.fileName(), st);
01002     if (err < 0) {
01003         errno = -err;
01004         return -1;
01005     } else {
01006         return 0;
01007     }
01008 }
01009 
01010 extern "C" int statvfs(const char *path, struct statvfs *buf) {
01011     FilePath fp(path);
01012     FileSystemHandle *fs = fp.fileSystem();
01013     if (fs == NULL) {
01014         errno = ENODEV;
01015         return -1;
01016     }
01017 
01018     int err = fs->statvfs(fp.fileName(), buf);
01019     if (err < 0) {
01020         errno = -err;
01021         return -1;
01022     } else {
01023         return 0;
01024     }
01025 }
01026 
01027 #if defined(TOOLCHAIN_GCC)
01028 /* prevents the exception handling name demangling code getting pulled in */
01029 #include "mbed_error.h"
01030 namespace __gnu_cxx {
01031     void __verbose_terminate_handler() {
01032         error("Exception");
01033     }
01034 }
01035 extern "C" WEAK void __cxa_pure_virtual(void);
01036 extern "C" WEAK void __cxa_pure_virtual(void) {
01037     exit(1);
01038 }
01039 
01040 #endif
01041 
01042 // Provide implementation of _sbrk (low-level dynamic memory allocation
01043 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
01044 // SP.  This make it compatible with RTX RTOS thread stacks.
01045 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
01046 
01047 #if defined(TARGET_CORTEX_A)
01048 extern "C" uint32_t  __HeapLimit;
01049 #endif
01050 
01051 // Turn off the errno macro and use actual global variable instead.
01052 #undef errno
01053 extern "C" int errno;
01054 
01055 // Dynamic memory allocation related syscall.
01056 #if (defined(TARGET_NUVOTON) || defined(TWO_RAM_REGIONS))
01057 
01058 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
01059 // __wrap__sbrk() is implemented in:
01060 // TARGET_NUMAKER_PFM_NUC472    targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c
01061 // TARGET_NUMAKER_PFM_M453      targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/m451_retarget.c
01062 // TARGET_STM32L4               targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L4/l4_retarget.c
01063 extern "C" void *__wrap__sbrk(int incr);
01064 extern "C" caddr_t _sbrk(int incr) {
01065     return (caddr_t) __wrap__sbrk(incr);
01066 }
01067 #else
01068 // Linker defined symbol used by _sbrk to indicate where heap should start.
01069 extern "C" uint32_t __end__;
01070 // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory.
01071 extern "C" WEAK caddr_t _sbrk(int incr) {
01072     static unsigned char* heap = (unsigned char*)&__end__;
01073     unsigned char*        prev_heap = heap;
01074     unsigned char*        new_heap = heap + incr;
01075 
01076 #if defined(TARGET_CORTEX_A)
01077     if (new_heap >= (unsigned char*)&__HeapLimit) {     /* __HeapLimit is end of heap section */
01078 #else
01079     if (new_heap >= (unsigned char*)__get_MSP()) {
01080 #endif
01081         errno = ENOMEM;
01082         return (caddr_t)-1;
01083     }
01084 
01085     // Additional heap checking if set
01086     if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
01087         errno = ENOMEM;
01088         return (caddr_t)-1;
01089     }
01090 
01091     heap = new_heap;
01092     return (caddr_t) prev_heap;
01093 }
01094 #endif
01095 #endif
01096 
01097 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
01098 extern "C" void _exit(int return_code) {
01099 #else
01100 namespace std {
01101 extern "C" void exit(int return_code) {
01102 #endif
01103 
01104 #if DEVICE_STDIO_MESSAGES
01105 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
01106     fflush(stdout);
01107     fflush(stderr);
01108 #endif
01109 #endif
01110 
01111 #if DEVICE_SEMIHOST
01112     if (mbed_interface_connected()) {
01113         semihost_exit();
01114     }
01115 #endif
01116     if (return_code) {
01117         mbed_die();
01118     }
01119 
01120     while (1);
01121 }
01122 
01123 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
01124 } //namespace std
01125 #endif
01126 
01127 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
01128 
01129 // This series of function disable the registration of global destructors
01130 // in a dynamic table which will be called when the application exit.
01131 // In mbed, program never exit properly, it dies.
01132 // More informations about this topic for ARMCC here:
01133 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
01134 extern "C" {
01135 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) {
01136     return 1;
01137 }
01138 
01139 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) {
01140     return 1;
01141 }
01142 
01143 void __cxa_finalize(void *handle) {
01144 }
01145 
01146 } // end of extern "C"
01147 
01148 #endif
01149 
01150 
01151 #if defined(TOOLCHAIN_GCC)
01152 
01153 /*
01154  * Depending on how newlib is  configured, it is often not enough to define
01155  * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
01156  * behavior regarding the registration of handlers with atexit.
01157  *
01158  * To overcome this limitation, exit and atexit are overriden here.
01159  */
01160 extern "C"{
01161 
01162 /**
01163  * @brief Retarget of exit for GCC.
01164  * @details Unlike the standard version, this function doesn't call any function
01165  * registered with atexit before calling _exit.
01166  */
01167 void __wrap_exit(int return_code) {
01168     _exit(return_code);
01169 }
01170 
01171 /**
01172  * @brief Retarget atexit from GCC.
01173  * @details This function will always fail and never register any handler to be
01174  * called at exit.
01175  */
01176 int __wrap_atexit(void (*func)()) {
01177     return 1;
01178 }
01179 
01180 }
01181 
01182 #endif
01183 
01184 
01185 
01186 namespace mbed {
01187 
01188 void mbed_set_unbuffered_stream(std::FILE *_file) {
01189 #if defined (__ICCARM__)
01190     char buf[2];
01191     std::setvbuf(_file,buf,_IONBF,NULL);
01192 #else
01193     setbuf(_file, NULL);
01194 #endif
01195 }
01196 
01197 int mbed_getc(std::FILE *_file){
01198 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
01199     /*This is only valid for unbuffered streams*/
01200     int res = std::fgetc(_file);
01201     if (res>=0){
01202         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
01203         _file->_Rend = _file->_Wend;
01204         _file->_Next = _file->_Wend;
01205     }
01206     return res;
01207 #else
01208     return std::fgetc(_file);
01209 #endif
01210 }
01211 
01212 char* mbed_gets(char*s, int size, std::FILE *_file){
01213 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
01214     /*This is only valid for unbuffered streams*/
01215     char *str = fgets(s,size,_file);
01216     if (str!=NULL){
01217         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
01218         _file->_Rend = _file->_Wend;
01219         _file->_Next = _file->_Wend;
01220     }
01221     return str;
01222 #else
01223     return std::fgets(s,size,_file);
01224 #endif
01225 }
01226 
01227 } // namespace mbed
01228 
01229 #if defined (__ICCARM__)
01230 // Stub out locks when an rtos is not present
01231 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
01232 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
01233 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
01234 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
01235 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
01236 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
01237 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
01238 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
01239 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
01240 #pragma section="__iar_tls$$DATA"
01241 extern "C" WEAK void *__aeabi_read_tp (void) {
01242   // Thread Local storage is not supported, using main thread memory for errno
01243   return __section_begin("__iar_tls$$DATA");
01244 }
01245 #endif
01246 #elif defined(__CC_ARM)
01247 // Do nothing
01248 #elif defined (__GNUC__)
01249 struct _reent;
01250 // Stub out locks when an rtos is not present
01251 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {}
01252 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {}
01253 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {}
01254 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {}
01255 
01256 extern "C" void __malloc_lock( struct _reent *_r )
01257 {
01258     __rtos_malloc_lock(_r);
01259 }
01260 
01261 extern "C" void __malloc_unlock( struct _reent *_r )
01262 {
01263     __rtos_malloc_unlock(_r);
01264 }
01265 
01266 extern "C" void __env_lock( struct _reent *_r )
01267 {
01268     __rtos_env_lock(_r);
01269 }
01270 
01271 extern "C" void __env_unlock( struct _reent *_r )
01272 {
01273     __rtos_env_unlock(_r);
01274 }
01275 
01276 #endif
01277 
01278 #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
01279 
01280 #define CXA_GUARD_INIT_DONE             (1 << 0)
01281 #define CXA_GUARD_INIT_IN_PROGRESS      (1 << 1)
01282 #define CXA_GUARD_MASK                  (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
01283 
01284 extern "C" int __cxa_guard_acquire(int *guard_object_p)
01285 {
01286     uint8_t *guard_object = (uint8_t *)guard_object_p;
01287     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
01288         return 0;
01289     }
01290     singleton_lock();
01291     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
01292         singleton_unlock();
01293         return 0;
01294     }
01295     MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
01296     *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
01297     return 1;
01298 }
01299 
01300 extern "C" void __cxa_guard_release(int *guard_object_p)
01301 {
01302     uint8_t *guard_object = (uint8_t *)guard_object_p;
01303     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
01304     *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
01305     singleton_unlock();
01306 }
01307 
01308 extern "C" void __cxa_guard_abort(int *guard_object_p)
01309 {
01310     uint8_t *guard_object = (uint8_t *)guard_object_p;
01311     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
01312     *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
01313     singleton_unlock();
01314 }
01315 
01316 #endif
01317 
01318 #if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__))
01319 
01320 // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
01321 // provide the implementation for these. Note: this needs to use the wrappers
01322 // instead of malloc()/free() as the caller address would point to wrappers,
01323 // not the caller of "new" or "delete".
01324 extern "C" void* malloc_wrapper(size_t size, const void* caller);
01325 extern "C" void free_wrapper(void *ptr, const void* caller);
01326     
01327 void *operator new(std::size_t count)
01328 {
01329     void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
01330     if (NULL == buffer) {
01331         error("Operator new out of memory\r\n");
01332     }
01333     return buffer;
01334 }
01335 
01336 void *operator new[](std::size_t count)
01337 {
01338     void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
01339     if (NULL == buffer) {
01340         error("Operator new[] out of memory\r\n");
01341     }
01342     return buffer;
01343 }
01344 
01345 void *operator new(std::size_t count, const std::nothrow_t& tag)
01346 {
01347     return malloc_wrapper(count, MBED_CALLER_ADDR());
01348 }
01349 
01350 void *operator new[](std::size_t count, const std::nothrow_t& tag)
01351 {
01352     return malloc_wrapper(count, MBED_CALLER_ADDR());
01353 }
01354 
01355 void operator delete(void *ptr)
01356 {
01357     free_wrapper(ptr, MBED_CALLER_ADDR());
01358 }
01359 void operator delete[](void *ptr)
01360 {
01361     free_wrapper(ptr, MBED_CALLER_ADDR());
01362 }
01363 
01364 #elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__)
01365 
01366 #include <reent.h>
01367 
01368 extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller);
01369 extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller);
01370 
01371 void *operator new(std::size_t count)
01372 {
01373     void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01374     if (NULL == buffer) {
01375         error("Operator new out of memory\r\n");
01376     }
01377     return buffer;
01378 }
01379 
01380 void *operator new[](std::size_t count)
01381 {
01382     void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01383     if (NULL == buffer) {
01384         error("Operator new[] out of memory\r\n");
01385     }
01386     return buffer;
01387 }
01388 
01389 void *operator new(std::size_t count, const std::nothrow_t& tag)
01390 {
01391     return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01392 }
01393 
01394 void *operator new[](std::size_t count, const std::nothrow_t& tag)
01395 {
01396     return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01397 }
01398 
01399 void operator delete(void *ptr)
01400 {
01401     free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
01402 }
01403 
01404 void operator delete[](void *ptr)
01405 {
01406     free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
01407 }
01408 
01409 #else
01410 
01411 void *operator new(std::size_t count)
01412 {
01413     void *buffer = malloc(count);
01414     if (NULL == buffer) {
01415         error("Operator new out of memory\r\n");
01416     }
01417     return buffer;
01418 }
01419 
01420 void *operator new[](std::size_t count)
01421 {
01422     void *buffer = malloc(count);
01423     if (NULL == buffer) {
01424         error("Operator new[] out of memory\r\n");
01425     }
01426     return buffer;
01427 }
01428 
01429 void *operator new(std::size_t count, const std::nothrow_t& tag)
01430 {
01431     return malloc(count);
01432 }
01433 
01434 void *operator new[](std::size_t count, const std::nothrow_t& tag)
01435 {
01436     return malloc(count);
01437 }
01438 
01439 void operator delete(void *ptr)
01440 {
01441     free(ptr);
01442 }
01443 void operator delete[](void *ptr)
01444 {
01445     free(ptr);
01446 }
01447 
01448 #endif
01449 
01450 /* @brief   standard c library clock() function.
01451  *
01452  * This function returns the number of clock ticks elapsed since the start of the program.
01453  *
01454  * @note Synchronization level: Thread safe
01455  *
01456  * @return
01457  *  the number of clock ticks elapsed since the start of the program.
01458  *
01459  * */
01460 extern "C" clock_t clock()
01461 {
01462     _mutex->lock();
01463     clock_t t = ticker_read(get_us_ticker_data());
01464     t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time
01465     _mutex->unlock();
01466     return t;
01467 }
01468 
01469 // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info
01470 MBED_WEAK const ticker_info_t* us_ticker_get_info()
01471 {
01472     static const ticker_info_t info = {
01473         1000000,
01474         32
01475     };
01476     return &info;
01477 }
01478 
01479 // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info
01480 MBED_WEAK const ticker_info_t* lp_ticker_get_info()
01481 {
01482     static const ticker_info_t info = {
01483         1000000,
01484         32
01485     };
01486     return &info;
01487 }