RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

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