BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

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