BA / Mbed OS BaBoRo1
Committer:
borlanic
Date:
Fri Mar 30 14:07:05 2018 +0000
Revision:
4:75df35ef4fb6
Parent:
0:380207fcb5c1
commentar

Who changed what in which revision?

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