mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
Anna Bridge
Date:
Fri Jun 22 16:45:37 2018 +0100
Revision:
186:707f6e361f3e
Parent:
184:08ed48f1de7f
mbed-dev library. Release version 162

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