Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2006-2015 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16 #include <time.h>
kadonotakashi 0:8fdf9a60065b 17 #include "platform/platform.h"
kadonotakashi 0:8fdf9a60065b 18 #include "platform/FilePath.h"
kadonotakashi 0:8fdf9a60065b 19 #include "hal/serial_api.h"
kadonotakashi 0:8fdf9a60065b 20 #include "hal/us_ticker_api.h"
kadonotakashi 0:8fdf9a60065b 21 #include "platform/mbed_toolchain.h"
kadonotakashi 0:8fdf9a60065b 22 #include "platform/mbed_semihost_api.h"
kadonotakashi 0:8fdf9a60065b 23 #include "platform/mbed_interface.h"
kadonotakashi 0:8fdf9a60065b 24 #include "platform/SingletonPtr.h"
kadonotakashi 0:8fdf9a60065b 25 #include "platform/PlatformMutex.h"
kadonotakashi 0:8fdf9a60065b 26 #include "platform/mbed_error.h"
kadonotakashi 0:8fdf9a60065b 27 #include "platform/mbed_stats.h"
kadonotakashi 0:8fdf9a60065b 28 #include "platform/mbed_critical.h"
kadonotakashi 0:8fdf9a60065b 29 #include "platform/mbed_poll.h"
kadonotakashi 0:8fdf9a60065b 30 #include "platform/PlatformMutex.h"
kadonotakashi 0:8fdf9a60065b 31 #include "drivers/UARTSerial.h"
kadonotakashi 0:8fdf9a60065b 32 #include "us_ticker_api.h"
kadonotakashi 0:8fdf9a60065b 33 #include "lp_ticker_api.h"
kadonotakashi 0:8fdf9a60065b 34 #include <stdlib.h>
kadonotakashi 0:8fdf9a60065b 35 #include <string.h>
kadonotakashi 0:8fdf9a60065b 36 #include <limits.h>
kadonotakashi 0:8fdf9a60065b 37 #ifndef SSIZE_MAX
kadonotakashi 0:8fdf9a60065b 38 #define SSIZE_MAX INT_MAX
kadonotakashi 0:8fdf9a60065b 39 #endif
kadonotakashi 0:8fdf9a60065b 40 #include <stdio.h>
kadonotakashi 0:8fdf9a60065b 41 #include <errno.h>
kadonotakashi 0:8fdf9a60065b 42 #include "platform/mbed_retarget.h"
kadonotakashi 0:8fdf9a60065b 43
kadonotakashi 0:8fdf9a60065b 44 static SingletonPtr<PlatformMutex> _mutex;
kadonotakashi 0:8fdf9a60065b 45
kadonotakashi 0:8fdf9a60065b 46 #if defined(__ARMCC_VERSION)
kadonotakashi 0:8fdf9a60065b 47 # if __ARMCC_VERSION >= 6010050
kadonotakashi 0:8fdf9a60065b 48 # include <arm_compat.h>
kadonotakashi 0:8fdf9a60065b 49 # endif
kadonotakashi 0:8fdf9a60065b 50 # include <rt_sys.h>
kadonotakashi 0:8fdf9a60065b 51 # include <rt_misc.h>
kadonotakashi 0:8fdf9a60065b 52 # include <stdint.h>
kadonotakashi 0:8fdf9a60065b 53 # define PREFIX(x) _sys##x
kadonotakashi 0:8fdf9a60065b 54 # define OPEN_MAX _SYS_OPEN
kadonotakashi 0:8fdf9a60065b 55 # ifdef __MICROLIB
kadonotakashi 0:8fdf9a60065b 56 # pragma import(__use_full_stdio)
kadonotakashi 0:8fdf9a60065b 57 # endif
kadonotakashi 0:8fdf9a60065b 58
kadonotakashi 0:8fdf9a60065b 59 #elif defined(__ICCARM__)
kadonotakashi 0:8fdf9a60065b 60 # include <yfuns.h>
kadonotakashi 0:8fdf9a60065b 61 # define PREFIX(x) _##x
kadonotakashi 0:8fdf9a60065b 62 # define OPEN_MAX 16
kadonotakashi 0:8fdf9a60065b 63
kadonotakashi 0:8fdf9a60065b 64 # define STDIN_FILENO 0
kadonotakashi 0:8fdf9a60065b 65 # define STDOUT_FILENO 1
kadonotakashi 0:8fdf9a60065b 66 # define STDERR_FILENO 2
kadonotakashi 0:8fdf9a60065b 67
kadonotakashi 0:8fdf9a60065b 68 #else
kadonotakashi 0:8fdf9a60065b 69 # include <sys/syslimits.h>
kadonotakashi 0:8fdf9a60065b 70 # define PREFIX(x) x
kadonotakashi 0:8fdf9a60065b 71 #endif
kadonotakashi 0:8fdf9a60065b 72
kadonotakashi 0:8fdf9a60065b 73 #define FILE_HANDLE_RESERVED ((FileHandle*)0xFFFFFFFF)
kadonotakashi 0:8fdf9a60065b 74
kadonotakashi 0:8fdf9a60065b 75 /**
kadonotakashi 0:8fdf9a60065b 76 * Macros for setting console flow control.
kadonotakashi 0:8fdf9a60065b 77 */
kadonotakashi 0:8fdf9a60065b 78 #define CONSOLE_FLOWCONTROL_RTS 1
kadonotakashi 0:8fdf9a60065b 79 #define CONSOLE_FLOWCONTROL_CTS 2
kadonotakashi 0:8fdf9a60065b 80 #define CONSOLE_FLOWCONTROL_RTSCTS 3
kadonotakashi 0:8fdf9a60065b 81 #define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
kadonotakashi 0:8fdf9a60065b 82 #define mbed_console_concat(x) mbed_console_concat_(x)
kadonotakashi 0:8fdf9a60065b 83 #define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
kadonotakashi 0:8fdf9a60065b 84
kadonotakashi 0:8fdf9a60065b 85 using namespace mbed;
kadonotakashi 0:8fdf9a60065b 86
kadonotakashi 0:8fdf9a60065b 87 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
kadonotakashi 0:8fdf9a60065b 88 // Before version 5.03, we were using a patched version of microlib with proper names
kadonotakashi 0:8fdf9a60065b 89 extern const char __stdin_name[] = ":tt";
kadonotakashi 0:8fdf9a60065b 90 extern const char __stdout_name[] = ":tt";
kadonotakashi 0:8fdf9a60065b 91 extern const char __stderr_name[] = ":tt";
kadonotakashi 0:8fdf9a60065b 92
kadonotakashi 0:8fdf9a60065b 93 #else
kadonotakashi 0:8fdf9a60065b 94 extern const char __stdin_name[] = "/stdin";
kadonotakashi 0:8fdf9a60065b 95 extern const char __stdout_name[] = "/stdout";
kadonotakashi 0:8fdf9a60065b 96 extern const char __stderr_name[] = "/stderr";
kadonotakashi 0:8fdf9a60065b 97 #endif
kadonotakashi 0:8fdf9a60065b 98
kadonotakashi 0:8fdf9a60065b 99 unsigned char *mbed_heap_start = 0;
kadonotakashi 0:8fdf9a60065b 100 uint32_t mbed_heap_size = 0;
kadonotakashi 0:8fdf9a60065b 101
kadonotakashi 0:8fdf9a60065b 102 /* newlib has the filehandle field in the FILE struct as a short, so
kadonotakashi 0:8fdf9a60065b 103 * we can't just return a Filehandle* from _open and instead have to
kadonotakashi 0:8fdf9a60065b 104 * put it in a filehandles array and return the index into that array
kadonotakashi 0:8fdf9a60065b 105 */
kadonotakashi 0:8fdf9a60065b 106 static FileHandle *filehandles[OPEN_MAX] = { FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED };
kadonotakashi 0:8fdf9a60065b 107 static char stdio_in_prev[OPEN_MAX];
kadonotakashi 0:8fdf9a60065b 108 static char stdio_out_prev[OPEN_MAX];
kadonotakashi 0:8fdf9a60065b 109 static SingletonPtr<PlatformMutex> filehandle_mutex;
kadonotakashi 0:8fdf9a60065b 110
kadonotakashi 0:8fdf9a60065b 111 namespace mbed {
kadonotakashi 0:8fdf9a60065b 112 void mbed_set_unbuffered_stream(std::FILE *_file);
kadonotakashi 0:8fdf9a60065b 113
kadonotakashi 0:8fdf9a60065b 114 void remove_filehandle(FileHandle *file)
kadonotakashi 0:8fdf9a60065b 115 {
kadonotakashi 0:8fdf9a60065b 116 filehandle_mutex->lock();
kadonotakashi 0:8fdf9a60065b 117 /* Remove all open filehandles for this */
kadonotakashi 0:8fdf9a60065b 118 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles) / sizeof(*filehandles); fh_i++) {
kadonotakashi 0:8fdf9a60065b 119 if (filehandles[fh_i] == file) {
kadonotakashi 0:8fdf9a60065b 120 filehandles[fh_i] = NULL;
kadonotakashi 0:8fdf9a60065b 121 }
kadonotakashi 0:8fdf9a60065b 122 }
kadonotakashi 0:8fdf9a60065b 123 filehandle_mutex->unlock();
kadonotakashi 0:8fdf9a60065b 124 }
kadonotakashi 0:8fdf9a60065b 125 }
kadonotakashi 0:8fdf9a60065b 126
kadonotakashi 0:8fdf9a60065b 127 #if DEVICE_SERIAL
kadonotakashi 0:8fdf9a60065b 128 extern int stdio_uart_inited;
kadonotakashi 0:8fdf9a60065b 129 extern serial_t stdio_uart;
kadonotakashi 0:8fdf9a60065b 130
kadonotakashi 0:8fdf9a60065b 131 /* Private FileHandle to implement backwards-compatible functionality of
kadonotakashi 0:8fdf9a60065b 132 * direct HAL serial access for default stdin/stdout/stderr.
kadonotakashi 0:8fdf9a60065b 133 * This is not a particularly well-behaved FileHandle for a stream, which
kadonotakashi 0:8fdf9a60065b 134 * is why it's not public. People should be using UARTSerial.
kadonotakashi 0:8fdf9a60065b 135 */
kadonotakashi 0:8fdf9a60065b 136 class DirectSerial : public FileHandle {
kadonotakashi 0:8fdf9a60065b 137 public:
kadonotakashi 0:8fdf9a60065b 138 DirectSerial(PinName tx, PinName rx, int baud);
kadonotakashi 0:8fdf9a60065b 139 virtual ssize_t write(const void *buffer, size_t size);
kadonotakashi 0:8fdf9a60065b 140 virtual ssize_t read(void *buffer, size_t size);
kadonotakashi 0:8fdf9a60065b 141 virtual off_t seek(off_t offset, int whence = SEEK_SET)
kadonotakashi 0:8fdf9a60065b 142 {
kadonotakashi 0:8fdf9a60065b 143 return -ESPIPE;
kadonotakashi 0:8fdf9a60065b 144 }
kadonotakashi 0:8fdf9a60065b 145 virtual off_t size()
kadonotakashi 0:8fdf9a60065b 146 {
kadonotakashi 0:8fdf9a60065b 147 return -EINVAL;
kadonotakashi 0:8fdf9a60065b 148 }
kadonotakashi 0:8fdf9a60065b 149 virtual int isatty()
kadonotakashi 0:8fdf9a60065b 150 {
kadonotakashi 0:8fdf9a60065b 151 return true;
kadonotakashi 0:8fdf9a60065b 152 }
kadonotakashi 0:8fdf9a60065b 153 virtual int close()
kadonotakashi 0:8fdf9a60065b 154 {
kadonotakashi 0:8fdf9a60065b 155 return 0;
kadonotakashi 0:8fdf9a60065b 156 }
kadonotakashi 0:8fdf9a60065b 157 virtual short poll(short events) const;
kadonotakashi 0:8fdf9a60065b 158 };
kadonotakashi 0:8fdf9a60065b 159
kadonotakashi 0:8fdf9a60065b 160 DirectSerial::DirectSerial(PinName tx, PinName rx, int baud)
kadonotakashi 0:8fdf9a60065b 161 {
kadonotakashi 0:8fdf9a60065b 162 if (stdio_uart_inited) {
kadonotakashi 0:8fdf9a60065b 163 return;
kadonotakashi 0:8fdf9a60065b 164 }
kadonotakashi 0:8fdf9a60065b 165 serial_init(&stdio_uart, tx, rx);
kadonotakashi 0:8fdf9a60065b 166 serial_baud(&stdio_uart, baud);
kadonotakashi 0:8fdf9a60065b 167 #if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
kadonotakashi 0:8fdf9a60065b 168 serial_set_flow_control(&stdio_uart, FlowControlRTS, STDIO_UART_RTS, NC);
kadonotakashi 0:8fdf9a60065b 169 #elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
kadonotakashi 0:8fdf9a60065b 170 serial_set_flow_control(&stdio_uart, FlowControlCTS, NC, STDIO_UART_CTS);
kadonotakashi 0:8fdf9a60065b 171 #elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
kadonotakashi 0:8fdf9a60065b 172 serial_set_flow_control(&stdio_uart, FlowControlRTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
kadonotakashi 0:8fdf9a60065b 173 #endif
kadonotakashi 0:8fdf9a60065b 174 }
kadonotakashi 0:8fdf9a60065b 175
kadonotakashi 0:8fdf9a60065b 176 ssize_t DirectSerial::write(const void *buffer, size_t size)
kadonotakashi 0:8fdf9a60065b 177 {
kadonotakashi 0:8fdf9a60065b 178 const unsigned char *buf = static_cast<const unsigned char *>(buffer);
kadonotakashi 0:8fdf9a60065b 179 for (size_t i = 0; i < size; i++) {
kadonotakashi 0:8fdf9a60065b 180 serial_putc(&stdio_uart, buf[i]);
kadonotakashi 0:8fdf9a60065b 181 }
kadonotakashi 0:8fdf9a60065b 182 return size;
kadonotakashi 0:8fdf9a60065b 183 }
kadonotakashi 0:8fdf9a60065b 184
kadonotakashi 0:8fdf9a60065b 185 ssize_t DirectSerial::read(void *buffer, size_t size)
kadonotakashi 0:8fdf9a60065b 186 {
kadonotakashi 0:8fdf9a60065b 187 unsigned char *buf = static_cast<unsigned char *>(buffer);
kadonotakashi 0:8fdf9a60065b 188 if (size == 0) {
kadonotakashi 0:8fdf9a60065b 189 return 0;
kadonotakashi 0:8fdf9a60065b 190 }
kadonotakashi 0:8fdf9a60065b 191 buf[0] = serial_getc(&stdio_uart);
kadonotakashi 0:8fdf9a60065b 192 return 1;
kadonotakashi 0:8fdf9a60065b 193 }
kadonotakashi 0:8fdf9a60065b 194
kadonotakashi 0:8fdf9a60065b 195 short DirectSerial::poll(short events) const
kadonotakashi 0:8fdf9a60065b 196 {
kadonotakashi 0:8fdf9a60065b 197 short revents = 0;
kadonotakashi 0:8fdf9a60065b 198 if ((events & POLLIN) && serial_readable(&stdio_uart)) {
kadonotakashi 0:8fdf9a60065b 199 revents |= POLLIN;
kadonotakashi 0:8fdf9a60065b 200 }
kadonotakashi 0:8fdf9a60065b 201 if ((events & POLLOUT) && serial_writable(&stdio_uart)) {
kadonotakashi 0:8fdf9a60065b 202 revents |= POLLOUT;
kadonotakashi 0:8fdf9a60065b 203 }
kadonotakashi 0:8fdf9a60065b 204 return revents;
kadonotakashi 0:8fdf9a60065b 205 }
kadonotakashi 0:8fdf9a60065b 206 #endif
kadonotakashi 0:8fdf9a60065b 207
kadonotakashi 0:8fdf9a60065b 208 class Sink : public FileHandle {
kadonotakashi 0:8fdf9a60065b 209 public:
kadonotakashi 0:8fdf9a60065b 210 virtual ssize_t write(const void *buffer, size_t size);
kadonotakashi 0:8fdf9a60065b 211 virtual ssize_t read(void *buffer, size_t size);
kadonotakashi 0:8fdf9a60065b 212 virtual off_t seek(off_t offset, int whence = SEEK_SET)
kadonotakashi 0:8fdf9a60065b 213 {
kadonotakashi 0:8fdf9a60065b 214 return ESPIPE;
kadonotakashi 0:8fdf9a60065b 215 }
kadonotakashi 0:8fdf9a60065b 216 virtual off_t size()
kadonotakashi 0:8fdf9a60065b 217 {
kadonotakashi 0:8fdf9a60065b 218 return -EINVAL;
kadonotakashi 0:8fdf9a60065b 219 }
kadonotakashi 0:8fdf9a60065b 220 virtual int isatty()
kadonotakashi 0:8fdf9a60065b 221 {
kadonotakashi 0:8fdf9a60065b 222 return true;
kadonotakashi 0:8fdf9a60065b 223 }
kadonotakashi 0:8fdf9a60065b 224 virtual int close()
kadonotakashi 0:8fdf9a60065b 225 {
kadonotakashi 0:8fdf9a60065b 226 return 0;
kadonotakashi 0:8fdf9a60065b 227 }
kadonotakashi 0:8fdf9a60065b 228 };
kadonotakashi 0:8fdf9a60065b 229
kadonotakashi 0:8fdf9a60065b 230 ssize_t Sink::write(const void *buffer, size_t size)
kadonotakashi 0:8fdf9a60065b 231 {
kadonotakashi 0:8fdf9a60065b 232 // Just swallow the data - this is historical non-DEVICE_SERIAL behaviour
kadonotakashi 0:8fdf9a60065b 233 return size;
kadonotakashi 0:8fdf9a60065b 234 }
kadonotakashi 0:8fdf9a60065b 235
kadonotakashi 0:8fdf9a60065b 236 ssize_t Sink::read(void *buffer, size_t size)
kadonotakashi 0:8fdf9a60065b 237 {
kadonotakashi 0:8fdf9a60065b 238 // Produce 1 zero byte - historical behaviour returned 1 without touching
kadonotakashi 0:8fdf9a60065b 239 // the buffer
kadonotakashi 0:8fdf9a60065b 240 unsigned char *buf = static_cast<unsigned char *>(buffer);
kadonotakashi 0:8fdf9a60065b 241 buf[0] = 0;
kadonotakashi 0:8fdf9a60065b 242 return 1;
kadonotakashi 0:8fdf9a60065b 243 }
kadonotakashi 0:8fdf9a60065b 244
kadonotakashi 0:8fdf9a60065b 245
kadonotakashi 0:8fdf9a60065b 246 MBED_WEAK FileHandle *mbed::mbed_target_override_console(int fd)
kadonotakashi 0:8fdf9a60065b 247 {
kadonotakashi 0:8fdf9a60065b 248 return NULL;
kadonotakashi 0:8fdf9a60065b 249 }
kadonotakashi 0:8fdf9a60065b 250
kadonotakashi 0:8fdf9a60065b 251 MBED_WEAK FileHandle *mbed::mbed_override_console(int fd)
kadonotakashi 0:8fdf9a60065b 252 {
kadonotakashi 0:8fdf9a60065b 253 return NULL;
kadonotakashi 0:8fdf9a60065b 254 }
kadonotakashi 0:8fdf9a60065b 255
kadonotakashi 0:8fdf9a60065b 256 static FileHandle *default_console()
kadonotakashi 0:8fdf9a60065b 257 {
kadonotakashi 0:8fdf9a60065b 258 #if DEVICE_SERIAL
kadonotakashi 0:8fdf9a60065b 259 # if MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL
kadonotakashi 0:8fdf9a60065b 260 static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
kadonotakashi 0:8fdf9a60065b 261 # if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
kadonotakashi 0:8fdf9a60065b 262 console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
kadonotakashi 0:8fdf9a60065b 263 # elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
kadonotakashi 0:8fdf9a60065b 264 console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
kadonotakashi 0:8fdf9a60065b 265 # elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
kadonotakashi 0:8fdf9a60065b 266 console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
kadonotakashi 0:8fdf9a60065b 267 # endif
kadonotakashi 0:8fdf9a60065b 268 # else
kadonotakashi 0:8fdf9a60065b 269 static DirectSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
kadonotakashi 0:8fdf9a60065b 270 # endif
kadonotakashi 0:8fdf9a60065b 271 #else // DEVICE_SERIAL
kadonotakashi 0:8fdf9a60065b 272 static Sink console;
kadonotakashi 0:8fdf9a60065b 273 #endif
kadonotakashi 0:8fdf9a60065b 274 return &console;
kadonotakashi 0:8fdf9a60065b 275 }
kadonotakashi 0:8fdf9a60065b 276
kadonotakashi 0:8fdf9a60065b 277 /* Locate the default console for stdout, stdin, stderr */
kadonotakashi 0:8fdf9a60065b 278 static FileHandle *get_console(int fd)
kadonotakashi 0:8fdf9a60065b 279 {
kadonotakashi 0:8fdf9a60065b 280 FileHandle *fh = mbed_override_console(fd);
kadonotakashi 0:8fdf9a60065b 281 if (fh) {
kadonotakashi 0:8fdf9a60065b 282 return fh;
kadonotakashi 0:8fdf9a60065b 283 }
kadonotakashi 0:8fdf9a60065b 284 fh = mbed_target_override_console(fd);
kadonotakashi 0:8fdf9a60065b 285 if (fh) {
kadonotakashi 0:8fdf9a60065b 286 return fh;
kadonotakashi 0:8fdf9a60065b 287 }
kadonotakashi 0:8fdf9a60065b 288 return default_console();
kadonotakashi 0:8fdf9a60065b 289 }
kadonotakashi 0:8fdf9a60065b 290
kadonotakashi 0:8fdf9a60065b 291 /* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
kadonotakashi 0:8fdf9a60065b 292 static FileHandle *get_fhc(int fd)
kadonotakashi 0:8fdf9a60065b 293 {
kadonotakashi 0:8fdf9a60065b 294 if (fd >= OPEN_MAX) {
kadonotakashi 0:8fdf9a60065b 295 return NULL;
kadonotakashi 0:8fdf9a60065b 296 }
kadonotakashi 0:8fdf9a60065b 297 FileHandle *fh = filehandles[fd];
kadonotakashi 0:8fdf9a60065b 298 if (fh == FILE_HANDLE_RESERVED && fd < 3) {
kadonotakashi 0:8fdf9a60065b 299 filehandles[fd] = fh = get_console(fd);
kadonotakashi 0:8fdf9a60065b 300 }
kadonotakashi 0:8fdf9a60065b 301 return fh;
kadonotakashi 0:8fdf9a60065b 302 }
kadonotakashi 0:8fdf9a60065b 303
kadonotakashi 0:8fdf9a60065b 304 /**
kadonotakashi 0:8fdf9a60065b 305 * Sets errno when file opening fails.
kadonotakashi 0:8fdf9a60065b 306 * Wipes out the filehandle too.
kadonotakashi 0:8fdf9a60065b 307 *
kadonotakashi 0:8fdf9a60065b 308 * @param error is a negative error code returned from an mbed function and
kadonotakashi 0:8fdf9a60065b 309 * will be negated to store a positive error code in errno
kadonotakashi 0:8fdf9a60065b 310 */
kadonotakashi 0:8fdf9a60065b 311 static int handle_open_errors(int error, unsigned filehandle_idx)
kadonotakashi 0:8fdf9a60065b 312 {
kadonotakashi 0:8fdf9a60065b 313 errno = -error;
kadonotakashi 0:8fdf9a60065b 314 // Free file handle
kadonotakashi 0:8fdf9a60065b 315 filehandles[filehandle_idx] = NULL;
kadonotakashi 0:8fdf9a60065b 316 return -1;
kadonotakashi 0:8fdf9a60065b 317 }
kadonotakashi 0:8fdf9a60065b 318
kadonotakashi 0:8fdf9a60065b 319 static inline int openflags_to_posix(int openflags)
kadonotakashi 0:8fdf9a60065b 320 {
kadonotakashi 0:8fdf9a60065b 321 int posix = openflags;
kadonotakashi 0:8fdf9a60065b 322 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 323 if (openflags & OPEN_PLUS) {
kadonotakashi 0:8fdf9a60065b 324 posix = O_RDWR;
kadonotakashi 0:8fdf9a60065b 325 } else if (openflags & OPEN_W) {
kadonotakashi 0:8fdf9a60065b 326 posix = O_WRONLY;
kadonotakashi 0:8fdf9a60065b 327 } else if (openflags & OPEN_A) {
kadonotakashi 0:8fdf9a60065b 328 posix = O_WRONLY | O_APPEND;
kadonotakashi 0:8fdf9a60065b 329 } else {
kadonotakashi 0:8fdf9a60065b 330 posix = O_RDONLY;
kadonotakashi 0:8fdf9a60065b 331 }
kadonotakashi 0:8fdf9a60065b 332 /* a, w, a+, w+ all create if file does not already exist */
kadonotakashi 0:8fdf9a60065b 333 if (openflags & (OPEN_A | OPEN_W)) {
kadonotakashi 0:8fdf9a60065b 334 posix |= O_CREAT;
kadonotakashi 0:8fdf9a60065b 335 }
kadonotakashi 0:8fdf9a60065b 336 /* w and w+ truncate */
kadonotakashi 0:8fdf9a60065b 337 if (openflags & OPEN_W) {
kadonotakashi 0:8fdf9a60065b 338 posix |= O_TRUNC;
kadonotakashi 0:8fdf9a60065b 339 }
kadonotakashi 0:8fdf9a60065b 340 #elif defined(__ICCARM__)
kadonotakashi 0:8fdf9a60065b 341 switch (openflags & _LLIO_RDWRMASK) {
kadonotakashi 0:8fdf9a60065b 342 case _LLIO_RDONLY:
kadonotakashi 0:8fdf9a60065b 343 posix = O_RDONLY;
kadonotakashi 0:8fdf9a60065b 344 break;
kadonotakashi 0:8fdf9a60065b 345 case _LLIO_WRONLY:
kadonotakashi 0:8fdf9a60065b 346 posix = O_WRONLY;
kadonotakashi 0:8fdf9a60065b 347 break;
kadonotakashi 0:8fdf9a60065b 348 case _LLIO_RDWR :
kadonotakashi 0:8fdf9a60065b 349 posix = O_RDWR ;
kadonotakashi 0:8fdf9a60065b 350 break;
kadonotakashi 0:8fdf9a60065b 351 }
kadonotakashi 0:8fdf9a60065b 352 if (openflags & _LLIO_CREAT) {
kadonotakashi 0:8fdf9a60065b 353 posix |= O_CREAT;
kadonotakashi 0:8fdf9a60065b 354 }
kadonotakashi 0:8fdf9a60065b 355 if (openflags & _LLIO_APPEND) {
kadonotakashi 0:8fdf9a60065b 356 posix |= O_APPEND;
kadonotakashi 0:8fdf9a60065b 357 }
kadonotakashi 0:8fdf9a60065b 358 if (openflags & _LLIO_TRUNC) {
kadonotakashi 0:8fdf9a60065b 359 posix |= O_TRUNC;
kadonotakashi 0:8fdf9a60065b 360 }
kadonotakashi 0:8fdf9a60065b 361 #elif defined(TOOLCHAIN_GCC)
kadonotakashi 0:8fdf9a60065b 362 posix &= ~O_BINARY;
kadonotakashi 0:8fdf9a60065b 363 #endif
kadonotakashi 0:8fdf9a60065b 364 return posix;
kadonotakashi 0:8fdf9a60065b 365 }
kadonotakashi 0:8fdf9a60065b 366
kadonotakashi 0:8fdf9a60065b 367 static int reserve_filehandle()
kadonotakashi 0:8fdf9a60065b 368 {
kadonotakashi 0:8fdf9a60065b 369 // find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr
kadonotakashi 0:8fdf9a60065b 370 filehandle_mutex->lock();
kadonotakashi 0:8fdf9a60065b 371 int fh_i;
kadonotakashi 0:8fdf9a60065b 372 for (fh_i = 3; fh_i < OPEN_MAX; fh_i++) {
kadonotakashi 0:8fdf9a60065b 373 /* Take a next free filehandle slot available. */
kadonotakashi 0:8fdf9a60065b 374 if (filehandles[fh_i] == NULL) {
kadonotakashi 0:8fdf9a60065b 375 break;
kadonotakashi 0:8fdf9a60065b 376 }
kadonotakashi 0:8fdf9a60065b 377 }
kadonotakashi 0:8fdf9a60065b 378 if (fh_i >= OPEN_MAX) {
kadonotakashi 0:8fdf9a60065b 379 /* Too many file handles have been opened */
kadonotakashi 0:8fdf9a60065b 380 errno = EMFILE;
kadonotakashi 0:8fdf9a60065b 381 filehandle_mutex->unlock();
kadonotakashi 0:8fdf9a60065b 382 return -1;
kadonotakashi 0:8fdf9a60065b 383 }
kadonotakashi 0:8fdf9a60065b 384 filehandles[fh_i] = FILE_HANDLE_RESERVED;
kadonotakashi 0:8fdf9a60065b 385 filehandle_mutex->unlock();
kadonotakashi 0:8fdf9a60065b 386
kadonotakashi 0:8fdf9a60065b 387 return fh_i;
kadonotakashi 0:8fdf9a60065b 388 }
kadonotakashi 0:8fdf9a60065b 389
kadonotakashi 0:8fdf9a60065b 390 int mbed::bind_to_fd(FileHandle *fh)
kadonotakashi 0:8fdf9a60065b 391 {
kadonotakashi 0:8fdf9a60065b 392 int fildes = reserve_filehandle();
kadonotakashi 0:8fdf9a60065b 393 if (fildes < 0) {
kadonotakashi 0:8fdf9a60065b 394 return fildes;
kadonotakashi 0:8fdf9a60065b 395 }
kadonotakashi 0:8fdf9a60065b 396
kadonotakashi 0:8fdf9a60065b 397 filehandles[fildes] = fh;
kadonotakashi 0:8fdf9a60065b 398 stdio_in_prev[fildes] = 0;
kadonotakashi 0:8fdf9a60065b 399 stdio_out_prev[fildes] = 0;
kadonotakashi 0:8fdf9a60065b 400
kadonotakashi 0:8fdf9a60065b 401 return fildes;
kadonotakashi 0:8fdf9a60065b 402 }
kadonotakashi 0:8fdf9a60065b 403
kadonotakashi 0:8fdf9a60065b 404 static int unbind_from_fd(int fd, FileHandle *fh)
kadonotakashi 0:8fdf9a60065b 405 {
kadonotakashi 0:8fdf9a60065b 406 if (filehandles[fd] == fh) {
kadonotakashi 0:8fdf9a60065b 407 filehandles[fd] = NULL;
kadonotakashi 0:8fdf9a60065b 408 return 0;
kadonotakashi 0:8fdf9a60065b 409 } else {
kadonotakashi 0:8fdf9a60065b 410 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 411 return -1;
kadonotakashi 0:8fdf9a60065b 412 }
kadonotakashi 0:8fdf9a60065b 413 }
kadonotakashi 0:8fdf9a60065b 414
kadonotakashi 0:8fdf9a60065b 415 #ifndef __IAR_SYSTEMS_ICC__
kadonotakashi 0:8fdf9a60065b 416 /* IAR provides fdopen itself */
kadonotakashi 0:8fdf9a60065b 417 extern "C" std::FILE *fdopen(int fildes, const char *mode)
kadonotakashi 0:8fdf9a60065b 418 {
kadonotakashi 0:8fdf9a60065b 419 // This is to avoid scanf and the bloat it brings.
kadonotakashi 0:8fdf9a60065b 420 char buf[1 + sizeof fildes]; /* @(integer) */
kadonotakashi 0:8fdf9a60065b 421 MBED_STATIC_ASSERT(sizeof buf == 5, "Integers should be 4 bytes.");
kadonotakashi 0:8fdf9a60065b 422 buf[0] = '@';
kadonotakashi 0:8fdf9a60065b 423 memcpy(buf + 1, &fildes, sizeof fildes);
kadonotakashi 0:8fdf9a60065b 424
kadonotakashi 0:8fdf9a60065b 425 std::FILE *stream = std::fopen(buf, mode);
kadonotakashi 0:8fdf9a60065b 426 /* newlib-nano doesn't appear to ever call _isatty itself, so
kadonotakashi 0:8fdf9a60065b 427 * happily fully buffers an interactive stream. Deal with that here.
kadonotakashi 0:8fdf9a60065b 428 */
kadonotakashi 0:8fdf9a60065b 429 if (stream && isatty(fildes)) {
kadonotakashi 0:8fdf9a60065b 430 mbed_set_unbuffered_stream(stream);
kadonotakashi 0:8fdf9a60065b 431 }
kadonotakashi 0:8fdf9a60065b 432 return stream;
kadonotakashi 0:8fdf9a60065b 433 }
kadonotakashi 0:8fdf9a60065b 434 #endif
kadonotakashi 0:8fdf9a60065b 435
kadonotakashi 0:8fdf9a60065b 436 namespace mbed {
kadonotakashi 0:8fdf9a60065b 437 std::FILE *fdopen(FileHandle *fh, const char *mode)
kadonotakashi 0:8fdf9a60065b 438 {
kadonotakashi 0:8fdf9a60065b 439 // First reserve the integer file descriptor
kadonotakashi 0:8fdf9a60065b 440 int fd = bind_to_fd(fh);
kadonotakashi 0:8fdf9a60065b 441 if (!fd) {
kadonotakashi 0:8fdf9a60065b 442 return NULL;
kadonotakashi 0:8fdf9a60065b 443 }
kadonotakashi 0:8fdf9a60065b 444 // Then bind that to the C stream. If successful, C library
kadonotakashi 0:8fdf9a60065b 445 // takes ownership and responsibility to close.
kadonotakashi 0:8fdf9a60065b 446 std::FILE *stream = ::fdopen(fd, mode);
kadonotakashi 0:8fdf9a60065b 447 if (!stream) {
kadonotakashi 0:8fdf9a60065b 448 unbind_from_fd(fd, fh);
kadonotakashi 0:8fdf9a60065b 449 }
kadonotakashi 0:8fdf9a60065b 450 return stream;
kadonotakashi 0:8fdf9a60065b 451 }
kadonotakashi 0:8fdf9a60065b 452 }
kadonotakashi 0:8fdf9a60065b 453
kadonotakashi 0:8fdf9a60065b 454 /* @brief standard c library fopen() retargeting function.
kadonotakashi 0:8fdf9a60065b 455 *
kadonotakashi 0:8fdf9a60065b 456 * This function is invoked by the standard c library retargeting to handle fopen()
kadonotakashi 0:8fdf9a60065b 457 *
kadonotakashi 0:8fdf9a60065b 458 * @return
kadonotakashi 0:8fdf9a60065b 459 * On success, a valid FILEHANDLE is returned.
kadonotakashi 0:8fdf9a60065b 460 * On failure, -1 is returned and errno is set to an appropriate value e.g.
kadonotakashi 0:8fdf9a60065b 461 * ENOENT file not found (default errno setting)
kadonotakashi 0:8fdf9a60065b 462 * EMFILE the maximum number of open files was exceeded.
kadonotakashi 0:8fdf9a60065b 463 *
kadonotakashi 0:8fdf9a60065b 464 * */
kadonotakashi 0:8fdf9a60065b 465 extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
kadonotakashi 0:8fdf9a60065b 466 {
kadonotakashi 0:8fdf9a60065b 467 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
kadonotakashi 0:8fdf9a60065b 468 #if !defined(MBED_CONF_RTOS_PRESENT)
kadonotakashi 0:8fdf9a60065b 469 // valid only for mbed 2
kadonotakashi 0:8fdf9a60065b 470 // for ulib, this is invoked after RAM init, prior c++
kadonotakashi 0:8fdf9a60065b 471 // used as hook, as post stack/heap is not active there
kadonotakashi 0:8fdf9a60065b 472 extern void mbed_copy_nvic(void);
kadonotakashi 0:8fdf9a60065b 473 extern void mbed_sdk_init(void);
kadonotakashi 0:8fdf9a60065b 474
kadonotakashi 0:8fdf9a60065b 475 static int mbed_sdk_inited = 0;
kadonotakashi 0:8fdf9a60065b 476 if (!mbed_sdk_inited) {
kadonotakashi 0:8fdf9a60065b 477 mbed_copy_nvic();
kadonotakashi 0:8fdf9a60065b 478 mbed_sdk_init();
kadonotakashi 0:8fdf9a60065b 479 mbed_sdk_inited = 1;
kadonotakashi 0:8fdf9a60065b 480 }
kadonotakashi 0:8fdf9a60065b 481 #endif
kadonotakashi 0:8fdf9a60065b 482 // Before version 5.03, we were using a patched version of microlib with proper names
kadonotakashi 0:8fdf9a60065b 483 // This is the workaround that the microlib author suggested us
kadonotakashi 0:8fdf9a60065b 484 static int n = 0;
kadonotakashi 0:8fdf9a60065b 485 if (std::strcmp(name, ":tt") == 0 && n < 3) {
kadonotakashi 0:8fdf9a60065b 486 return n++;
kadonotakashi 0:8fdf9a60065b 487 }
kadonotakashi 0:8fdf9a60065b 488 #else
kadonotakashi 0:8fdf9a60065b 489 /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
kadonotakashi 0:8fdf9a60065b 490 */
kadonotakashi 0:8fdf9a60065b 491 if (std::strcmp(name, __stdin_name) == 0) {
kadonotakashi 0:8fdf9a60065b 492 get_fhc(STDIN_FILENO);
kadonotakashi 0:8fdf9a60065b 493 return STDIN_FILENO;
kadonotakashi 0:8fdf9a60065b 494 } else if (std::strcmp(name, __stdout_name) == 0) {
kadonotakashi 0:8fdf9a60065b 495 get_fhc(STDOUT_FILENO);
kadonotakashi 0:8fdf9a60065b 496 return STDOUT_FILENO;
kadonotakashi 0:8fdf9a60065b 497 } else if (std::strcmp(name, __stderr_name) == 0) {
kadonotakashi 0:8fdf9a60065b 498 get_fhc(STDERR_FILENO);
kadonotakashi 0:8fdf9a60065b 499 return STDERR_FILENO;
kadonotakashi 0:8fdf9a60065b 500 }
kadonotakashi 0:8fdf9a60065b 501 #endif
kadonotakashi 0:8fdf9a60065b 502 #ifndef __IAR_SYSTEMS_ICC__
kadonotakashi 0:8fdf9a60065b 503 /* FILENAME: "@(integer)" gives an already-allocated descriptor */
kadonotakashi 0:8fdf9a60065b 504 if (name[0] == '@') {
kadonotakashi 0:8fdf9a60065b 505 int fd;
kadonotakashi 0:8fdf9a60065b 506 memcpy(&fd, name + 1, sizeof fd);
kadonotakashi 0:8fdf9a60065b 507 return fd;
kadonotakashi 0:8fdf9a60065b 508 }
kadonotakashi 0:8fdf9a60065b 509 #endif
kadonotakashi 0:8fdf9a60065b 510 return open(name, openflags_to_posix(openflags));
kadonotakashi 0:8fdf9a60065b 511 }
kadonotakashi 0:8fdf9a60065b 512
kadonotakashi 0:8fdf9a60065b 513 extern "C" int open(const char *name, int oflag, ...)
kadonotakashi 0:8fdf9a60065b 514 {
kadonotakashi 0:8fdf9a60065b 515 int fildes = reserve_filehandle();
kadonotakashi 0:8fdf9a60065b 516 if (fildes < 0) {
kadonotakashi 0:8fdf9a60065b 517 return fildes;
kadonotakashi 0:8fdf9a60065b 518 }
kadonotakashi 0:8fdf9a60065b 519
kadonotakashi 0:8fdf9a60065b 520 FileHandle *res = NULL;
kadonotakashi 0:8fdf9a60065b 521 FilePath path(name);
kadonotakashi 0:8fdf9a60065b 522
kadonotakashi 0:8fdf9a60065b 523 if (!path.exists()) {
kadonotakashi 0:8fdf9a60065b 524 /* The first part of the filename (between first 2 '/') is not a
kadonotakashi 0:8fdf9a60065b 525 * registered mount point in the namespace.
kadonotakashi 0:8fdf9a60065b 526 */
kadonotakashi 0:8fdf9a60065b 527 return handle_open_errors(-ENODEV, fildes);
kadonotakashi 0:8fdf9a60065b 528 }
kadonotakashi 0:8fdf9a60065b 529
kadonotakashi 0:8fdf9a60065b 530 if (path.isFile()) {
kadonotakashi 0:8fdf9a60065b 531 res = path.file();
kadonotakashi 0:8fdf9a60065b 532 } else {
kadonotakashi 0:8fdf9a60065b 533 FileSystemHandle *fs = path.fileSystem();
kadonotakashi 0:8fdf9a60065b 534 if (fs == NULL) {
kadonotakashi 0:8fdf9a60065b 535 return handle_open_errors(-ENODEV, fildes);
kadonotakashi 0:8fdf9a60065b 536 }
kadonotakashi 0:8fdf9a60065b 537 int err = fs->open(&res, path.fileName(), oflag);
kadonotakashi 0:8fdf9a60065b 538 if (err) {
kadonotakashi 0:8fdf9a60065b 539 return handle_open_errors(err, fildes);
kadonotakashi 0:8fdf9a60065b 540 }
kadonotakashi 0:8fdf9a60065b 541 }
kadonotakashi 0:8fdf9a60065b 542
kadonotakashi 0:8fdf9a60065b 543 filehandles[fildes] = res;
kadonotakashi 0:8fdf9a60065b 544 stdio_in_prev[fildes] = 0;
kadonotakashi 0:8fdf9a60065b 545 stdio_out_prev[fildes] = 0;
kadonotakashi 0:8fdf9a60065b 546
kadonotakashi 0:8fdf9a60065b 547 return fildes;
kadonotakashi 0:8fdf9a60065b 548 }
kadonotakashi 0:8fdf9a60065b 549
kadonotakashi 0:8fdf9a60065b 550 extern "C" int PREFIX(_close)(FILEHANDLE fh)
kadonotakashi 0:8fdf9a60065b 551 {
kadonotakashi 0:8fdf9a60065b 552 return close(fh);
kadonotakashi 0:8fdf9a60065b 553 }
kadonotakashi 0:8fdf9a60065b 554
kadonotakashi 0:8fdf9a60065b 555 extern "C" int close(int fildes)
kadonotakashi 0:8fdf9a60065b 556 {
kadonotakashi 0:8fdf9a60065b 557 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 558 filehandles[fildes] = NULL;
kadonotakashi 0:8fdf9a60065b 559 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 560 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 561 return -1;
kadonotakashi 0:8fdf9a60065b 562 }
kadonotakashi 0:8fdf9a60065b 563
kadonotakashi 0:8fdf9a60065b 564 int err = fhc->close();
kadonotakashi 0:8fdf9a60065b 565 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 566 errno = -err;
kadonotakashi 0:8fdf9a60065b 567 return -1;
kadonotakashi 0:8fdf9a60065b 568 } else {
kadonotakashi 0:8fdf9a60065b 569 return 0;
kadonotakashi 0:8fdf9a60065b 570 }
kadonotakashi 0:8fdf9a60065b 571 }
kadonotakashi 0:8fdf9a60065b 572
kadonotakashi 0:8fdf9a60065b 573 static bool convert_crlf(int fd)
kadonotakashi 0:8fdf9a60065b 574 {
kadonotakashi 0:8fdf9a60065b 575 #if MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
kadonotakashi 0:8fdf9a60065b 576 return isatty(fd);
kadonotakashi 0:8fdf9a60065b 577 #elif MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
kadonotakashi 0:8fdf9a60065b 578 return fd < 3 && isatty(fd);
kadonotakashi 0:8fdf9a60065b 579 #else
kadonotakashi 0:8fdf9a60065b 580 return false;
kadonotakashi 0:8fdf9a60065b 581 #endif
kadonotakashi 0:8fdf9a60065b 582 }
kadonotakashi 0:8fdf9a60065b 583
kadonotakashi 0:8fdf9a60065b 584 #if defined(__ICCARM__)
kadonotakashi 0:8fdf9a60065b 585 extern "C" size_t __write(int fh, const unsigned char *buffer, size_t length)
kadonotakashi 0:8fdf9a60065b 586 {
kadonotakashi 0:8fdf9a60065b 587 #else
kadonotakashi 0:8fdf9a60065b 588 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode)
kadonotakashi 0:8fdf9a60065b 589 {
kadonotakashi 0:8fdf9a60065b 590 #endif
kadonotakashi 0:8fdf9a60065b 591
kadonotakashi 0:8fdf9a60065b 592 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
kadonotakashi 0:8fdf9a60065b 593 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
kadonotakashi 0:8fdf9a60065b 594 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);
kadonotakashi 0:8fdf9a60065b 595 }
kadonotakashi 0:8fdf9a60065b 596 #endif
kadonotakashi 0:8fdf9a60065b 597
kadonotakashi 0:8fdf9a60065b 598 if (length > SSIZE_MAX) {
kadonotakashi 0:8fdf9a60065b 599 errno = EINVAL;
kadonotakashi 0:8fdf9a60065b 600 return -1;
kadonotakashi 0:8fdf9a60065b 601 }
kadonotakashi 0:8fdf9a60065b 602
kadonotakashi 0:8fdf9a60065b 603 ssize_t slength = length;
kadonotakashi 0:8fdf9a60065b 604 ssize_t written = 0;
kadonotakashi 0:8fdf9a60065b 605
kadonotakashi 0:8fdf9a60065b 606 if (convert_crlf(fh)) {
kadonotakashi 0:8fdf9a60065b 607 // local prev is previous in buffer during seek
kadonotakashi 0:8fdf9a60065b 608 // stdio_out_prev[fh] is last thing actually written
kadonotakashi 0:8fdf9a60065b 609 char prev = stdio_out_prev[fh];
kadonotakashi 0:8fdf9a60065b 610 // Seek for '\n' without preceding '\r'; if found flush
kadonotakashi 0:8fdf9a60065b 611 // preceding and insert '\r'. Continue until end of input.
kadonotakashi 0:8fdf9a60065b 612 for (ssize_t cur = 0; cur < slength; cur++) {
kadonotakashi 0:8fdf9a60065b 613 if (buffer[cur] == '\n' && prev != '\r') {
kadonotakashi 0:8fdf9a60065b 614 ssize_t r;
kadonotakashi 0:8fdf9a60065b 615 // flush stuff preceding the \n
kadonotakashi 0:8fdf9a60065b 616 if (cur > written) {
kadonotakashi 0:8fdf9a60065b 617 r = write(fh, buffer + written, cur - written);
kadonotakashi 0:8fdf9a60065b 618 if (r < 0) {
kadonotakashi 0:8fdf9a60065b 619 return -1;
kadonotakashi 0:8fdf9a60065b 620 }
kadonotakashi 0:8fdf9a60065b 621 written += r;
kadonotakashi 0:8fdf9a60065b 622 if (written < cur) {
kadonotakashi 0:8fdf9a60065b 623 // For some reason, didn't write all - give up now
kadonotakashi 0:8fdf9a60065b 624 goto finish;
kadonotakashi 0:8fdf9a60065b 625 }
kadonotakashi 0:8fdf9a60065b 626 stdio_out_prev[fh] = prev;
kadonotakashi 0:8fdf9a60065b 627 }
kadonotakashi 0:8fdf9a60065b 628 // insert a \r now, leaving the \n still to be written
kadonotakashi 0:8fdf9a60065b 629 r = write(fh, "\r", 1);
kadonotakashi 0:8fdf9a60065b 630 if (r < 0) {
kadonotakashi 0:8fdf9a60065b 631 return -1;
kadonotakashi 0:8fdf9a60065b 632 }
kadonotakashi 0:8fdf9a60065b 633 if (r < 1) {
kadonotakashi 0:8fdf9a60065b 634 goto finish;
kadonotakashi 0:8fdf9a60065b 635 }
kadonotakashi 0:8fdf9a60065b 636 stdio_out_prev[fh] = '\r';
kadonotakashi 0:8fdf9a60065b 637 }
kadonotakashi 0:8fdf9a60065b 638 prev = buffer[cur];
kadonotakashi 0:8fdf9a60065b 639 }
kadonotakashi 0:8fdf9a60065b 640 }
kadonotakashi 0:8fdf9a60065b 641
kadonotakashi 0:8fdf9a60065b 642 // Flush remaining from conversion, or the whole thing if no conversion
kadonotakashi 0:8fdf9a60065b 643 if (written < slength) {
kadonotakashi 0:8fdf9a60065b 644 ssize_t r = write(fh, buffer + written, slength - written);
kadonotakashi 0:8fdf9a60065b 645 if (r < 0) {
kadonotakashi 0:8fdf9a60065b 646 return -1;
kadonotakashi 0:8fdf9a60065b 647 }
kadonotakashi 0:8fdf9a60065b 648 written += r;
kadonotakashi 0:8fdf9a60065b 649 if (written > 0) {
kadonotakashi 0:8fdf9a60065b 650 stdio_out_prev[fh] = buffer[written - 1];
kadonotakashi 0:8fdf9a60065b 651 }
kadonotakashi 0:8fdf9a60065b 652 }
kadonotakashi 0:8fdf9a60065b 653
kadonotakashi 0:8fdf9a60065b 654 finish:
kadonotakashi 0:8fdf9a60065b 655 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 656 if (written >= 0) {
kadonotakashi 0:8fdf9a60065b 657 return slength - written;
kadonotakashi 0:8fdf9a60065b 658 } else {
kadonotakashi 0:8fdf9a60065b 659 return written;
kadonotakashi 0:8fdf9a60065b 660 }
kadonotakashi 0:8fdf9a60065b 661 #else
kadonotakashi 0:8fdf9a60065b 662 return written;
kadonotakashi 0:8fdf9a60065b 663 #endif
kadonotakashi 0:8fdf9a60065b 664 }
kadonotakashi 0:8fdf9a60065b 665
kadonotakashi 0:8fdf9a60065b 666 extern "C" ssize_t write(int fildes, const void *buf, size_t length)
kadonotakashi 0:8fdf9a60065b 667 {
kadonotakashi 0:8fdf9a60065b 668
kadonotakashi 0:8fdf9a60065b 669 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 670 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 671 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 672 return -1;
kadonotakashi 0:8fdf9a60065b 673 }
kadonotakashi 0:8fdf9a60065b 674
kadonotakashi 0:8fdf9a60065b 675 ssize_t ret = fhc->write(buf, length);
kadonotakashi 0:8fdf9a60065b 676 if (ret < 0) {
kadonotakashi 0:8fdf9a60065b 677 errno = -ret;
kadonotakashi 0:8fdf9a60065b 678 return -1;
kadonotakashi 0:8fdf9a60065b 679 } else {
kadonotakashi 0:8fdf9a60065b 680 return ret;
kadonotakashi 0:8fdf9a60065b 681 }
kadonotakashi 0:8fdf9a60065b 682 }
kadonotakashi 0:8fdf9a60065b 683
kadonotakashi 0:8fdf9a60065b 684 #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
kadonotakashi 0:8fdf9a60065b 685 extern "C" void PREFIX(_exit)(int return_code)
kadonotakashi 0:8fdf9a60065b 686 {
kadonotakashi 0:8fdf9a60065b 687 while (1) {}
kadonotakashi 0:8fdf9a60065b 688 }
kadonotakashi 0:8fdf9a60065b 689
kadonotakashi 0:8fdf9a60065b 690 extern "C" void _ttywrch(int ch)
kadonotakashi 0:8fdf9a60065b 691 {
kadonotakashi 0:8fdf9a60065b 692 char c = ch;
kadonotakashi 0:8fdf9a60065b 693 write(STDOUT_FILENO, &c, 1);
kadonotakashi 0:8fdf9a60065b 694 }
kadonotakashi 0:8fdf9a60065b 695 #endif
kadonotakashi 0:8fdf9a60065b 696
kadonotakashi 0:8fdf9a60065b 697 #if defined(__ICCARM__)
kadonotakashi 0:8fdf9a60065b 698 extern "C" size_t __read(int fh, unsigned char *buffer, size_t length)
kadonotakashi 0:8fdf9a60065b 699 {
kadonotakashi 0:8fdf9a60065b 700 #else
kadonotakashi 0:8fdf9a60065b 701 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode)
kadonotakashi 0:8fdf9a60065b 702 {
kadonotakashi 0:8fdf9a60065b 703 #endif
kadonotakashi 0:8fdf9a60065b 704
kadonotakashi 0:8fdf9a60065b 705 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
kadonotakashi 0:8fdf9a60065b 706 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
kadonotakashi 0:8fdf9a60065b 707 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);
kadonotakashi 0:8fdf9a60065b 708 }
kadonotakashi 0:8fdf9a60065b 709 #endif
kadonotakashi 0:8fdf9a60065b 710
kadonotakashi 0:8fdf9a60065b 711 if (length > SSIZE_MAX) {
kadonotakashi 0:8fdf9a60065b 712 errno = EINVAL;
kadonotakashi 0:8fdf9a60065b 713 return -1;
kadonotakashi 0:8fdf9a60065b 714 }
kadonotakashi 0:8fdf9a60065b 715
kadonotakashi 0:8fdf9a60065b 716 ssize_t bytes_read = 0;
kadonotakashi 0:8fdf9a60065b 717
kadonotakashi 0:8fdf9a60065b 718 if (convert_crlf(fh)) {
kadonotakashi 0:8fdf9a60065b 719 while (true) {
kadonotakashi 0:8fdf9a60065b 720 char c;
kadonotakashi 0:8fdf9a60065b 721 ssize_t r = read(fh, &c, 1);
kadonotakashi 0:8fdf9a60065b 722 if (r < 0) {
kadonotakashi 0:8fdf9a60065b 723 return -1;
kadonotakashi 0:8fdf9a60065b 724 }
kadonotakashi 0:8fdf9a60065b 725 if (r == 0) {
kadonotakashi 0:8fdf9a60065b 726 return bytes_read;
kadonotakashi 0:8fdf9a60065b 727 }
kadonotakashi 0:8fdf9a60065b 728 if ((c == '\r' && stdio_in_prev[fh] != '\n') ||
kadonotakashi 0:8fdf9a60065b 729 (c == '\n' && stdio_in_prev[fh] != '\r')) {
kadonotakashi 0:8fdf9a60065b 730 stdio_in_prev[fh] = c;
kadonotakashi 0:8fdf9a60065b 731 *buffer = '\n';
kadonotakashi 0:8fdf9a60065b 732 break;
kadonotakashi 0:8fdf9a60065b 733 } else if ((c == '\r' && stdio_in_prev[fh] == '\n') ||
kadonotakashi 0:8fdf9a60065b 734 (c == '\n' && stdio_in_prev[fh] == '\r')) {
kadonotakashi 0:8fdf9a60065b 735 stdio_in_prev[fh] = c;
kadonotakashi 0:8fdf9a60065b 736 continue;
kadonotakashi 0:8fdf9a60065b 737 } else {
kadonotakashi 0:8fdf9a60065b 738 stdio_in_prev[fh] = c;
kadonotakashi 0:8fdf9a60065b 739 *buffer = c;
kadonotakashi 0:8fdf9a60065b 740 break;
kadonotakashi 0:8fdf9a60065b 741 }
kadonotakashi 0:8fdf9a60065b 742 }
kadonotakashi 0:8fdf9a60065b 743 bytes_read = 1;
kadonotakashi 0:8fdf9a60065b 744 } else {
kadonotakashi 0:8fdf9a60065b 745 bytes_read = read(fh, buffer, length);
kadonotakashi 0:8fdf9a60065b 746 }
kadonotakashi 0:8fdf9a60065b 747
kadonotakashi 0:8fdf9a60065b 748 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 749 if (bytes_read < 0) {
kadonotakashi 0:8fdf9a60065b 750 return -1;
kadonotakashi 0:8fdf9a60065b 751 } else if (bytes_read == 0) {
kadonotakashi 0:8fdf9a60065b 752 return 0x80000000 | length; // weird EOF indication
kadonotakashi 0:8fdf9a60065b 753 } else {
kadonotakashi 0:8fdf9a60065b 754 return (ssize_t)length - bytes_read;
kadonotakashi 0:8fdf9a60065b 755 }
kadonotakashi 0:8fdf9a60065b 756 #else
kadonotakashi 0:8fdf9a60065b 757 return bytes_read;
kadonotakashi 0:8fdf9a60065b 758 #endif
kadonotakashi 0:8fdf9a60065b 759 }
kadonotakashi 0:8fdf9a60065b 760
kadonotakashi 0:8fdf9a60065b 761 extern "C" ssize_t read(int fildes, void *buf, size_t length)
kadonotakashi 0:8fdf9a60065b 762 {
kadonotakashi 0:8fdf9a60065b 763
kadonotakashi 0:8fdf9a60065b 764 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 765 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 766 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 767 return -1;
kadonotakashi 0:8fdf9a60065b 768 }
kadonotakashi 0:8fdf9a60065b 769
kadonotakashi 0:8fdf9a60065b 770 ssize_t ret = fhc->read(buf, length);
kadonotakashi 0:8fdf9a60065b 771 if (ret < 0) {
kadonotakashi 0:8fdf9a60065b 772 errno = -ret;
kadonotakashi 0:8fdf9a60065b 773 return -1;
kadonotakashi 0:8fdf9a60065b 774 } else {
kadonotakashi 0:8fdf9a60065b 775 return ret;
kadonotakashi 0:8fdf9a60065b 776 }
kadonotakashi 0:8fdf9a60065b 777 }
kadonotakashi 0:8fdf9a60065b 778
kadonotakashi 0:8fdf9a60065b 779
kadonotakashi 0:8fdf9a60065b 780 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 781 extern "C" int PREFIX(_istty)(FILEHANDLE fh)
kadonotakashi 0:8fdf9a60065b 782 #else
kadonotakashi 0:8fdf9a60065b 783 extern "C" int _isatty(FILEHANDLE fh)
kadonotakashi 0:8fdf9a60065b 784 #endif
kadonotakashi 0:8fdf9a60065b 785 {
kadonotakashi 0:8fdf9a60065b 786 return isatty(fh);
kadonotakashi 0:8fdf9a60065b 787 }
kadonotakashi 0:8fdf9a60065b 788
kadonotakashi 0:8fdf9a60065b 789 extern "C" int isatty(int fildes)
kadonotakashi 0:8fdf9a60065b 790 {
kadonotakashi 0:8fdf9a60065b 791 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 792 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 793 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 794 return 0;
kadonotakashi 0:8fdf9a60065b 795 }
kadonotakashi 0:8fdf9a60065b 796
kadonotakashi 0:8fdf9a60065b 797 int tty = fhc->isatty();
kadonotakashi 0:8fdf9a60065b 798 if (tty < 0) {
kadonotakashi 0:8fdf9a60065b 799 errno = -tty;
kadonotakashi 0:8fdf9a60065b 800 return 0;
kadonotakashi 0:8fdf9a60065b 801 } else {
kadonotakashi 0:8fdf9a60065b 802 return tty;
kadonotakashi 0:8fdf9a60065b 803 }
kadonotakashi 0:8fdf9a60065b 804 }
kadonotakashi 0:8fdf9a60065b 805
kadonotakashi 0:8fdf9a60065b 806 extern "C"
kadonotakashi 0:8fdf9a60065b 807 #if defined(__ARMCC_VERSION)
kadonotakashi 0:8fdf9a60065b 808 int _sys_seek(FILEHANDLE fh, long offset)
kadonotakashi 0:8fdf9a60065b 809 #elif defined(__ICCARM__)
kadonotakashi 0:8fdf9a60065b 810 long __lseek(int fh, long offset, int whence)
kadonotakashi 0:8fdf9a60065b 811 #else
kadonotakashi 0:8fdf9a60065b 812 int _lseek(FILEHANDLE fh, int offset, int whence)
kadonotakashi 0:8fdf9a60065b 813 #endif
kadonotakashi 0:8fdf9a60065b 814 {
kadonotakashi 0:8fdf9a60065b 815 #if defined(__ARMCC_VERSION)
kadonotakashi 0:8fdf9a60065b 816 int whence = SEEK_SET;
kadonotakashi 0:8fdf9a60065b 817 #endif
kadonotakashi 0:8fdf9a60065b 818
kadonotakashi 0:8fdf9a60065b 819 off_t off = lseek(fh, offset, whence);
kadonotakashi 0:8fdf9a60065b 820 // Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference
kadonotakashi 0:8fdf9a60065b 821 if (off > INT_MAX) {
kadonotakashi 0:8fdf9a60065b 822 errno = EOVERFLOW;
kadonotakashi 0:8fdf9a60065b 823 return -1;
kadonotakashi 0:8fdf9a60065b 824 }
kadonotakashi 0:8fdf9a60065b 825 return off;
kadonotakashi 0:8fdf9a60065b 826 }
kadonotakashi 0:8fdf9a60065b 827
kadonotakashi 0:8fdf9a60065b 828 extern "C" off_t lseek(int fildes, off_t offset, int whence)
kadonotakashi 0:8fdf9a60065b 829 {
kadonotakashi 0:8fdf9a60065b 830 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 831 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 832 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 833 return -1;
kadonotakashi 0:8fdf9a60065b 834 }
kadonotakashi 0:8fdf9a60065b 835
kadonotakashi 0:8fdf9a60065b 836 off_t off = fhc->seek(offset, whence);
kadonotakashi 0:8fdf9a60065b 837 if (off < 0) {
kadonotakashi 0:8fdf9a60065b 838 errno = -off;
kadonotakashi 0:8fdf9a60065b 839 return -1;
kadonotakashi 0:8fdf9a60065b 840 }
kadonotakashi 0:8fdf9a60065b 841 return off;
kadonotakashi 0:8fdf9a60065b 842 }
kadonotakashi 0:8fdf9a60065b 843
kadonotakashi 0:8fdf9a60065b 844 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 845 extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
kadonotakashi 0:8fdf9a60065b 846 {
kadonotakashi 0:8fdf9a60065b 847 return fsync(fh);
kadonotakashi 0:8fdf9a60065b 848 }
kadonotakashi 0:8fdf9a60065b 849 #endif
kadonotakashi 0:8fdf9a60065b 850
kadonotakashi 0:8fdf9a60065b 851 extern "C" int fsync(int fildes)
kadonotakashi 0:8fdf9a60065b 852 {
kadonotakashi 0:8fdf9a60065b 853 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 854 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 855 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 856 return -1;
kadonotakashi 0:8fdf9a60065b 857 }
kadonotakashi 0:8fdf9a60065b 858
kadonotakashi 0:8fdf9a60065b 859 int err = fhc->sync();
kadonotakashi 0:8fdf9a60065b 860 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 861 errno = -err;
kadonotakashi 0:8fdf9a60065b 862 return -1;
kadonotakashi 0:8fdf9a60065b 863 } else {
kadonotakashi 0:8fdf9a60065b 864 return 0;
kadonotakashi 0:8fdf9a60065b 865 }
kadonotakashi 0:8fdf9a60065b 866 }
kadonotakashi 0:8fdf9a60065b 867
kadonotakashi 0:8fdf9a60065b 868 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 869 extern "C" long PREFIX(_flen)(FILEHANDLE fh)
kadonotakashi 0:8fdf9a60065b 870 {
kadonotakashi 0:8fdf9a60065b 871 FileHandle *fhc = get_fhc(fh);
kadonotakashi 0:8fdf9a60065b 872 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 873 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 874 return -1;
kadonotakashi 0:8fdf9a60065b 875 }
kadonotakashi 0:8fdf9a60065b 876
kadonotakashi 0:8fdf9a60065b 877 off_t size = fhc->size();
kadonotakashi 0:8fdf9a60065b 878 if (size < 0) {
kadonotakashi 0:8fdf9a60065b 879 errno = -size;
kadonotakashi 0:8fdf9a60065b 880 return -1;
kadonotakashi 0:8fdf9a60065b 881 }
kadonotakashi 0:8fdf9a60065b 882 if (size > LONG_MAX) {
kadonotakashi 0:8fdf9a60065b 883 errno = EOVERFLOW;
kadonotakashi 0:8fdf9a60065b 884 return -1;
kadonotakashi 0:8fdf9a60065b 885 }
kadonotakashi 0:8fdf9a60065b 886 return size;
kadonotakashi 0:8fdf9a60065b 887 }
kadonotakashi 0:8fdf9a60065b 888
kadonotakashi 0:8fdf9a60065b 889 extern "C" char Image$$RW_IRAM1$$ZI$$Limit[];
kadonotakashi 0:8fdf9a60065b 890
kadonotakashi 0:8fdf9a60065b 891 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)
kadonotakashi 0:8fdf9a60065b 892 {
kadonotakashi 0:8fdf9a60065b 893 uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
kadonotakashi 0:8fdf9a60065b 894 uint32_t sp_limit = __current_sp();
kadonotakashi 0:8fdf9a60065b 895
kadonotakashi 0:8fdf9a60065b 896 zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
kadonotakashi 0:8fdf9a60065b 897
kadonotakashi 0:8fdf9a60065b 898 struct __initial_stackheap r;
kadonotakashi 0:8fdf9a60065b 899 r.heap_base = zi_limit;
kadonotakashi 0:8fdf9a60065b 900 r.heap_limit = sp_limit;
kadonotakashi 0:8fdf9a60065b 901 return r;
kadonotakashi 0:8fdf9a60065b 902 }
kadonotakashi 0:8fdf9a60065b 903
kadonotakashi 0:8fdf9a60065b 904 extern "C" __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3)
kadonotakashi 0:8fdf9a60065b 905 {
kadonotakashi 0:8fdf9a60065b 906 return _mbed_user_setup_stackheap(R0, R1, R2, R3);
kadonotakashi 0:8fdf9a60065b 907 }
kadonotakashi 0:8fdf9a60065b 908
kadonotakashi 0:8fdf9a60065b 909 #endif
kadonotakashi 0:8fdf9a60065b 910
kadonotakashi 0:8fdf9a60065b 911
kadonotakashi 0:8fdf9a60065b 912 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
kadonotakashi 0:8fdf9a60065b 913 extern "C" int _fstat(int fh, struct stat *st)
kadonotakashi 0:8fdf9a60065b 914 {
kadonotakashi 0:8fdf9a60065b 915 return fstat(fh, st);
kadonotakashi 0:8fdf9a60065b 916 }
kadonotakashi 0:8fdf9a60065b 917 #endif
kadonotakashi 0:8fdf9a60065b 918
kadonotakashi 0:8fdf9a60065b 919 extern "C" int fstat(int fildes, struct stat *st)
kadonotakashi 0:8fdf9a60065b 920 {
kadonotakashi 0:8fdf9a60065b 921 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 922 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 923 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 924 return -1;
kadonotakashi 0:8fdf9a60065b 925 }
kadonotakashi 0:8fdf9a60065b 926
kadonotakashi 0:8fdf9a60065b 927 st->st_mode = fhc->isatty() ? S_IFCHR : S_IFREG;
kadonotakashi 0:8fdf9a60065b 928 st->st_size = fhc->size();
kadonotakashi 0:8fdf9a60065b 929 return 0;
kadonotakashi 0:8fdf9a60065b 930 }
kadonotakashi 0:8fdf9a60065b 931
kadonotakashi 0:8fdf9a60065b 932 extern "C" int fcntl(int fildes, int cmd, ...)
kadonotakashi 0:8fdf9a60065b 933 {
kadonotakashi 0:8fdf9a60065b 934 FileHandle *fhc = get_fhc(fildes);
kadonotakashi 0:8fdf9a60065b 935 if (fhc == NULL) {
kadonotakashi 0:8fdf9a60065b 936 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 937 return -1;
kadonotakashi 0:8fdf9a60065b 938 }
kadonotakashi 0:8fdf9a60065b 939
kadonotakashi 0:8fdf9a60065b 940 switch (cmd) {
kadonotakashi 0:8fdf9a60065b 941 case F_GETFL: {
kadonotakashi 0:8fdf9a60065b 942 int flags = 0;
kadonotakashi 0:8fdf9a60065b 943 if (fhc->is_blocking()) {
kadonotakashi 0:8fdf9a60065b 944 flags |= O_NONBLOCK;
kadonotakashi 0:8fdf9a60065b 945 }
kadonotakashi 0:8fdf9a60065b 946 return flags;
kadonotakashi 0:8fdf9a60065b 947 }
kadonotakashi 0:8fdf9a60065b 948 case F_SETFL: {
kadonotakashi 0:8fdf9a60065b 949 va_list ap;
kadonotakashi 0:8fdf9a60065b 950 va_start(ap, cmd);
kadonotakashi 0:8fdf9a60065b 951 int flags = va_arg(ap, int);
kadonotakashi 0:8fdf9a60065b 952 va_end(ap);
kadonotakashi 0:8fdf9a60065b 953 int ret = fhc->set_blocking(flags & O_NONBLOCK);
kadonotakashi 0:8fdf9a60065b 954 if (ret < 0) {
kadonotakashi 0:8fdf9a60065b 955 errno = -ret;
kadonotakashi 0:8fdf9a60065b 956 return -1;
kadonotakashi 0:8fdf9a60065b 957 }
kadonotakashi 0:8fdf9a60065b 958 return 0;
kadonotakashi 0:8fdf9a60065b 959 }
kadonotakashi 0:8fdf9a60065b 960
kadonotakashi 0:8fdf9a60065b 961 default: {
kadonotakashi 0:8fdf9a60065b 962 errno = EINVAL;
kadonotakashi 0:8fdf9a60065b 963 return -1;
kadonotakashi 0:8fdf9a60065b 964 }
kadonotakashi 0:8fdf9a60065b 965 }
kadonotakashi 0:8fdf9a60065b 966 }
kadonotakashi 0:8fdf9a60065b 967
kadonotakashi 0:8fdf9a60065b 968 extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
kadonotakashi 0:8fdf9a60065b 969 {
kadonotakashi 0:8fdf9a60065b 970 if (nfds > OPEN_MAX) {
kadonotakashi 0:8fdf9a60065b 971 errno = EINVAL;
kadonotakashi 0:8fdf9a60065b 972 return -1;
kadonotakashi 0:8fdf9a60065b 973 }
kadonotakashi 0:8fdf9a60065b 974
kadonotakashi 0:8fdf9a60065b 975 struct mbed::pollfh fhs[OPEN_MAX];
kadonotakashi 0:8fdf9a60065b 976 for (nfds_t n = 0; n < nfds; n++) {
kadonotakashi 0:8fdf9a60065b 977 // Underlying FileHandle poll returns POLLNVAL if given NULL, so
kadonotakashi 0:8fdf9a60065b 978 // we don't need to take special action.
kadonotakashi 0:8fdf9a60065b 979 fhs[n].fh = get_fhc(fds[n].fd);
kadonotakashi 0:8fdf9a60065b 980 fhs[n].events = fds[n].events;
kadonotakashi 0:8fdf9a60065b 981 }
kadonotakashi 0:8fdf9a60065b 982 int ret = poll(fhs, nfds, timeout);
kadonotakashi 0:8fdf9a60065b 983 for (nfds_t n = 0; n < nfds; n++) {
kadonotakashi 0:8fdf9a60065b 984 fds[n].revents = fhs[n].revents;
kadonotakashi 0:8fdf9a60065b 985 }
kadonotakashi 0:8fdf9a60065b 986 return ret;
kadonotakashi 0:8fdf9a60065b 987 }
kadonotakashi 0:8fdf9a60065b 988
kadonotakashi 0:8fdf9a60065b 989 namespace std {
kadonotakashi 0:8fdf9a60065b 990 extern "C" int remove(const char *path)
kadonotakashi 0:8fdf9a60065b 991 {
kadonotakashi 0:8fdf9a60065b 992 FilePath fp(path);
kadonotakashi 0:8fdf9a60065b 993 FileSystemHandle *fs = fp.fileSystem();
kadonotakashi 0:8fdf9a60065b 994 if (fs == NULL) {
kadonotakashi 0:8fdf9a60065b 995 errno = ENODEV;
kadonotakashi 0:8fdf9a60065b 996 return -1;
kadonotakashi 0:8fdf9a60065b 997 }
kadonotakashi 0:8fdf9a60065b 998
kadonotakashi 0:8fdf9a60065b 999 int err = fs->remove(fp.fileName());
kadonotakashi 0:8fdf9a60065b 1000 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1001 errno = -err;
kadonotakashi 0:8fdf9a60065b 1002 return -1;
kadonotakashi 0:8fdf9a60065b 1003 } else {
kadonotakashi 0:8fdf9a60065b 1004 return 0;
kadonotakashi 0:8fdf9a60065b 1005 }
kadonotakashi 0:8fdf9a60065b 1006 }
kadonotakashi 0:8fdf9a60065b 1007
kadonotakashi 0:8fdf9a60065b 1008 extern "C" int rename(const char *oldname, const char *newname)
kadonotakashi 0:8fdf9a60065b 1009 {
kadonotakashi 0:8fdf9a60065b 1010 FilePath fpOld(oldname);
kadonotakashi 0:8fdf9a60065b 1011 FilePath fpNew(newname);
kadonotakashi 0:8fdf9a60065b 1012 FileSystemHandle *fsOld = fpOld.fileSystem();
kadonotakashi 0:8fdf9a60065b 1013 FileSystemHandle *fsNew = fpNew.fileSystem();
kadonotakashi 0:8fdf9a60065b 1014
kadonotakashi 0:8fdf9a60065b 1015 if (fsOld == NULL) {
kadonotakashi 0:8fdf9a60065b 1016 errno = ENODEV;
kadonotakashi 0:8fdf9a60065b 1017 return -1;
kadonotakashi 0:8fdf9a60065b 1018 }
kadonotakashi 0:8fdf9a60065b 1019
kadonotakashi 0:8fdf9a60065b 1020 /* rename only if both files are on the same FS */
kadonotakashi 0:8fdf9a60065b 1021 if (fsOld != fsNew) {
kadonotakashi 0:8fdf9a60065b 1022 errno = EXDEV;
kadonotakashi 0:8fdf9a60065b 1023 return -1;
kadonotakashi 0:8fdf9a60065b 1024 }
kadonotakashi 0:8fdf9a60065b 1025
kadonotakashi 0:8fdf9a60065b 1026 int err = fsOld->rename(fpOld.fileName(), fpNew.fileName());
kadonotakashi 0:8fdf9a60065b 1027 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1028 errno = -err;
kadonotakashi 0:8fdf9a60065b 1029 return -1;
kadonotakashi 0:8fdf9a60065b 1030 } else {
kadonotakashi 0:8fdf9a60065b 1031 return 0;
kadonotakashi 0:8fdf9a60065b 1032 }
kadonotakashi 0:8fdf9a60065b 1033 }
kadonotakashi 0:8fdf9a60065b 1034
kadonotakashi 0:8fdf9a60065b 1035 extern "C" char *tmpnam(char *s)
kadonotakashi 0:8fdf9a60065b 1036 {
kadonotakashi 0:8fdf9a60065b 1037 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 1038 return NULL;
kadonotakashi 0:8fdf9a60065b 1039 }
kadonotakashi 0:8fdf9a60065b 1040
kadonotakashi 0:8fdf9a60065b 1041 extern "C" FILE *tmpfile()
kadonotakashi 0:8fdf9a60065b 1042 {
kadonotakashi 0:8fdf9a60065b 1043 errno = EBADF;
kadonotakashi 0:8fdf9a60065b 1044 return NULL;
kadonotakashi 0:8fdf9a60065b 1045 }
kadonotakashi 0:8fdf9a60065b 1046 } // namespace std
kadonotakashi 0:8fdf9a60065b 1047
kadonotakashi 0:8fdf9a60065b 1048 #ifdef __ARMCC_VERSION
kadonotakashi 0:8fdf9a60065b 1049 extern "C" char *_sys_command_string(char *cmd, int len)
kadonotakashi 0:8fdf9a60065b 1050 {
kadonotakashi 0:8fdf9a60065b 1051 return NULL;
kadonotakashi 0:8fdf9a60065b 1052 }
kadonotakashi 0:8fdf9a60065b 1053 #endif
kadonotakashi 0:8fdf9a60065b 1054
kadonotakashi 0:8fdf9a60065b 1055 extern "C" DIR *opendir(const char *path)
kadonotakashi 0:8fdf9a60065b 1056 {
kadonotakashi 0:8fdf9a60065b 1057 FilePath fp(path);
kadonotakashi 0:8fdf9a60065b 1058 FileSystemHandle *fs = fp.fileSystem();
kadonotakashi 0:8fdf9a60065b 1059 if (fs == NULL) {
kadonotakashi 0:8fdf9a60065b 1060 errno = ENODEV;
kadonotakashi 0:8fdf9a60065b 1061 return NULL;
kadonotakashi 0:8fdf9a60065b 1062 }
kadonotakashi 0:8fdf9a60065b 1063
kadonotakashi 0:8fdf9a60065b 1064 DirHandle *dir;
kadonotakashi 0:8fdf9a60065b 1065 int err = fs->open(&dir, fp.fileName());
kadonotakashi 0:8fdf9a60065b 1066 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1067 errno = -err;
kadonotakashi 0:8fdf9a60065b 1068 return NULL;
kadonotakashi 0:8fdf9a60065b 1069 }
kadonotakashi 0:8fdf9a60065b 1070
kadonotakashi 0:8fdf9a60065b 1071 return dir;
kadonotakashi 0:8fdf9a60065b 1072 }
kadonotakashi 0:8fdf9a60065b 1073
kadonotakashi 0:8fdf9a60065b 1074 extern "C" struct dirent *readdir(DIR *dir)
kadonotakashi 0:8fdf9a60065b 1075 {
kadonotakashi 0:8fdf9a60065b 1076 static struct dirent ent;
kadonotakashi 0:8fdf9a60065b 1077 int err = dir->read(&ent);
kadonotakashi 0:8fdf9a60065b 1078 if (err < 1) {
kadonotakashi 0:8fdf9a60065b 1079 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1080 errno = -err;
kadonotakashi 0:8fdf9a60065b 1081 }
kadonotakashi 0:8fdf9a60065b 1082 return NULL;
kadonotakashi 0:8fdf9a60065b 1083 }
kadonotakashi 0:8fdf9a60065b 1084
kadonotakashi 0:8fdf9a60065b 1085 return &ent;
kadonotakashi 0:8fdf9a60065b 1086 }
kadonotakashi 0:8fdf9a60065b 1087
kadonotakashi 0:8fdf9a60065b 1088 extern "C" int closedir(DIR *dir)
kadonotakashi 0:8fdf9a60065b 1089 {
kadonotakashi 0:8fdf9a60065b 1090 int err = dir->close();
kadonotakashi 0:8fdf9a60065b 1091 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1092 errno = -err;
kadonotakashi 0:8fdf9a60065b 1093 return -1;
kadonotakashi 0:8fdf9a60065b 1094 } else {
kadonotakashi 0:8fdf9a60065b 1095 return 0;
kadonotakashi 0:8fdf9a60065b 1096 }
kadonotakashi 0:8fdf9a60065b 1097 }
kadonotakashi 0:8fdf9a60065b 1098
kadonotakashi 0:8fdf9a60065b 1099 extern "C" void rewinddir(DIR *dir)
kadonotakashi 0:8fdf9a60065b 1100 {
kadonotakashi 0:8fdf9a60065b 1101 dir->rewind();
kadonotakashi 0:8fdf9a60065b 1102 }
kadonotakashi 0:8fdf9a60065b 1103
kadonotakashi 0:8fdf9a60065b 1104 extern "C" off_t telldir(DIR *dir)
kadonotakashi 0:8fdf9a60065b 1105 {
kadonotakashi 0:8fdf9a60065b 1106 return dir->tell();
kadonotakashi 0:8fdf9a60065b 1107 }
kadonotakashi 0:8fdf9a60065b 1108
kadonotakashi 0:8fdf9a60065b 1109 extern "C" void seekdir(DIR *dir, off_t off)
kadonotakashi 0:8fdf9a60065b 1110 {
kadonotakashi 0:8fdf9a60065b 1111 dir->seek(off);
kadonotakashi 0:8fdf9a60065b 1112 }
kadonotakashi 0:8fdf9a60065b 1113
kadonotakashi 0:8fdf9a60065b 1114 extern "C" int mkdir(const char *path, mode_t mode)
kadonotakashi 0:8fdf9a60065b 1115 {
kadonotakashi 0:8fdf9a60065b 1116 FilePath fp(path);
kadonotakashi 0:8fdf9a60065b 1117 FileSystemHandle *fs = fp.fileSystem();
kadonotakashi 0:8fdf9a60065b 1118 if (fs == NULL) {
kadonotakashi 0:8fdf9a60065b 1119 errno = ENODEV;
kadonotakashi 0:8fdf9a60065b 1120 return -1;
kadonotakashi 0:8fdf9a60065b 1121 }
kadonotakashi 0:8fdf9a60065b 1122
kadonotakashi 0:8fdf9a60065b 1123 int err = fs->mkdir(fp.fileName(), mode);
kadonotakashi 0:8fdf9a60065b 1124 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1125 errno = -err;
kadonotakashi 0:8fdf9a60065b 1126 return -1;
kadonotakashi 0:8fdf9a60065b 1127 } else {
kadonotakashi 0:8fdf9a60065b 1128 return 0;
kadonotakashi 0:8fdf9a60065b 1129 }
kadonotakashi 0:8fdf9a60065b 1130 }
kadonotakashi 0:8fdf9a60065b 1131
kadonotakashi 0:8fdf9a60065b 1132 extern "C" int stat(const char *path, struct stat *st)
kadonotakashi 0:8fdf9a60065b 1133 {
kadonotakashi 0:8fdf9a60065b 1134 FilePath fp(path);
kadonotakashi 0:8fdf9a60065b 1135 FileSystemHandle *fs = fp.fileSystem();
kadonotakashi 0:8fdf9a60065b 1136 if (fs == NULL) {
kadonotakashi 0:8fdf9a60065b 1137 errno = ENODEV;
kadonotakashi 0:8fdf9a60065b 1138 return -1;
kadonotakashi 0:8fdf9a60065b 1139 }
kadonotakashi 0:8fdf9a60065b 1140
kadonotakashi 0:8fdf9a60065b 1141 int err = fs->stat(fp.fileName(), st);
kadonotakashi 0:8fdf9a60065b 1142 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1143 errno = -err;
kadonotakashi 0:8fdf9a60065b 1144 return -1;
kadonotakashi 0:8fdf9a60065b 1145 } else {
kadonotakashi 0:8fdf9a60065b 1146 return 0;
kadonotakashi 0:8fdf9a60065b 1147 }
kadonotakashi 0:8fdf9a60065b 1148 }
kadonotakashi 0:8fdf9a60065b 1149
kadonotakashi 0:8fdf9a60065b 1150 extern "C" int statvfs(const char *path, struct statvfs *buf)
kadonotakashi 0:8fdf9a60065b 1151 {
kadonotakashi 0:8fdf9a60065b 1152 FilePath fp(path);
kadonotakashi 0:8fdf9a60065b 1153 FileSystemHandle *fs = fp.fileSystem();
kadonotakashi 0:8fdf9a60065b 1154 if (fs == NULL) {
kadonotakashi 0:8fdf9a60065b 1155 errno = ENODEV;
kadonotakashi 0:8fdf9a60065b 1156 return -1;
kadonotakashi 0:8fdf9a60065b 1157 }
kadonotakashi 0:8fdf9a60065b 1158
kadonotakashi 0:8fdf9a60065b 1159 int err = fs->statvfs(fp.fileName(), buf);
kadonotakashi 0:8fdf9a60065b 1160 if (err < 0) {
kadonotakashi 0:8fdf9a60065b 1161 errno = -err;
kadonotakashi 0:8fdf9a60065b 1162 return -1;
kadonotakashi 0:8fdf9a60065b 1163 } else {
kadonotakashi 0:8fdf9a60065b 1164 return 0;
kadonotakashi 0:8fdf9a60065b 1165 }
kadonotakashi 0:8fdf9a60065b 1166 }
kadonotakashi 0:8fdf9a60065b 1167
kadonotakashi 0:8fdf9a60065b 1168 #if defined(TOOLCHAIN_GCC)
kadonotakashi 0:8fdf9a60065b 1169 /* prevents the exception handling name demangling code getting pulled in */
kadonotakashi 0:8fdf9a60065b 1170 #include "mbed_error.h"
kadonotakashi 0:8fdf9a60065b 1171 namespace __gnu_cxx {
kadonotakashi 0:8fdf9a60065b 1172 void __verbose_terminate_handler()
kadonotakashi 0:8fdf9a60065b 1173 {
kadonotakashi 0:8fdf9a60065b 1174 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_CLIB_EXCEPTION), "Exception", 0);
kadonotakashi 0:8fdf9a60065b 1175 }
kadonotakashi 0:8fdf9a60065b 1176 }
kadonotakashi 0:8fdf9a60065b 1177 extern "C" WEAK void __cxa_pure_virtual(void);
kadonotakashi 0:8fdf9a60065b 1178 extern "C" WEAK void __cxa_pure_virtual(void)
kadonotakashi 0:8fdf9a60065b 1179 {
kadonotakashi 0:8fdf9a60065b 1180 exit(1);
kadonotakashi 0:8fdf9a60065b 1181 }
kadonotakashi 0:8fdf9a60065b 1182
kadonotakashi 0:8fdf9a60065b 1183 #endif
kadonotakashi 0:8fdf9a60065b 1184
kadonotakashi 0:8fdf9a60065b 1185 // Provide implementation of _sbrk (low-level dynamic memory allocation
kadonotakashi 0:8fdf9a60065b 1186 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
kadonotakashi 0:8fdf9a60065b 1187 // SP. This make it compatible with RTX RTOS thread stacks.
kadonotakashi 0:8fdf9a60065b 1188 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
kadonotakashi 0:8fdf9a60065b 1189
kadonotakashi 0:8fdf9a60065b 1190 #if defined(TARGET_CORTEX_A)
kadonotakashi 0:8fdf9a60065b 1191 extern "C" uint32_t __HeapLimit;
kadonotakashi 0:8fdf9a60065b 1192 #endif
kadonotakashi 0:8fdf9a60065b 1193
kadonotakashi 0:8fdf9a60065b 1194 // Turn off the errno macro and use actual global variable instead.
kadonotakashi 0:8fdf9a60065b 1195 #undef errno
kadonotakashi 0:8fdf9a60065b 1196 extern "C" int errno;
kadonotakashi 0:8fdf9a60065b 1197
kadonotakashi 0:8fdf9a60065b 1198 // Dynamic memory allocation related syscall.
kadonotakashi 0:8fdf9a60065b 1199 #if defined(TWO_RAM_REGIONS)
kadonotakashi 0:8fdf9a60065b 1200
kadonotakashi 0:8fdf9a60065b 1201 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
kadonotakashi 0:8fdf9a60065b 1202 // __wrap__sbrk() is implemented in:
kadonotakashi 0:8fdf9a60065b 1203 // TARGET_STM32L4 targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L4/l4_retarget.c
kadonotakashi 0:8fdf9a60065b 1204 extern "C" void *__wrap__sbrk(int incr);
kadonotakashi 0:8fdf9a60065b 1205 extern "C" caddr_t _sbrk(int incr)
kadonotakashi 0:8fdf9a60065b 1206 {
kadonotakashi 0:8fdf9a60065b 1207 return (caddr_t) __wrap__sbrk(incr);
kadonotakashi 0:8fdf9a60065b 1208 }
kadonotakashi 0:8fdf9a60065b 1209 #else
kadonotakashi 0:8fdf9a60065b 1210 // Linker defined symbol used by _sbrk to indicate where heap should start.
kadonotakashi 0:8fdf9a60065b 1211 extern "C" uint32_t __end__;
kadonotakashi 0:8fdf9a60065b 1212 // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory.
kadonotakashi 0:8fdf9a60065b 1213 extern "C" WEAK caddr_t _sbrk(int incr)
kadonotakashi 0:8fdf9a60065b 1214 {
kadonotakashi 0:8fdf9a60065b 1215 static unsigned char *heap = (unsigned char *)&__end__;
kadonotakashi 0:8fdf9a60065b 1216 unsigned char *prev_heap = heap;
kadonotakashi 0:8fdf9a60065b 1217 unsigned char *new_heap = heap + incr;
kadonotakashi 0:8fdf9a60065b 1218
kadonotakashi 0:8fdf9a60065b 1219 #if defined(TARGET_CORTEX_A)
kadonotakashi 0:8fdf9a60065b 1220 if (new_heap >= (unsigned char *)&__HeapLimit) { /* __HeapLimit is end of heap section */
kadonotakashi 0:8fdf9a60065b 1221 #else
kadonotakashi 0:8fdf9a60065b 1222 if (new_heap >= (unsigned char *)__get_MSP()) {
kadonotakashi 0:8fdf9a60065b 1223 #endif
kadonotakashi 0:8fdf9a60065b 1224 errno = ENOMEM;
kadonotakashi 0:8fdf9a60065b 1225 return (caddr_t) -1;
kadonotakashi 0:8fdf9a60065b 1226 }
kadonotakashi 0:8fdf9a60065b 1227
kadonotakashi 0:8fdf9a60065b 1228 // Additional heap checking if set
kadonotakashi 0:8fdf9a60065b 1229 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
kadonotakashi 0:8fdf9a60065b 1230 errno = ENOMEM;
kadonotakashi 0:8fdf9a60065b 1231 return (caddr_t) -1;
kadonotakashi 0:8fdf9a60065b 1232 }
kadonotakashi 0:8fdf9a60065b 1233
kadonotakashi 0:8fdf9a60065b 1234 heap = new_heap;
kadonotakashi 0:8fdf9a60065b 1235 return (caddr_t) prev_heap;
kadonotakashi 0:8fdf9a60065b 1236 }
kadonotakashi 0:8fdf9a60065b 1237 #endif
kadonotakashi 0:8fdf9a60065b 1238 #endif
kadonotakashi 0:8fdf9a60065b 1239
kadonotakashi 0:8fdf9a60065b 1240 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
kadonotakashi 0:8fdf9a60065b 1241 extern "C" void _exit(int return_code)
kadonotakashi 0:8fdf9a60065b 1242 {
kadonotakashi 0:8fdf9a60065b 1243 #else
kadonotakashi 0:8fdf9a60065b 1244 namespace std {
kadonotakashi 0:8fdf9a60065b 1245 extern "C" void exit(int return_code)
kadonotakashi 0:8fdf9a60065b 1246 {
kadonotakashi 0:8fdf9a60065b 1247 #endif
kadonotakashi 0:8fdf9a60065b 1248
kadonotakashi 0:8fdf9a60065b 1249 #if DEVICE_STDIO_MESSAGES
kadonotakashi 0:8fdf9a60065b 1250 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
kadonotakashi 0:8fdf9a60065b 1251 fflush(stdout);
kadonotakashi 0:8fdf9a60065b 1252 fflush(stderr);
kadonotakashi 0:8fdf9a60065b 1253 #endif
kadonotakashi 0:8fdf9a60065b 1254 #endif
kadonotakashi 0:8fdf9a60065b 1255
kadonotakashi 0:8fdf9a60065b 1256 #if DEVICE_SEMIHOST
kadonotakashi 0:8fdf9a60065b 1257 if (mbed_interface_connected()) {
kadonotakashi 0:8fdf9a60065b 1258 semihost_exit();
kadonotakashi 0:8fdf9a60065b 1259 }
kadonotakashi 0:8fdf9a60065b 1260 #endif
kadonotakashi 0:8fdf9a60065b 1261 if (return_code) {
kadonotakashi 0:8fdf9a60065b 1262 mbed_die();
kadonotakashi 0:8fdf9a60065b 1263 }
kadonotakashi 0:8fdf9a60065b 1264
kadonotakashi 0:8fdf9a60065b 1265 while (1);
kadonotakashi 0:8fdf9a60065b 1266 }
kadonotakashi 0:8fdf9a60065b 1267
kadonotakashi 0:8fdf9a60065b 1268 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
kadonotakashi 0:8fdf9a60065b 1269 } //namespace std
kadonotakashi 0:8fdf9a60065b 1270 #endif
kadonotakashi 0:8fdf9a60065b 1271
kadonotakashi 0:8fdf9a60065b 1272 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
kadonotakashi 0:8fdf9a60065b 1273
kadonotakashi 0:8fdf9a60065b 1274 // This series of function disable the registration of global destructors
kadonotakashi 0:8fdf9a60065b 1275 // in a dynamic table which will be called when the application exit.
kadonotakashi 0:8fdf9a60065b 1276 // In mbed, program never exit properly, it dies.
kadonotakashi 0:8fdf9a60065b 1277 // More informations about this topic for ARMCC here:
kadonotakashi 0:8fdf9a60065b 1278 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
kadonotakashi 0:8fdf9a60065b 1279 extern "C" {
kadonotakashi 0:8fdf9a60065b 1280 int __aeabi_atexit(void *object, void (*dtor)(void * /*this*/), void *handle)
kadonotakashi 0:8fdf9a60065b 1281 {
kadonotakashi 0:8fdf9a60065b 1282 return 1;
kadonotakashi 0:8fdf9a60065b 1283 }
kadonotakashi 0:8fdf9a60065b 1284
kadonotakashi 0:8fdf9a60065b 1285 int __cxa_atexit(void (*dtor)(void * /*this*/), void *object, void *handle)
kadonotakashi 0:8fdf9a60065b 1286 {
kadonotakashi 0:8fdf9a60065b 1287 return 1;
kadonotakashi 0:8fdf9a60065b 1288 }
kadonotakashi 0:8fdf9a60065b 1289
kadonotakashi 0:8fdf9a60065b 1290 void __cxa_finalize(void *handle)
kadonotakashi 0:8fdf9a60065b 1291 {
kadonotakashi 0:8fdf9a60065b 1292 }
kadonotakashi 0:8fdf9a60065b 1293
kadonotakashi 0:8fdf9a60065b 1294 } // end of extern "C"
kadonotakashi 0:8fdf9a60065b 1295
kadonotakashi 0:8fdf9a60065b 1296 #endif
kadonotakashi 0:8fdf9a60065b 1297
kadonotakashi 0:8fdf9a60065b 1298
kadonotakashi 0:8fdf9a60065b 1299 #if defined(TOOLCHAIN_GCC)
kadonotakashi 0:8fdf9a60065b 1300
kadonotakashi 0:8fdf9a60065b 1301 /*
kadonotakashi 0:8fdf9a60065b 1302 * Depending on how newlib is configured, it is often not enough to define
kadonotakashi 0:8fdf9a60065b 1303 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
kadonotakashi 0:8fdf9a60065b 1304 * behavior regarding the registration of handlers with atexit.
kadonotakashi 0:8fdf9a60065b 1305 *
kadonotakashi 0:8fdf9a60065b 1306 * To overcome this limitation, exit and atexit are overriden here.
kadonotakashi 0:8fdf9a60065b 1307 */
kadonotakashi 0:8fdf9a60065b 1308 extern "C" {
kadonotakashi 0:8fdf9a60065b 1309
kadonotakashi 0:8fdf9a60065b 1310 /**
kadonotakashi 0:8fdf9a60065b 1311 * @brief Retarget of exit for GCC.
kadonotakashi 0:8fdf9a60065b 1312 * @details Unlike the standard version, this function doesn't call any function
kadonotakashi 0:8fdf9a60065b 1313 * registered with atexit before calling _exit.
kadonotakashi 0:8fdf9a60065b 1314 */
kadonotakashi 0:8fdf9a60065b 1315 void __wrap_exit(int return_code)
kadonotakashi 0:8fdf9a60065b 1316 {
kadonotakashi 0:8fdf9a60065b 1317 _exit(return_code);
kadonotakashi 0:8fdf9a60065b 1318 }
kadonotakashi 0:8fdf9a60065b 1319
kadonotakashi 0:8fdf9a60065b 1320 /**
kadonotakashi 0:8fdf9a60065b 1321 * @brief Retarget atexit from GCC.
kadonotakashi 0:8fdf9a60065b 1322 * @details This function will always fail and never register any handler to be
kadonotakashi 0:8fdf9a60065b 1323 * called at exit.
kadonotakashi 0:8fdf9a60065b 1324 */
kadonotakashi 0:8fdf9a60065b 1325 int __wrap_atexit(void (*func)())
kadonotakashi 0:8fdf9a60065b 1326 {
kadonotakashi 0:8fdf9a60065b 1327 return 1;
kadonotakashi 0:8fdf9a60065b 1328 }
kadonotakashi 0:8fdf9a60065b 1329
kadonotakashi 0:8fdf9a60065b 1330 }
kadonotakashi 0:8fdf9a60065b 1331
kadonotakashi 0:8fdf9a60065b 1332 #endif
kadonotakashi 0:8fdf9a60065b 1333
kadonotakashi 0:8fdf9a60065b 1334
kadonotakashi 0:8fdf9a60065b 1335
kadonotakashi 0:8fdf9a60065b 1336 namespace mbed {
kadonotakashi 0:8fdf9a60065b 1337
kadonotakashi 0:8fdf9a60065b 1338 void mbed_set_unbuffered_stream(std::FILE *_file)
kadonotakashi 0:8fdf9a60065b 1339 {
kadonotakashi 0:8fdf9a60065b 1340 #if defined (__ICCARM__)
kadonotakashi 0:8fdf9a60065b 1341 char buf[2];
kadonotakashi 0:8fdf9a60065b 1342 std::setvbuf(_file, buf, _IONBF, NULL);
kadonotakashi 0:8fdf9a60065b 1343 #else
kadonotakashi 0:8fdf9a60065b 1344 setbuf(_file, NULL);
kadonotakashi 0:8fdf9a60065b 1345 #endif
kadonotakashi 0:8fdf9a60065b 1346 }
kadonotakashi 0:8fdf9a60065b 1347
kadonotakashi 0:8fdf9a60065b 1348 int mbed_getc(std::FILE *_file)
kadonotakashi 0:8fdf9a60065b 1349 {
kadonotakashi 0:8fdf9a60065b 1350 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
kadonotakashi 0:8fdf9a60065b 1351 /*This is only valid for unbuffered streams*/
kadonotakashi 0:8fdf9a60065b 1352 int res = std::fgetc(_file);
kadonotakashi 0:8fdf9a60065b 1353 if (res >= 0) {
kadonotakashi 0:8fdf9a60065b 1354 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
kadonotakashi 0:8fdf9a60065b 1355 _file->_Rend = _file->_Wend;
kadonotakashi 0:8fdf9a60065b 1356 _file->_Next = _file->_Wend;
kadonotakashi 0:8fdf9a60065b 1357 }
kadonotakashi 0:8fdf9a60065b 1358 return res;
kadonotakashi 0:8fdf9a60065b 1359 #else
kadonotakashi 0:8fdf9a60065b 1360 return std::fgetc(_file);
kadonotakashi 0:8fdf9a60065b 1361 #endif
kadonotakashi 0:8fdf9a60065b 1362 }
kadonotakashi 0:8fdf9a60065b 1363
kadonotakashi 0:8fdf9a60065b 1364 char *mbed_gets(char *s, int size, std::FILE *_file)
kadonotakashi 0:8fdf9a60065b 1365 {
kadonotakashi 0:8fdf9a60065b 1366 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
kadonotakashi 0:8fdf9a60065b 1367 /*This is only valid for unbuffered streams*/
kadonotakashi 0:8fdf9a60065b 1368 char *str = fgets(s, size, _file);
kadonotakashi 0:8fdf9a60065b 1369 if (str != NULL) {
kadonotakashi 0:8fdf9a60065b 1370 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
kadonotakashi 0:8fdf9a60065b 1371 _file->_Rend = _file->_Wend;
kadonotakashi 0:8fdf9a60065b 1372 _file->_Next = _file->_Wend;
kadonotakashi 0:8fdf9a60065b 1373 }
kadonotakashi 0:8fdf9a60065b 1374 return str;
kadonotakashi 0:8fdf9a60065b 1375 #else
kadonotakashi 0:8fdf9a60065b 1376 return std::fgets(s, size, _file);
kadonotakashi 0:8fdf9a60065b 1377 #endif
kadonotakashi 0:8fdf9a60065b 1378 }
kadonotakashi 0:8fdf9a60065b 1379
kadonotakashi 0:8fdf9a60065b 1380 } // namespace mbed
kadonotakashi 0:8fdf9a60065b 1381
kadonotakashi 0:8fdf9a60065b 1382 #if defined (__ICCARM__)
kadonotakashi 0:8fdf9a60065b 1383 // Stub out locks when an rtos is not present
kadonotakashi 0:8fdf9a60065b 1384 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1385 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1386 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1387 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1388 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1389 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1390 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1391 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
kadonotakashi 0:8fdf9a60065b 1392 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
kadonotakashi 0:8fdf9a60065b 1393 #pragma section="__iar_tls$$DATA"
kadonotakashi 0:8fdf9a60065b 1394 extern "C" WEAK void *__aeabi_read_tp(void)
kadonotakashi 0:8fdf9a60065b 1395 {
kadonotakashi 0:8fdf9a60065b 1396 // Thread Local storage is not supported, using main thread memory for errno
kadonotakashi 0:8fdf9a60065b 1397 return __section_begin("__iar_tls$$DATA");
kadonotakashi 0:8fdf9a60065b 1398 }
kadonotakashi 0:8fdf9a60065b 1399 #endif
kadonotakashi 0:8fdf9a60065b 1400 #elif defined(__CC_ARM)
kadonotakashi 0:8fdf9a60065b 1401 // Do nothing
kadonotakashi 0:8fdf9a60065b 1402 #elif defined (__GNUC__)
kadonotakashi 0:8fdf9a60065b 1403 struct _reent;
kadonotakashi 0:8fdf9a60065b 1404 // Stub out locks when an rtos is not present
kadonotakashi 0:8fdf9a60065b 1405 extern "C" WEAK void __rtos_malloc_lock(struct _reent *_r) {}
kadonotakashi 0:8fdf9a60065b 1406 extern "C" WEAK void __rtos_malloc_unlock(struct _reent *_r) {}
kadonotakashi 0:8fdf9a60065b 1407 extern "C" WEAK void __rtos_env_lock(struct _reent *_r) {}
kadonotakashi 0:8fdf9a60065b 1408 extern "C" WEAK void __rtos_env_unlock(struct _reent *_r) {}
kadonotakashi 0:8fdf9a60065b 1409
kadonotakashi 0:8fdf9a60065b 1410 extern "C" void __malloc_lock(struct _reent *_r)
kadonotakashi 0:8fdf9a60065b 1411 {
kadonotakashi 0:8fdf9a60065b 1412 __rtos_malloc_lock(_r);
kadonotakashi 0:8fdf9a60065b 1413 }
kadonotakashi 0:8fdf9a60065b 1414
kadonotakashi 0:8fdf9a60065b 1415 extern "C" void __malloc_unlock(struct _reent *_r)
kadonotakashi 0:8fdf9a60065b 1416 {
kadonotakashi 0:8fdf9a60065b 1417 __rtos_malloc_unlock(_r);
kadonotakashi 0:8fdf9a60065b 1418 }
kadonotakashi 0:8fdf9a60065b 1419
kadonotakashi 0:8fdf9a60065b 1420 extern "C" void __env_lock(struct _reent *_r)
kadonotakashi 0:8fdf9a60065b 1421 {
kadonotakashi 0:8fdf9a60065b 1422 __rtos_env_lock(_r);
kadonotakashi 0:8fdf9a60065b 1423 }
kadonotakashi 0:8fdf9a60065b 1424
kadonotakashi 0:8fdf9a60065b 1425 extern "C" void __env_unlock(struct _reent *_r)
kadonotakashi 0:8fdf9a60065b 1426 {
kadonotakashi 0:8fdf9a60065b 1427 __rtos_env_unlock(_r);
kadonotakashi 0:8fdf9a60065b 1428 }
kadonotakashi 0:8fdf9a60065b 1429
kadonotakashi 0:8fdf9a60065b 1430 #endif
kadonotakashi 0:8fdf9a60065b 1431
kadonotakashi 0:8fdf9a60065b 1432 #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
kadonotakashi 0:8fdf9a60065b 1433
kadonotakashi 0:8fdf9a60065b 1434 #define CXA_GUARD_INIT_DONE (1 << 0)
kadonotakashi 0:8fdf9a60065b 1435 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
kadonotakashi 0:8fdf9a60065b 1436 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
kadonotakashi 0:8fdf9a60065b 1437
kadonotakashi 0:8fdf9a60065b 1438 extern "C" int __cxa_guard_acquire(int *guard_object_p)
kadonotakashi 0:8fdf9a60065b 1439 {
kadonotakashi 0:8fdf9a60065b 1440 uint8_t *guard_object = (uint8_t *)guard_object_p;
kadonotakashi 0:8fdf9a60065b 1441 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
kadonotakashi 0:8fdf9a60065b 1442 return 0;
kadonotakashi 0:8fdf9a60065b 1443 }
kadonotakashi 0:8fdf9a60065b 1444 singleton_lock();
kadonotakashi 0:8fdf9a60065b 1445 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
kadonotakashi 0:8fdf9a60065b 1446 singleton_unlock();
kadonotakashi 0:8fdf9a60065b 1447 return 0;
kadonotakashi 0:8fdf9a60065b 1448 }
kadonotakashi 0:8fdf9a60065b 1449 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
kadonotakashi 0:8fdf9a60065b 1450 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
kadonotakashi 0:8fdf9a60065b 1451 return 1;
kadonotakashi 0:8fdf9a60065b 1452 }
kadonotakashi 0:8fdf9a60065b 1453
kadonotakashi 0:8fdf9a60065b 1454 extern "C" void __cxa_guard_release(int *guard_object_p)
kadonotakashi 0:8fdf9a60065b 1455 {
kadonotakashi 0:8fdf9a60065b 1456 uint8_t *guard_object = (uint8_t *)guard_object_p;
kadonotakashi 0:8fdf9a60065b 1457 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
kadonotakashi 0:8fdf9a60065b 1458 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
kadonotakashi 0:8fdf9a60065b 1459 singleton_unlock();
kadonotakashi 0:8fdf9a60065b 1460 }
kadonotakashi 0:8fdf9a60065b 1461
kadonotakashi 0:8fdf9a60065b 1462 extern "C" void __cxa_guard_abort(int *guard_object_p)
kadonotakashi 0:8fdf9a60065b 1463 {
kadonotakashi 0:8fdf9a60065b 1464 uint8_t *guard_object = (uint8_t *)guard_object_p;
kadonotakashi 0:8fdf9a60065b 1465 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
kadonotakashi 0:8fdf9a60065b 1466 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
kadonotakashi 0:8fdf9a60065b 1467 singleton_unlock();
kadonotakashi 0:8fdf9a60065b 1468 }
kadonotakashi 0:8fdf9a60065b 1469
kadonotakashi 0:8fdf9a60065b 1470 #endif
kadonotakashi 0:8fdf9a60065b 1471
kadonotakashi 0:8fdf9a60065b 1472 #if MBED_MEM_TRACING_ENABLED && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))
kadonotakashi 0:8fdf9a60065b 1473
kadonotakashi 0:8fdf9a60065b 1474 // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
kadonotakashi 0:8fdf9a60065b 1475 // provide the implementation for these. Note: this needs to use the wrappers
kadonotakashi 0:8fdf9a60065b 1476 // instead of malloc()/free() as the caller address would point to wrappers,
kadonotakashi 0:8fdf9a60065b 1477 // not the caller of "new" or "delete".
kadonotakashi 0:8fdf9a60065b 1478 extern "C" void *malloc_wrapper(size_t size, const void *caller);
kadonotakashi 0:8fdf9a60065b 1479 extern "C" void free_wrapper(void *ptr, const void *caller);
kadonotakashi 0:8fdf9a60065b 1480
kadonotakashi 0:8fdf9a60065b 1481 void *operator new (std::size_t count)
kadonotakashi 0:8fdf9a60065b 1482 {
kadonotakashi 0:8fdf9a60065b 1483 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1484 if (NULL == buffer) {
kadonotakashi 0:8fdf9a60065b 1485 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
kadonotakashi 0:8fdf9a60065b 1486 }
kadonotakashi 0:8fdf9a60065b 1487 return buffer;
kadonotakashi 0:8fdf9a60065b 1488 }
kadonotakashi 0:8fdf9a60065b 1489
kadonotakashi 0:8fdf9a60065b 1490 void *operator new[](std::size_t count)
kadonotakashi 0:8fdf9a60065b 1491 {
kadonotakashi 0:8fdf9a60065b 1492 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1493 if (NULL == buffer) {
kadonotakashi 0:8fdf9a60065b 1494 error("Operator new[] out of memory\r\n");
kadonotakashi 0:8fdf9a60065b 1495 }
kadonotakashi 0:8fdf9a60065b 1496 return buffer;
kadonotakashi 0:8fdf9a60065b 1497 }
kadonotakashi 0:8fdf9a60065b 1498
kadonotakashi 0:8fdf9a60065b 1499 void *operator new (std::size_t count, const std::nothrow_t &tag)
kadonotakashi 0:8fdf9a60065b 1500 {
kadonotakashi 0:8fdf9a60065b 1501 return malloc_wrapper(count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1502 }
kadonotakashi 0:8fdf9a60065b 1503
kadonotakashi 0:8fdf9a60065b 1504 void *operator new[](std::size_t count, const std::nothrow_t &tag)
kadonotakashi 0:8fdf9a60065b 1505 {
kadonotakashi 0:8fdf9a60065b 1506 return malloc_wrapper(count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1507 }
kadonotakashi 0:8fdf9a60065b 1508
kadonotakashi 0:8fdf9a60065b 1509 void operator delete (void *ptr)
kadonotakashi 0:8fdf9a60065b 1510 {
kadonotakashi 0:8fdf9a60065b 1511 free_wrapper(ptr, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1512 }
kadonotakashi 0:8fdf9a60065b 1513 void operator delete[](void *ptr)
kadonotakashi 0:8fdf9a60065b 1514 {
kadonotakashi 0:8fdf9a60065b 1515 free_wrapper(ptr, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1516 }
kadonotakashi 0:8fdf9a60065b 1517
kadonotakashi 0:8fdf9a60065b 1518 #elif MBED_MEM_TRACING_ENABLED && defined(__GNUC__)
kadonotakashi 0:8fdf9a60065b 1519
kadonotakashi 0:8fdf9a60065b 1520 #include <reent.h>
kadonotakashi 0:8fdf9a60065b 1521
kadonotakashi 0:8fdf9a60065b 1522 extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller);
kadonotakashi 0:8fdf9a60065b 1523 extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller);
kadonotakashi 0:8fdf9a60065b 1524
kadonotakashi 0:8fdf9a60065b 1525 void *operator new (std::size_t count)
kadonotakashi 0:8fdf9a60065b 1526 {
kadonotakashi 0:8fdf9a60065b 1527 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1528 if (NULL == buffer) {
kadonotakashi 0:8fdf9a60065b 1529 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
kadonotakashi 0:8fdf9a60065b 1530 }
kadonotakashi 0:8fdf9a60065b 1531 return buffer;
kadonotakashi 0:8fdf9a60065b 1532 }
kadonotakashi 0:8fdf9a60065b 1533
kadonotakashi 0:8fdf9a60065b 1534 void *operator new[](std::size_t count)
kadonotakashi 0:8fdf9a60065b 1535 {
kadonotakashi 0:8fdf9a60065b 1536 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1537 if (NULL == buffer) {
kadonotakashi 0:8fdf9a60065b 1538 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
kadonotakashi 0:8fdf9a60065b 1539 }
kadonotakashi 0:8fdf9a60065b 1540 return buffer;
kadonotakashi 0:8fdf9a60065b 1541 }
kadonotakashi 0:8fdf9a60065b 1542
kadonotakashi 0:8fdf9a60065b 1543 void *operator new (std::size_t count, const std::nothrow_t &tag)
kadonotakashi 0:8fdf9a60065b 1544 {
kadonotakashi 0:8fdf9a60065b 1545 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1546 }
kadonotakashi 0:8fdf9a60065b 1547
kadonotakashi 0:8fdf9a60065b 1548 void *operator new[](std::size_t count, const std::nothrow_t &tag)
kadonotakashi 0:8fdf9a60065b 1549 {
kadonotakashi 0:8fdf9a60065b 1550 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1551 }
kadonotakashi 0:8fdf9a60065b 1552
kadonotakashi 0:8fdf9a60065b 1553 void operator delete (void *ptr)
kadonotakashi 0:8fdf9a60065b 1554 {
kadonotakashi 0:8fdf9a60065b 1555 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1556 }
kadonotakashi 0:8fdf9a60065b 1557
kadonotakashi 0:8fdf9a60065b 1558 void operator delete[](void *ptr)
kadonotakashi 0:8fdf9a60065b 1559 {
kadonotakashi 0:8fdf9a60065b 1560 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
kadonotakashi 0:8fdf9a60065b 1561 }
kadonotakashi 0:8fdf9a60065b 1562
kadonotakashi 0:8fdf9a60065b 1563 #else
kadonotakashi 0:8fdf9a60065b 1564
kadonotakashi 0:8fdf9a60065b 1565 void *operator new (std::size_t count)
kadonotakashi 0:8fdf9a60065b 1566 {
kadonotakashi 0:8fdf9a60065b 1567 void *buffer = malloc(count);
kadonotakashi 0:8fdf9a60065b 1568 if (NULL == buffer) {
kadonotakashi 0:8fdf9a60065b 1569 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
kadonotakashi 0:8fdf9a60065b 1570 }
kadonotakashi 0:8fdf9a60065b 1571 return buffer;
kadonotakashi 0:8fdf9a60065b 1572 }
kadonotakashi 0:8fdf9a60065b 1573
kadonotakashi 0:8fdf9a60065b 1574 void *operator new[](std::size_t count)
kadonotakashi 0:8fdf9a60065b 1575 {
kadonotakashi 0:8fdf9a60065b 1576 void *buffer = malloc(count);
kadonotakashi 0:8fdf9a60065b 1577 if (NULL == buffer) {
kadonotakashi 0:8fdf9a60065b 1578 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new[] out of memory\r\n", count);
kadonotakashi 0:8fdf9a60065b 1579 }
kadonotakashi 0:8fdf9a60065b 1580 return buffer;
kadonotakashi 0:8fdf9a60065b 1581 }
kadonotakashi 0:8fdf9a60065b 1582
kadonotakashi 0:8fdf9a60065b 1583 void *operator new (std::size_t count, const std::nothrow_t &tag)
kadonotakashi 0:8fdf9a60065b 1584 {
kadonotakashi 0:8fdf9a60065b 1585 return malloc(count);
kadonotakashi 0:8fdf9a60065b 1586 }
kadonotakashi 0:8fdf9a60065b 1587
kadonotakashi 0:8fdf9a60065b 1588 void *operator new[](std::size_t count, const std::nothrow_t &tag)
kadonotakashi 0:8fdf9a60065b 1589 {
kadonotakashi 0:8fdf9a60065b 1590 return malloc(count);
kadonotakashi 0:8fdf9a60065b 1591 }
kadonotakashi 0:8fdf9a60065b 1592
kadonotakashi 0:8fdf9a60065b 1593 void operator delete (void *ptr)
kadonotakashi 0:8fdf9a60065b 1594 {
kadonotakashi 0:8fdf9a60065b 1595 free(ptr);
kadonotakashi 0:8fdf9a60065b 1596 }
kadonotakashi 0:8fdf9a60065b 1597 void operator delete[](void *ptr)
kadonotakashi 0:8fdf9a60065b 1598 {
kadonotakashi 0:8fdf9a60065b 1599 free(ptr);
kadonotakashi 0:8fdf9a60065b 1600 }
kadonotakashi 0:8fdf9a60065b 1601
kadonotakashi 0:8fdf9a60065b 1602 #endif
kadonotakashi 0:8fdf9a60065b 1603
kadonotakashi 0:8fdf9a60065b 1604 /* @brief standard c library clock() function.
kadonotakashi 0:8fdf9a60065b 1605 *
kadonotakashi 0:8fdf9a60065b 1606 * This function returns the number of clock ticks elapsed since the start of the program.
kadonotakashi 0:8fdf9a60065b 1607 *
kadonotakashi 0:8fdf9a60065b 1608 * @note Synchronization level: Thread safe
kadonotakashi 0:8fdf9a60065b 1609 *
kadonotakashi 0:8fdf9a60065b 1610 * @return
kadonotakashi 0:8fdf9a60065b 1611 * the number of clock ticks elapsed since the start of the program.
kadonotakashi 0:8fdf9a60065b 1612 *
kadonotakashi 0:8fdf9a60065b 1613 * */
kadonotakashi 0:8fdf9a60065b 1614 extern "C" clock_t clock()
kadonotakashi 0:8fdf9a60065b 1615 {
kadonotakashi 0:8fdf9a60065b 1616 _mutex->lock();
kadonotakashi 0:8fdf9a60065b 1617 clock_t t = ticker_read(get_us_ticker_data());
kadonotakashi 0:8fdf9a60065b 1618 t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time
kadonotakashi 0:8fdf9a60065b 1619 _mutex->unlock();
kadonotakashi 0:8fdf9a60065b 1620 return t;
kadonotakashi 0:8fdf9a60065b 1621 }
kadonotakashi 0:8fdf9a60065b 1622
kadonotakashi 0:8fdf9a60065b 1623 // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info
kadonotakashi 0:8fdf9a60065b 1624 MBED_WEAK const ticker_info_t *us_ticker_get_info()
kadonotakashi 0:8fdf9a60065b 1625 {
kadonotakashi 0:8fdf9a60065b 1626 static const ticker_info_t info = {
kadonotakashi 0:8fdf9a60065b 1627 1000000,
kadonotakashi 0:8fdf9a60065b 1628 32
kadonotakashi 0:8fdf9a60065b 1629 };
kadonotakashi 0:8fdf9a60065b 1630 return &info;
kadonotakashi 0:8fdf9a60065b 1631 }
kadonotakashi 0:8fdf9a60065b 1632
kadonotakashi 0:8fdf9a60065b 1633 // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info
kadonotakashi 0:8fdf9a60065b 1634 MBED_WEAK const ticker_info_t *lp_ticker_get_info()
kadonotakashi 0:8fdf9a60065b 1635 {
kadonotakashi 0:8fdf9a60065b 1636 static const ticker_info_t info = {
kadonotakashi 0:8fdf9a60065b 1637 1000000,
kadonotakashi 0:8fdf9a60065b 1638 32
kadonotakashi 0:8fdf9a60065b 1639 };
kadonotakashi 0:8fdf9a60065b 1640 return &info;
kadonotakashi 0:8fdf9a60065b 1641 }