mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

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