mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Thu Apr 19 17:12:19 2018 +0100
Revision:
184:08ed48f1de7f
Parent:
182:a56a73fd2a6f
Child:
186:707f6e361f3e
mbed-dev library. Release version 161

Who changed what in which revision?

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