Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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