Knight KE / Mbed OS Game_Master
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 fildes = reserve_filehandle();
00348     if (fildes < 0) {
00349         return fildes;
00350     }
00351 
00352     filehandles[fildes] = fh;
00353     stdio_in_prev[fildes] = 0;
00354     stdio_out_prev[fildes] = 0;
00355 
00356     return fildes;
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 fildes = reserve_filehandle();
00468     if (fildes < 0) {
00469         return fildes;
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, fildes);
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, fildes);
00488         }
00489         int err = fs->open(&res, path.fileName(), oflag);
00490         if (err) {
00491             return handle_open_errors(err, fildes);
00492         }
00493     }
00494 
00495     filehandles[fildes] = res;
00496     stdio_in_prev[fildes] = 0;
00497     stdio_out_prev[fildes] = 0;
00498 
00499     return fildes;
00500 }
00501 
00502 extern "C" int PREFIX(_close)(FILEHANDLE fh) {
00503     return close(fh);
00504 }
00505 
00506 extern "C" int close(int fildes) {
00507     FileHandle* fhc = get_fhc(fildes);
00508     filehandles[fildes] = 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         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_PROHIBITED_IN_ISR_CONTEXT), "Error - writing to a file in an ISR or critical section\r\n", fh);
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 fildes, const void *buf, size_t length) {
00614 
00615     FileHandle* fhc = get_fhc(fildes);
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         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_PROHIBITED_IN_ISR_CONTEXT), "Error - reading from a file in an ISR or critical section\r\n", fh);
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 fildes, void *buf, size_t length) {
00704 
00705     FileHandle* fhc = get_fhc(fildes);
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 fildes) {
00731     FileHandle* fhc = get_fhc(fildes);
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 fildes, off_t offset, int whence) {
00769     FileHandle* fhc = get_fhc(fildes);
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 fildes) {
00790     FileHandle* fhc = get_fhc(fildes);
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 fildes, struct stat *st) {
00854     FileHandle* fhc = get_fhc(fildes);
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 fcntl(int fildes, int cmd, ...) {
00866     FileHandle *fhc = get_fhc(fildes);
00867     if (fhc == NULL) {
00868         errno = EBADF;
00869         return -1;
00870     }
00871 
00872     switch (cmd) {
00873         case F_GETFL: {
00874             int flags = 0;
00875             if (fhc->is_blocking()) {
00876                 flags |= O_NONBLOCK;
00877             }
00878             return flags;
00879         }
00880         case F_SETFL: {
00881             va_list ap;
00882             va_start(ap, cmd);
00883             int flags = va_arg(ap, int);
00884             va_end(ap);
00885             int ret = fhc->set_blocking(flags & O_NONBLOCK);
00886             if (ret < 0) {
00887                 errno = -ret;
00888                 return -1;
00889             }
00890             return 0;
00891         }
00892 
00893         default: {
00894             errno = EINVAL;
00895             return -1;
00896         }
00897     }
00898 }
00899 
00900 extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
00901 {
00902     if (nfds > OPEN_MAX) {
00903         errno = EINVAL;
00904         return -1;
00905     }
00906 
00907     struct mbed::pollfh fhs[OPEN_MAX];
00908     for (nfds_t n = 0; n < nfds; n++) {
00909         // Underlying FileHandle poll returns POLLNVAL if given NULL, so
00910         // we don't need to take special action.
00911         fhs[n].fh = get_fhc(fds[n].fd);
00912         fhs[n].events = fds[n].events;
00913     }
00914     int ret = poll(fhs, nfds, timeout);
00915     for (nfds_t n = 0; n < nfds; n++) {
00916         fds[n].revents = fhs[n].revents;
00917     }
00918     return ret;
00919 }
00920 
00921 namespace std {
00922 extern "C" int remove(const char *path) {
00923     FilePath fp(path);
00924     FileSystemHandle *fs = fp.fileSystem();
00925     if (fs == NULL) {
00926         errno = ENODEV;
00927         return -1;
00928     }
00929 
00930     int err = fs->remove(fp.fileName());
00931     if (err < 0) {
00932         errno = -err;
00933         return -1;
00934     } else {
00935         return 0;
00936     }
00937 }
00938 
00939 extern "C" int rename(const char *oldname, const char *newname) {
00940     FilePath fpOld(oldname);
00941     FilePath fpNew(newname);
00942     FileSystemHandle *fsOld = fpOld.fileSystem();
00943     FileSystemHandle *fsNew = fpNew.fileSystem();
00944 
00945     if (fsOld == NULL) {
00946         errno = ENODEV;
00947         return -1;
00948     }
00949 
00950     /* rename only if both files are on the same FS */
00951     if (fsOld != fsNew) {
00952         errno = EXDEV;
00953         return -1;
00954     }
00955 
00956     int err = fsOld->rename(fpOld.fileName(), fpNew.fileName());
00957     if (err < 0) {
00958         errno = -err;
00959         return -1;
00960     } else {
00961         return 0;
00962     }
00963 }
00964 
00965 extern "C" char *tmpnam(char *s) {
00966     errno = EBADF;
00967     return NULL;
00968 }
00969 
00970 extern "C" FILE *tmpfile() {
00971     errno = EBADF;
00972     return NULL;
00973 }
00974 } // namespace std
00975 
00976 #ifdef __ARMCC_VERSION
00977 extern "C" char *_sys_command_string(char *cmd, int len) {
00978     return NULL;
00979 }
00980 #endif
00981 
00982 extern "C" DIR *opendir(const char *path) {
00983     FilePath fp(path);
00984     FileSystemHandle* fs = fp.fileSystem();
00985     if (fs == NULL) {
00986         errno = ENODEV;
00987         return NULL;
00988     }
00989 
00990     DirHandle *dir;
00991     int err = fs->open(&dir, fp.fileName());
00992     if (err < 0) {
00993         errno = -err;
00994         return NULL;
00995     }
00996 
00997     return dir;
00998 }
00999 
01000 extern "C" struct dirent *readdir(DIR *dir) {
01001     static struct dirent ent;
01002     int err = dir->read(&ent);
01003     if (err < 1) {
01004         if (err < 0) {
01005             errno = -err;
01006         }
01007         return NULL;
01008     }
01009 
01010     return &ent;
01011 }
01012 
01013 extern "C" int closedir(DIR *dir) {
01014     int err = dir->close();
01015     if (err < 0) {
01016         errno = -err;
01017         return -1;
01018     } else {
01019         return 0;
01020     }
01021 }
01022 
01023 extern "C" void rewinddir(DIR *dir) {
01024     dir->rewind();
01025 }
01026 
01027 extern "C" off_t telldir(DIR *dir) {
01028     return dir->tell();
01029 }
01030 
01031 extern "C" void seekdir(DIR *dir, off_t off) {
01032     dir->seek(off);
01033 }
01034 
01035 extern "C" int mkdir(const char *path, mode_t mode) {
01036     FilePath fp(path);
01037     FileSystemHandle *fs = fp.fileSystem();
01038     if (fs == NULL) {
01039         errno = ENODEV;
01040         return -1;
01041     }
01042 
01043     int err = fs->mkdir(fp.fileName(), mode);
01044     if (err < 0) {
01045         errno = -err;
01046         return -1;
01047     } else {
01048         return 0;
01049     }
01050 }
01051 
01052 extern "C" int stat(const char *path, struct stat *st) {
01053     FilePath fp(path);
01054     FileSystemHandle *fs = fp.fileSystem();
01055     if (fs == NULL) {
01056         errno = ENODEV;
01057         return -1;
01058     }
01059 
01060     int err = fs->stat(fp.fileName(), st);
01061     if (err < 0) {
01062         errno = -err;
01063         return -1;
01064     } else {
01065         return 0;
01066     }
01067 }
01068 
01069 extern "C" int statvfs(const char *path, struct statvfs *buf) {
01070     FilePath fp(path);
01071     FileSystemHandle *fs = fp.fileSystem();
01072     if (fs == NULL) {
01073         errno = ENODEV;
01074         return -1;
01075     }
01076 
01077     int err = fs->statvfs(fp.fileName(), buf);
01078     if (err < 0) {
01079         errno = -err;
01080         return -1;
01081     } else {
01082         return 0;
01083     }
01084 }
01085 
01086 #if defined(TOOLCHAIN_GCC)
01087 /* prevents the exception handling name demangling code getting pulled in */
01088 #include "mbed_error.h"
01089 namespace __gnu_cxx {
01090     void __verbose_terminate_handler() {
01091         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_CLIB_EXCEPTION),"Exception", 0);
01092     }
01093 }
01094 extern "C" WEAK void __cxa_pure_virtual(void);
01095 extern "C" WEAK void __cxa_pure_virtual(void) {
01096     exit(1);
01097 }
01098 
01099 #endif
01100 
01101 // Provide implementation of _sbrk (low-level dynamic memory allocation
01102 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
01103 // SP.  This make it compatible with RTX RTOS thread stacks.
01104 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
01105 
01106 #if defined(TARGET_CORTEX_A)
01107 extern "C" uint32_t  __HeapLimit;
01108 #endif
01109 
01110 // Turn off the errno macro and use actual global variable instead.
01111 #undef errno
01112 extern "C" int errno;
01113 
01114 // Dynamic memory allocation related syscall.
01115 #if (defined(TARGET_NUVOTON) || defined(TWO_RAM_REGIONS))
01116 
01117 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
01118 // __wrap__sbrk() is implemented in:
01119 // TARGET_NUMAKER_PFM_NUC472    targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c
01120 // TARGET_NUMAKER_PFM_M453      targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/m451_retarget.c
01121 // TARGET_STM32L4               targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L4/l4_retarget.c
01122 extern "C" void *__wrap__sbrk(int incr);
01123 extern "C" caddr_t _sbrk(int incr) {
01124     return (caddr_t) __wrap__sbrk(incr);
01125 }
01126 #else
01127 // Linker defined symbol used by _sbrk to indicate where heap should start.
01128 extern "C" uint32_t __end__;
01129 // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory.
01130 extern "C" WEAK caddr_t _sbrk(int incr) {
01131     static unsigned char* heap = (unsigned char*)&__end__;
01132     unsigned char*        prev_heap = heap;
01133     unsigned char*        new_heap = heap + incr;
01134 
01135 #if defined(TARGET_CORTEX_A)
01136     if (new_heap >= (unsigned char*)&__HeapLimit) {     /* __HeapLimit is end of heap section */
01137 #else
01138     if (new_heap >= (unsigned char*)__get_MSP()) {
01139 #endif
01140         errno = ENOMEM;
01141         return (caddr_t)-1;
01142     }
01143 
01144     // Additional heap checking if set
01145     if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
01146         errno = ENOMEM;
01147         return (caddr_t)-1;
01148     }
01149 
01150     heap = new_heap;
01151     return (caddr_t) prev_heap;
01152 }
01153 #endif
01154 #endif
01155 
01156 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
01157 extern "C" void _exit(int return_code) {
01158 #else
01159 namespace std {
01160 extern "C" void exit(int return_code) {
01161 #endif
01162 
01163 #if DEVICE_STDIO_MESSAGES
01164 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
01165     fflush(stdout);
01166     fflush(stderr);
01167 #endif
01168 #endif
01169 
01170 #if DEVICE_SEMIHOST
01171     if (mbed_interface_connected()) {
01172         semihost_exit();
01173     }
01174 #endif
01175     if (return_code) {
01176         mbed_die();
01177     }
01178 
01179     while (1);
01180 }
01181 
01182 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
01183 } //namespace std
01184 #endif
01185 
01186 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
01187 
01188 // This series of function disable the registration of global destructors
01189 // in a dynamic table which will be called when the application exit.
01190 // In mbed, program never exit properly, it dies.
01191 // More informations about this topic for ARMCC here:
01192 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
01193 extern "C" {
01194 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) {
01195     return 1;
01196 }
01197 
01198 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) {
01199     return 1;
01200 }
01201 
01202 void __cxa_finalize(void *handle) {
01203 }
01204 
01205 } // end of extern "C"
01206 
01207 #endif
01208 
01209 
01210 #if defined(TOOLCHAIN_GCC)
01211 
01212 /*
01213  * Depending on how newlib is  configured, it is often not enough to define
01214  * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
01215  * behavior regarding the registration of handlers with atexit.
01216  *
01217  * To overcome this limitation, exit and atexit are overriden here.
01218  */
01219 extern "C"{
01220 
01221 /**
01222  * @brief Retarget of exit for GCC.
01223  * @details Unlike the standard version, this function doesn't call any function
01224  * registered with atexit before calling _exit.
01225  */
01226 void __wrap_exit(int return_code) {
01227     _exit(return_code);
01228 }
01229 
01230 /**
01231  * @brief Retarget atexit from GCC.
01232  * @details This function will always fail and never register any handler to be
01233  * called at exit.
01234  */
01235 int __wrap_atexit(void (*func)()) {
01236     return 1;
01237 }
01238 
01239 }
01240 
01241 #endif
01242 
01243 
01244 
01245 namespace mbed {
01246 
01247 void mbed_set_unbuffered_stream(std::FILE *_file) {
01248 #if defined (__ICCARM__)
01249     char buf[2];
01250     std::setvbuf(_file,buf,_IONBF,NULL);
01251 #else
01252     setbuf(_file, NULL);
01253 #endif
01254 }
01255 
01256 int mbed_getc(std::FILE *_file){
01257 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
01258     /*This is only valid for unbuffered streams*/
01259     int res = std::fgetc(_file);
01260     if (res>=0){
01261         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
01262         _file->_Rend = _file->_Wend;
01263         _file->_Next = _file->_Wend;
01264     }
01265     return res;
01266 #else
01267     return std::fgetc(_file);
01268 #endif
01269 }
01270 
01271 char* mbed_gets(char*s, int size, std::FILE *_file){
01272 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
01273     /*This is only valid for unbuffered streams*/
01274     char *str = fgets(s,size,_file);
01275     if (str!=NULL){
01276         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
01277         _file->_Rend = _file->_Wend;
01278         _file->_Next = _file->_Wend;
01279     }
01280     return str;
01281 #else
01282     return std::fgets(s,size,_file);
01283 #endif
01284 }
01285 
01286 } // namespace mbed
01287 
01288 #if defined (__ICCARM__)
01289 // Stub out locks when an rtos is not present
01290 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
01291 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
01292 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
01293 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
01294 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
01295 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
01296 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
01297 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
01298 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
01299 #pragma section="__iar_tls$$DATA"
01300 extern "C" WEAK void *__aeabi_read_tp (void) {
01301   // Thread Local storage is not supported, using main thread memory for errno
01302   return __section_begin("__iar_tls$$DATA");
01303 }
01304 #endif
01305 #elif defined(__CC_ARM)
01306 // Do nothing
01307 #elif defined (__GNUC__)
01308 struct _reent;
01309 // Stub out locks when an rtos is not present
01310 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {}
01311 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {}
01312 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {}
01313 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {}
01314 
01315 extern "C" void __malloc_lock( struct _reent *_r )
01316 {
01317     __rtos_malloc_lock(_r);
01318 }
01319 
01320 extern "C" void __malloc_unlock( struct _reent *_r )
01321 {
01322     __rtos_malloc_unlock(_r);
01323 }
01324 
01325 extern "C" void __env_lock( struct _reent *_r )
01326 {
01327     __rtos_env_lock(_r);
01328 }
01329 
01330 extern "C" void __env_unlock( struct _reent *_r )
01331 {
01332     __rtos_env_unlock(_r);
01333 }
01334 
01335 #endif
01336 
01337 #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
01338 
01339 #define CXA_GUARD_INIT_DONE             (1 << 0)
01340 #define CXA_GUARD_INIT_IN_PROGRESS      (1 << 1)
01341 #define CXA_GUARD_MASK                  (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
01342 
01343 extern "C" int __cxa_guard_acquire(int *guard_object_p)
01344 {
01345     uint8_t *guard_object = (uint8_t *)guard_object_p;
01346     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
01347         return 0;
01348     }
01349     singleton_lock();
01350     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
01351         singleton_unlock();
01352         return 0;
01353     }
01354     MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
01355     *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
01356     return 1;
01357 }
01358 
01359 extern "C" void __cxa_guard_release(int *guard_object_p)
01360 {
01361     uint8_t *guard_object = (uint8_t *)guard_object_p;
01362     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
01363     *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
01364     singleton_unlock();
01365 }
01366 
01367 extern "C" void __cxa_guard_abort(int *guard_object_p)
01368 {
01369     uint8_t *guard_object = (uint8_t *)guard_object_p;
01370     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
01371     *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
01372     singleton_unlock();
01373 }
01374 
01375 #endif
01376 
01377 #if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))
01378 
01379 // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
01380 // provide the implementation for these. Note: this needs to use the wrappers
01381 // instead of malloc()/free() as the caller address would point to wrappers,
01382 // not the caller of "new" or "delete".
01383 extern "C" void* malloc_wrapper(size_t size, const void* caller);
01384 extern "C" void free_wrapper(void *ptr, const void* caller);
01385     
01386 void *operator new(std::size_t count)
01387 {
01388     void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
01389     if (NULL == buffer) {
01390         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
01391     }
01392     return buffer;
01393 }
01394 
01395 void *operator new[](std::size_t count)
01396 {
01397     void *buffer = malloc_wrapper(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, const std::nothrow_t& tag)
01405 {
01406     return malloc_wrapper(count, MBED_CALLER_ADDR());
01407 }
01408 
01409 void *operator new[](std::size_t count, const std::nothrow_t& tag)
01410 {
01411     return malloc_wrapper(count, MBED_CALLER_ADDR());
01412 }
01413 
01414 void operator delete(void *ptr)
01415 {
01416     free_wrapper(ptr, MBED_CALLER_ADDR());
01417 }
01418 void operator delete[](void *ptr)
01419 {
01420     free_wrapper(ptr, MBED_CALLER_ADDR());
01421 }
01422 
01423 #elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__)
01424 
01425 #include <reent.h>
01426 
01427 extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller);
01428 extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller);
01429 
01430 void *operator new(std::size_t count)
01431 {
01432     void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01433     if (NULL == buffer) {
01434         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
01435     }
01436     return buffer;
01437 }
01438 
01439 void *operator new[](std::size_t count)
01440 {
01441     void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01442     if (NULL == buffer) {
01443         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
01444     }
01445     return buffer;
01446 }
01447 
01448 void *operator new(std::size_t count, const std::nothrow_t& tag)
01449 {
01450     return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01451 }
01452 
01453 void *operator new[](std::size_t count, const std::nothrow_t& tag)
01454 {
01455     return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
01456 }
01457 
01458 void operator delete(void *ptr)
01459 {
01460     free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
01461 }
01462 
01463 void operator delete[](void *ptr)
01464 {
01465     free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
01466 }
01467 
01468 #else
01469 
01470 void *operator new(std::size_t count)
01471 {
01472     void *buffer = malloc(count);
01473     if (NULL == buffer) {
01474         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
01475     }
01476     return buffer;
01477 }
01478 
01479 void *operator new[](std::size_t count)
01480 {
01481     void *buffer = malloc(count);
01482     if (NULL == buffer) {
01483         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new[] out of memory\r\n", count);
01484     }
01485     return buffer;
01486 }
01487 
01488 void *operator new(std::size_t count, const std::nothrow_t& tag)
01489 {
01490     return malloc(count);
01491 }
01492 
01493 void *operator new[](std::size_t count, const std::nothrow_t& tag)
01494 {
01495     return malloc(count);
01496 }
01497 
01498 void operator delete(void *ptr)
01499 {
01500     free(ptr);
01501 }
01502 void operator delete[](void *ptr)
01503 {
01504     free(ptr);
01505 }
01506 
01507 #endif
01508 
01509 /* @brief   standard c library clock() function.
01510  *
01511  * This function returns the number of clock ticks elapsed since the start of the program.
01512  *
01513  * @note Synchronization level: Thread safe
01514  *
01515  * @return
01516  *  the number of clock ticks elapsed since the start of the program.
01517  *
01518  * */
01519 extern "C" clock_t clock()
01520 {
01521     _mutex->lock();
01522     clock_t t = ticker_read(get_us_ticker_data());
01523     t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time
01524     _mutex->unlock();
01525     return t;
01526 }
01527 
01528 // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info
01529 MBED_WEAK const ticker_info_t* us_ticker_get_info()
01530 {
01531     static const ticker_info_t info = {
01532         1000000,
01533         32
01534     };
01535     return &info;
01536 }
01537 
01538 // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info
01539 MBED_WEAK const ticker_info_t* lp_ticker_get_info()
01540 {
01541     static const ticker_info_t info = {
01542         1000000,
01543         32
01544     };
01545     return &info;
01546 }