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