BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

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