takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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