Backup 1

Committer:
borlanic
Date:
Tue Apr 24 11:45:18 2018 +0000
Revision:
0:02dd72d1d465
BaBoRo_test2 - backup 1

Who changed what in which revision?

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