游戏王对战板,目前code还是空的

Committer:
WFKnight
Date:
Thu Jun 21 13:51:43 2018 +0000
Revision:
0:9b3d4731edbb
UART, RTOS, LED

Who changed what in which revision?

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