mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Thu Jul 06 15:42:05 2017 +0100
Revision:
168:9672193075cf
Parent:
167:e84263d55307
Child:
172:7d866c31b3c5
This updates the lib to the mbed lib v 146

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 160:d5399cc887bb 1 /* mbed Microcontroller Library
<> 160:d5399cc887bb 2 * Copyright (c) 2006-2015 ARM Limited
<> 160:d5399cc887bb 3 *
<> 160:d5399cc887bb 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 160:d5399cc887bb 5 * you may not use this file except in compliance with the License.
<> 160:d5399cc887bb 6 * You may obtain a copy of the License at
<> 160:d5399cc887bb 7 *
<> 160:d5399cc887bb 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 160:d5399cc887bb 9 *
<> 160:d5399cc887bb 10 * Unless required by applicable law or agreed to in writing, software
<> 160:d5399cc887bb 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 160:d5399cc887bb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 160:d5399cc887bb 13 * See the License for the specific language governing permissions and
<> 160:d5399cc887bb 14 * limitations under the License.
<> 160:d5399cc887bb 15 */
<> 160:d5399cc887bb 16 #include "platform/platform.h"
AnnaBridge 167:e84263d55307 17 #include "platform/FilePath.h"
<> 160:d5399cc887bb 18 #include "hal/serial_api.h"
<> 160:d5399cc887bb 19 #include "platform/mbed_toolchain.h"
<> 160:d5399cc887bb 20 #include "platform/mbed_semihost_api.h"
<> 160:d5399cc887bb 21 #include "platform/mbed_interface.h"
<> 160:d5399cc887bb 22 #include "platform/SingletonPtr.h"
<> 160:d5399cc887bb 23 #include "platform/PlatformMutex.h"
<> 160:d5399cc887bb 24 #include "platform/mbed_error.h"
<> 160:d5399cc887bb 25 #include "platform/mbed_stats.h"
AnnaBridge 167:e84263d55307 26 #include "platform/mbed_critical.h"
<> 160:d5399cc887bb 27 #include <stdlib.h>
<> 160:d5399cc887bb 28 #include <string.h>
AnnaBridge 167:e84263d55307 29 #include <limits.h>
<> 160:d5399cc887bb 30 #if DEVICE_STDIO_MESSAGES
<> 160:d5399cc887bb 31 #include <stdio.h>
<> 160:d5399cc887bb 32 #endif
<> 160:d5399cc887bb 33 #include <errno.h>
<> 160:d5399cc887bb 34 #include "platform/mbed_retarget.h"
<> 160:d5399cc887bb 35
<> 160:d5399cc887bb 36 #if defined(__ARMCC_VERSION)
<> 160:d5399cc887bb 37 # include <rt_sys.h>
<> 160:d5399cc887bb 38 # define PREFIX(x) _sys##x
<> 160:d5399cc887bb 39 # define OPEN_MAX _SYS_OPEN
<> 160:d5399cc887bb 40 # ifdef __MICROLIB
<> 160:d5399cc887bb 41 # pragma import(__use_full_stdio)
<> 160:d5399cc887bb 42 # endif
<> 160:d5399cc887bb 43
<> 160:d5399cc887bb 44 #elif defined(__ICCARM__)
<> 160:d5399cc887bb 45 # include <yfuns.h>
<> 160:d5399cc887bb 46 # define PREFIX(x) _##x
<> 160:d5399cc887bb 47 # define OPEN_MAX 16
<> 160:d5399cc887bb 48
<> 160:d5399cc887bb 49 # define STDIN_FILENO 0
<> 160:d5399cc887bb 50 # define STDOUT_FILENO 1
<> 160:d5399cc887bb 51 # define STDERR_FILENO 2
<> 160:d5399cc887bb 52
<> 160:d5399cc887bb 53 #else
<> 160:d5399cc887bb 54 # include <sys/stat.h>
<> 160:d5399cc887bb 55 # include <sys/syslimits.h>
<> 160:d5399cc887bb 56 # define PREFIX(x) x
<> 160:d5399cc887bb 57 #endif
<> 160:d5399cc887bb 58
<> 160:d5399cc887bb 59 #define FILE_HANDLE_RESERVED 0xFFFFFFFF
<> 160:d5399cc887bb 60
<> 160:d5399cc887bb 61 using namespace mbed;
<> 160:d5399cc887bb 62
<> 160:d5399cc887bb 63 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
<> 160:d5399cc887bb 64 // Before version 5.03, we were using a patched version of microlib with proper names
<> 160:d5399cc887bb 65 extern const char __stdin_name[] = ":tt";
<> 160:d5399cc887bb 66 extern const char __stdout_name[] = ":tt";
<> 160:d5399cc887bb 67 extern const char __stderr_name[] = ":tt";
<> 160:d5399cc887bb 68
<> 160:d5399cc887bb 69 #else
<> 160:d5399cc887bb 70 extern const char __stdin_name[] = "/stdin";
<> 160:d5399cc887bb 71 extern const char __stdout_name[] = "/stdout";
<> 160:d5399cc887bb 72 extern const char __stderr_name[] = "/stderr";
<> 160:d5399cc887bb 73 #endif
<> 160:d5399cc887bb 74
<> 160:d5399cc887bb 75 unsigned char *mbed_heap_start = 0;
<> 160:d5399cc887bb 76 uint32_t mbed_heap_size = 0;
<> 160:d5399cc887bb 77
<> 160:d5399cc887bb 78 /* newlib has the filehandle field in the FILE struct as a short, so
<> 160:d5399cc887bb 79 * we can't just return a Filehandle* from _open and instead have to
<> 160:d5399cc887bb 80 * put it in a filehandles array and return the index into that array
<> 160:d5399cc887bb 81 * (or rather index+3, as filehandles 0-2 are stdin/out/err).
<> 160:d5399cc887bb 82 */
AnnaBridge 167:e84263d55307 83 static FileHandle *filehandles[OPEN_MAX];
<> 160:d5399cc887bb 84 static SingletonPtr<PlatformMutex> filehandle_mutex;
<> 160:d5399cc887bb 85
<> 160:d5399cc887bb 86 namespace mbed {
AnnaBridge 167:e84263d55307 87 void remove_filehandle(FileHandle *file) {
<> 160:d5399cc887bb 88 filehandle_mutex->lock();
<> 160:d5399cc887bb 89 /* Remove all open filehandles for this */
<> 160:d5399cc887bb 90 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
<> 160:d5399cc887bb 91 if (filehandles[fh_i] == file) {
<> 160:d5399cc887bb 92 filehandles[fh_i] = NULL;
<> 160:d5399cc887bb 93 }
<> 160:d5399cc887bb 94 }
<> 160:d5399cc887bb 95 filehandle_mutex->unlock();
<> 160:d5399cc887bb 96 }
<> 160:d5399cc887bb 97 }
<> 160:d5399cc887bb 98
<> 160:d5399cc887bb 99 #if DEVICE_SERIAL
<> 160:d5399cc887bb 100 extern int stdio_uart_inited;
<> 160:d5399cc887bb 101 extern serial_t stdio_uart;
<> 160:d5399cc887bb 102 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
<> 160:d5399cc887bb 103 static char stdio_in_prev;
<> 160:d5399cc887bb 104 static char stdio_out_prev;
<> 160:d5399cc887bb 105 #endif
<> 160:d5399cc887bb 106 #endif
<> 160:d5399cc887bb 107
<> 160:d5399cc887bb 108 static void init_serial() {
<> 160:d5399cc887bb 109 #if DEVICE_SERIAL
<> 160:d5399cc887bb 110 if (stdio_uart_inited) return;
<> 160:d5399cc887bb 111 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
<> 160:d5399cc887bb 112 #if MBED_CONF_PLATFORM_STDIO_BAUD_RATE
<> 160:d5399cc887bb 113 serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
<> 160:d5399cc887bb 114 #endif
<> 160:d5399cc887bb 115 #endif
<> 160:d5399cc887bb 116 }
<> 160:d5399cc887bb 117
AnnaBridge 167:e84263d55307 118 /**
AnnaBridge 167:e84263d55307 119 * Sets errno when file opening fails.
AnnaBridge 167:e84263d55307 120 * Wipes out the filehandle too.
AnnaBridge 167:e84263d55307 121 *
AnnaBridge 167:e84263d55307 122 * @param error is a negative error code returned from an mbed function and
AnnaBridge 167:e84263d55307 123 * will be negated to store a positive error code in errno
AnnaBridge 167:e84263d55307 124 */
AnnaBridge 167:e84263d55307 125 static int handle_open_errors(int error, unsigned filehandle_idx) {
AnnaBridge 167:e84263d55307 126 errno = -error;
AnnaBridge 167:e84263d55307 127 // Free file handle
AnnaBridge 167:e84263d55307 128 filehandles[filehandle_idx] = NULL;
AnnaBridge 167:e84263d55307 129 return -1;
AnnaBridge 167:e84263d55307 130 }
AnnaBridge 167:e84263d55307 131
<> 160:d5399cc887bb 132 static inline int openmode_to_posix(int openmode) {
<> 160:d5399cc887bb 133 int posix = openmode;
<> 160:d5399cc887bb 134 #ifdef __ARMCC_VERSION
<> 160:d5399cc887bb 135 if (openmode & OPEN_PLUS) {
<> 160:d5399cc887bb 136 posix = O_RDWR;
<> 160:d5399cc887bb 137 } else if(openmode & OPEN_W) {
<> 160:d5399cc887bb 138 posix = O_WRONLY;
<> 160:d5399cc887bb 139 } else if(openmode & OPEN_A) {
<> 160:d5399cc887bb 140 posix = O_WRONLY|O_APPEND;
<> 160:d5399cc887bb 141 } else {
<> 160:d5399cc887bb 142 posix = O_RDONLY;
<> 160:d5399cc887bb 143 }
<> 160:d5399cc887bb 144 /* a, w, a+, w+ all create if file does not already exist */
<> 160:d5399cc887bb 145 if (openmode & (OPEN_A|OPEN_W)) {
<> 160:d5399cc887bb 146 posix |= O_CREAT;
<> 160:d5399cc887bb 147 }
<> 160:d5399cc887bb 148 /* w and w+ truncate */
<> 160:d5399cc887bb 149 if (openmode & OPEN_W) {
<> 160:d5399cc887bb 150 posix |= O_TRUNC;
<> 160:d5399cc887bb 151 }
<> 160:d5399cc887bb 152 #elif defined(__ICCARM__)
<> 160:d5399cc887bb 153 switch (openmode & _LLIO_RDWRMASK) {
<> 160:d5399cc887bb 154 case _LLIO_RDONLY: posix = O_RDONLY; break;
<> 160:d5399cc887bb 155 case _LLIO_WRONLY: posix = O_WRONLY; break;
<> 160:d5399cc887bb 156 case _LLIO_RDWR : posix = O_RDWR ; break;
<> 160:d5399cc887bb 157 }
<> 160:d5399cc887bb 158 if (openmode & _LLIO_CREAT ) posix |= O_CREAT;
<> 160:d5399cc887bb 159 if (openmode & _LLIO_APPEND) posix |= O_APPEND;
<> 160:d5399cc887bb 160 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC;
<> 160:d5399cc887bb 161 #elif defined(TOOLCHAIN_GCC)
<> 160:d5399cc887bb 162 posix &= ~O_BINARY;
<> 160:d5399cc887bb 163 #endif
<> 160:d5399cc887bb 164 return posix;
<> 160:d5399cc887bb 165 }
<> 160:d5399cc887bb 166
<> 160:d5399cc887bb 167 /* @brief standard c library fopen() retargeting function.
<> 160:d5399cc887bb 168 *
<> 160:d5399cc887bb 169 * This function is invoked by the standard c library retargeting to handle fopen()
<> 160:d5399cc887bb 170 *
<> 160:d5399cc887bb 171 * @return
<> 160:d5399cc887bb 172 * On success, a valid FILEHANDLE is returned.
<> 160:d5399cc887bb 173 * On failure, -1 is returned and errno is set to an appropriate value e.g.
AnnaBridge 167:e84263d55307 174 * ENOENT file not found (default errno setting)
<> 160:d5399cc887bb 175 * EMFILE the maximum number of open files was exceeded.
<> 160:d5399cc887bb 176 *
<> 160:d5399cc887bb 177 * */
<> 160:d5399cc887bb 178 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
<> 160:d5399cc887bb 179 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
AnnaBridge 168:9672193075cf 180 #if !defined(MBED_CONF_RTOS_PRESENT)
AnnaBridge 168:9672193075cf 181 // valid only for mbed 2
AnnaBridge 168:9672193075cf 182 // for ulib, this is invoked after RAM init, prior c++
AnnaBridge 168:9672193075cf 183 // used as hook, as post stack/heap is not active there
AnnaBridge 168:9672193075cf 184 extern void mbed_copy_nvic(void);
AnnaBridge 168:9672193075cf 185 extern void mbed_sdk_init(void);
AnnaBridge 168:9672193075cf 186
AnnaBridge 168:9672193075cf 187 static int mbed_sdk_inited = 0;
AnnaBridge 168:9672193075cf 188 if (!mbed_sdk_inited) {
AnnaBridge 168:9672193075cf 189 mbed_copy_nvic();
AnnaBridge 168:9672193075cf 190 mbed_sdk_init();
AnnaBridge 168:9672193075cf 191 mbed_sdk_inited = 1;
AnnaBridge 168:9672193075cf 192 }
AnnaBridge 168:9672193075cf 193 #endif
<> 160:d5399cc887bb 194 // Before version 5.03, we were using a patched version of microlib with proper names
<> 160:d5399cc887bb 195 // This is the workaround that the microlib author suggested us
<> 160:d5399cc887bb 196 static int n = 0;
<> 160:d5399cc887bb 197 if (!std::strcmp(name, ":tt")) return n++;
<> 160:d5399cc887bb 198 #else
<> 160:d5399cc887bb 199 /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
<> 160:d5399cc887bb 200 */
<> 160:d5399cc887bb 201 if (std::strcmp(name, __stdin_name) == 0) {
<> 160:d5399cc887bb 202 init_serial();
<> 160:d5399cc887bb 203 return 0;
<> 160:d5399cc887bb 204 } else if (std::strcmp(name, __stdout_name) == 0) {
<> 160:d5399cc887bb 205 init_serial();
<> 160:d5399cc887bb 206 return 1;
<> 160:d5399cc887bb 207 } else if (std::strcmp(name, __stderr_name) == 0) {
<> 160:d5399cc887bb 208 init_serial();
<> 160:d5399cc887bb 209 return 2;
<> 160:d5399cc887bb 210 }
<> 160:d5399cc887bb 211 #endif
<> 160:d5399cc887bb 212
<> 160:d5399cc887bb 213 // find the first empty slot in filehandles
<> 160:d5399cc887bb 214 filehandle_mutex->lock();
<> 160:d5399cc887bb 215 unsigned int fh_i;
<> 160:d5399cc887bb 216 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
<> 160:d5399cc887bb 217 /* Take a next free filehandle slot available. */
<> 160:d5399cc887bb 218 if (filehandles[fh_i] == NULL) break;
<> 160:d5399cc887bb 219 }
<> 160:d5399cc887bb 220 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) {
<> 160:d5399cc887bb 221 /* Too many file handles have been opened */
<> 160:d5399cc887bb 222 errno = EMFILE;
<> 160:d5399cc887bb 223 filehandle_mutex->unlock();
<> 160:d5399cc887bb 224 return -1;
<> 160:d5399cc887bb 225 }
AnnaBridge 167:e84263d55307 226 filehandles[fh_i] = (FileHandle*)FILE_HANDLE_RESERVED;
<> 160:d5399cc887bb 227 filehandle_mutex->unlock();
<> 160:d5399cc887bb 228
AnnaBridge 167:e84263d55307 229 FileHandle *res = NULL;
<> 160:d5399cc887bb 230
AnnaBridge 167:e84263d55307 231 /* FILENAME: ":0x12345678" describes a FileHandle* */
<> 160:d5399cc887bb 232 if (name[0] == ':') {
<> 160:d5399cc887bb 233 void *p;
AnnaBridge 167:e84263d55307 234 std::sscanf(name, ":%p", &p);
AnnaBridge 167:e84263d55307 235 res = (FileHandle*)p;
<> 160:d5399cc887bb 236
<> 160:d5399cc887bb 237 /* FILENAME: "/file_system/file_name" */
<> 160:d5399cc887bb 238 } else {
<> 160:d5399cc887bb 239 FilePath path(name);
<> 160:d5399cc887bb 240
<> 160:d5399cc887bb 241 if (!path.exists()) {
<> 160:d5399cc887bb 242 /* The first part of the filename (between first 2 '/') is not a
<> 160:d5399cc887bb 243 * registered mount point in the namespace.
<> 160:d5399cc887bb 244 */
AnnaBridge 167:e84263d55307 245 return handle_open_errors(-ENOENT, fh_i);
AnnaBridge 167:e84263d55307 246 }
AnnaBridge 167:e84263d55307 247
AnnaBridge 167:e84263d55307 248 if (path.isFile()) {
<> 160:d5399cc887bb 249 res = path.file();
<> 160:d5399cc887bb 250 } else {
AnnaBridge 167:e84263d55307 251 FileSystemHandle *fs = path.fileSystem();
<> 160:d5399cc887bb 252 if (fs == NULL) {
AnnaBridge 167:e84263d55307 253 return handle_open_errors(-ENOENT, fh_i);
<> 160:d5399cc887bb 254 }
<> 160:d5399cc887bb 255 int posix_mode = openmode_to_posix(openmode);
AnnaBridge 167:e84263d55307 256 int err = fs->open(&res, path.fileName(), posix_mode);
AnnaBridge 167:e84263d55307 257 if (err) {
AnnaBridge 167:e84263d55307 258 return handle_open_errors(err, fh_i);
<> 160:d5399cc887bb 259 }
<> 160:d5399cc887bb 260 }
<> 160:d5399cc887bb 261 }
<> 160:d5399cc887bb 262
<> 160:d5399cc887bb 263 filehandles[fh_i] = res;
<> 160:d5399cc887bb 264
<> 160:d5399cc887bb 265 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err
<> 160:d5399cc887bb 266 }
<> 160:d5399cc887bb 267
<> 160:d5399cc887bb 268 extern "C" int PREFIX(_close)(FILEHANDLE fh) {
<> 160:d5399cc887bb 269 if (fh < 3) return 0;
<> 160:d5399cc887bb 270
AnnaBridge 167:e84263d55307 271 FileHandle* fhc = filehandles[fh-3];
<> 160:d5399cc887bb 272 filehandles[fh-3] = NULL;
AnnaBridge 167:e84263d55307 273 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 274 errno = EBADF;
AnnaBridge 167:e84263d55307 275 return -1;
AnnaBridge 167:e84263d55307 276 }
<> 160:d5399cc887bb 277
<> 160:d5399cc887bb 278 int err = fhc->close();
<> 160:d5399cc887bb 279 if (err < 0) {
<> 160:d5399cc887bb 280 errno = -err;
<> 160:d5399cc887bb 281 return -1;
<> 160:d5399cc887bb 282 } else {
<> 160:d5399cc887bb 283 return 0;
<> 160:d5399cc887bb 284 }
<> 160:d5399cc887bb 285 }
<> 160:d5399cc887bb 286
<> 160:d5399cc887bb 287 #if defined(__ICCARM__)
<> 160:d5399cc887bb 288 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) {
<> 160:d5399cc887bb 289 #else
<> 160:d5399cc887bb 290 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) {
<> 160:d5399cc887bb 291 #endif
<> 160:d5399cc887bb 292 int n; // n is the number of bytes written
<> 160:d5399cc887bb 293
AnnaBridge 167:e84263d55307 294 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
AnnaBridge 167:e84263d55307 295 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
AnnaBridge 167:e84263d55307 296 error("Error - writing to a file in an ISR or critical section\r\n");
AnnaBridge 167:e84263d55307 297 }
AnnaBridge 167:e84263d55307 298 #endif
AnnaBridge 167:e84263d55307 299
<> 160:d5399cc887bb 300 if (fh < 3) {
<> 160:d5399cc887bb 301 #if DEVICE_SERIAL
<> 160:d5399cc887bb 302 if (!stdio_uart_inited) init_serial();
<> 160:d5399cc887bb 303 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
<> 160:d5399cc887bb 304 for (unsigned int i = 0; i < length; i++) {
<> 160:d5399cc887bb 305 if (buffer[i] == '\n' && stdio_out_prev != '\r') {
<> 160:d5399cc887bb 306 serial_putc(&stdio_uart, '\r');
<> 160:d5399cc887bb 307 }
<> 160:d5399cc887bb 308 serial_putc(&stdio_uart, buffer[i]);
<> 160:d5399cc887bb 309 stdio_out_prev = buffer[i];
<> 160:d5399cc887bb 310 }
<> 160:d5399cc887bb 311 #else
<> 160:d5399cc887bb 312 for (unsigned int i = 0; i < length; i++) {
<> 160:d5399cc887bb 313 serial_putc(&stdio_uart, buffer[i]);
<> 160:d5399cc887bb 314 }
<> 160:d5399cc887bb 315 #endif
<> 160:d5399cc887bb 316 #endif
<> 160:d5399cc887bb 317 n = length;
<> 160:d5399cc887bb 318 } else {
AnnaBridge 167:e84263d55307 319 FileHandle* fhc = filehandles[fh-3];
AnnaBridge 167:e84263d55307 320 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 321 errno = EBADF;
AnnaBridge 167:e84263d55307 322 return -1;
AnnaBridge 167:e84263d55307 323 }
<> 160:d5399cc887bb 324
<> 160:d5399cc887bb 325 n = fhc->write(buffer, length);
<> 160:d5399cc887bb 326 if (n < 0) {
<> 160:d5399cc887bb 327 errno = -n;
<> 160:d5399cc887bb 328 }
<> 160:d5399cc887bb 329 }
<> 160:d5399cc887bb 330 #ifdef __ARMCC_VERSION
<> 160:d5399cc887bb 331 return length-n;
<> 160:d5399cc887bb 332 #else
<> 160:d5399cc887bb 333 return n;
<> 160:d5399cc887bb 334 #endif
<> 160:d5399cc887bb 335 }
<> 160:d5399cc887bb 336
<> 160:d5399cc887bb 337 #if defined(__ICCARM__)
<> 160:d5399cc887bb 338 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) {
<> 160:d5399cc887bb 339 #else
<> 160:d5399cc887bb 340 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) {
<> 160:d5399cc887bb 341 #endif
<> 160:d5399cc887bb 342 int n; // n is the number of bytes read
<> 160:d5399cc887bb 343
AnnaBridge 167:e84263d55307 344 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
AnnaBridge 167:e84263d55307 345 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
AnnaBridge 167:e84263d55307 346 error("Error - reading from a file in an ISR or critical section\r\n");
AnnaBridge 167:e84263d55307 347 }
AnnaBridge 167:e84263d55307 348 #endif
AnnaBridge 167:e84263d55307 349
<> 160:d5399cc887bb 350 if (fh < 3) {
<> 160:d5399cc887bb 351 // only read a character at a time from stdin
<> 160:d5399cc887bb 352 #if DEVICE_SERIAL
<> 160:d5399cc887bb 353 if (!stdio_uart_inited) init_serial();
<> 160:d5399cc887bb 354 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
<> 160:d5399cc887bb 355 while (true) {
<> 160:d5399cc887bb 356 char c = serial_getc(&stdio_uart);
<> 160:d5399cc887bb 357 if ((c == '\r' && stdio_in_prev != '\n') ||
<> 160:d5399cc887bb 358 (c == '\n' && stdio_in_prev != '\r')) {
<> 160:d5399cc887bb 359 stdio_in_prev = c;
<> 160:d5399cc887bb 360 *buffer = '\n';
<> 160:d5399cc887bb 361 break;
<> 160:d5399cc887bb 362 } else if ((c == '\r' && stdio_in_prev == '\n') ||
<> 160:d5399cc887bb 363 (c == '\n' && stdio_in_prev == '\r')) {
<> 160:d5399cc887bb 364 stdio_in_prev = c;
<> 160:d5399cc887bb 365 // onto next character
<> 160:d5399cc887bb 366 continue;
<> 160:d5399cc887bb 367 } else {
<> 160:d5399cc887bb 368 stdio_in_prev = c;
<> 160:d5399cc887bb 369 *buffer = c;
<> 160:d5399cc887bb 370 break;
<> 160:d5399cc887bb 371 }
<> 160:d5399cc887bb 372 }
<> 160:d5399cc887bb 373 #else
<> 160:d5399cc887bb 374 *buffer = serial_getc(&stdio_uart);
<> 160:d5399cc887bb 375 #endif
<> 160:d5399cc887bb 376 #endif
<> 160:d5399cc887bb 377 n = 1;
<> 160:d5399cc887bb 378 } else {
AnnaBridge 167:e84263d55307 379 FileHandle* fhc = filehandles[fh-3];
AnnaBridge 167:e84263d55307 380 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 381 errno = EBADF;
AnnaBridge 167:e84263d55307 382 return -1;
AnnaBridge 167:e84263d55307 383 }
<> 160:d5399cc887bb 384
<> 160:d5399cc887bb 385 n = fhc->read(buffer, length);
<> 160:d5399cc887bb 386 if (n < 0) {
<> 160:d5399cc887bb 387 errno = -n;
<> 160:d5399cc887bb 388 }
<> 160:d5399cc887bb 389 }
<> 160:d5399cc887bb 390 #ifdef __ARMCC_VERSION
<> 160:d5399cc887bb 391 return length-n;
<> 160:d5399cc887bb 392 #else
<> 160:d5399cc887bb 393 return n;
<> 160:d5399cc887bb 394 #endif
<> 160:d5399cc887bb 395 }
<> 160:d5399cc887bb 396
AnnaBridge 167:e84263d55307 397
<> 160:d5399cc887bb 398 #ifdef __ARMCC_VERSION
<> 160:d5399cc887bb 399 extern "C" int PREFIX(_istty)(FILEHANDLE fh)
<> 160:d5399cc887bb 400 #else
<> 160:d5399cc887bb 401 extern "C" int _isatty(FILEHANDLE fh)
<> 160:d5399cc887bb 402 #endif
<> 160:d5399cc887bb 403 {
<> 160:d5399cc887bb 404 /* stdin, stdout and stderr should be tty */
<> 160:d5399cc887bb 405 if (fh < 3) return 1;
<> 160:d5399cc887bb 406
AnnaBridge 167:e84263d55307 407 FileHandle* fhc = filehandles[fh-3];
AnnaBridge 167:e84263d55307 408 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 409 errno = EBADF;
AnnaBridge 167:e84263d55307 410 return 0;
AnnaBridge 167:e84263d55307 411 }
<> 160:d5399cc887bb 412
AnnaBridge 167:e84263d55307 413 int tty = fhc->isatty();
AnnaBridge 167:e84263d55307 414 if (tty < 0) {
AnnaBridge 167:e84263d55307 415 errno = -tty;
AnnaBridge 167:e84263d55307 416 return 0;
<> 160:d5399cc887bb 417 } else {
AnnaBridge 167:e84263d55307 418 return tty;
<> 160:d5399cc887bb 419 }
<> 160:d5399cc887bb 420 }
<> 160:d5399cc887bb 421
<> 160:d5399cc887bb 422 extern "C"
<> 160:d5399cc887bb 423 #if defined(__ARMCC_VERSION)
AnnaBridge 167:e84263d55307 424 int _sys_seek(FILEHANDLE fh, long offset)
<> 160:d5399cc887bb 425 #elif defined(__ICCARM__)
<> 160:d5399cc887bb 426 long __lseek(int fh, long offset, int whence)
<> 160:d5399cc887bb 427 #else
<> 160:d5399cc887bb 428 int _lseek(FILEHANDLE fh, int offset, int whence)
<> 160:d5399cc887bb 429 #endif
<> 160:d5399cc887bb 430 {
AnnaBridge 167:e84263d55307 431 #if defined(__ARMCC_VERSION)
AnnaBridge 167:e84263d55307 432 int whence = SEEK_SET;
AnnaBridge 167:e84263d55307 433 #endif
AnnaBridge 167:e84263d55307 434 if (fh < 3) {
AnnaBridge 167:e84263d55307 435 errno = ESPIPE;
AnnaBridge 167:e84263d55307 436 return -1;
AnnaBridge 167:e84263d55307 437 }
<> 160:d5399cc887bb 438
AnnaBridge 167:e84263d55307 439 FileHandle* fhc = filehandles[fh-3];
AnnaBridge 167:e84263d55307 440 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 441 errno = EBADF;
AnnaBridge 167:e84263d55307 442 return -1;
AnnaBridge 167:e84263d55307 443 }
AnnaBridge 167:e84263d55307 444
AnnaBridge 167:e84263d55307 445 off_t off = fhc->seek(offset, whence);
AnnaBridge 167:e84263d55307 446 if (off < 0) {
AnnaBridge 167:e84263d55307 447 errno = -off;
AnnaBridge 167:e84263d55307 448 return -1;
AnnaBridge 167:e84263d55307 449 }
AnnaBridge 167:e84263d55307 450 // Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference
AnnaBridge 167:e84263d55307 451 if (off > INT_MAX) {
AnnaBridge 167:e84263d55307 452 errno = EOVERFLOW;
AnnaBridge 167:e84263d55307 453 return -1;
AnnaBridge 167:e84263d55307 454 }
AnnaBridge 167:e84263d55307 455 return off;
<> 160:d5399cc887bb 456 }
<> 160:d5399cc887bb 457
<> 160:d5399cc887bb 458 #ifdef __ARMCC_VERSION
<> 160:d5399cc887bb 459 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) {
<> 160:d5399cc887bb 460 if (fh < 3) return 0;
<> 160:d5399cc887bb 461
AnnaBridge 167:e84263d55307 462 FileHandle* fhc = filehandles[fh-3];
AnnaBridge 167:e84263d55307 463 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 464 errno = EBADF;
AnnaBridge 167:e84263d55307 465 return -1;
AnnaBridge 167:e84263d55307 466 }
<> 160:d5399cc887bb 467
<> 160:d5399cc887bb 468 int err = fhc->sync();
<> 160:d5399cc887bb 469 if (err < 0) {
<> 160:d5399cc887bb 470 errno = -err;
<> 160:d5399cc887bb 471 return -1;
<> 160:d5399cc887bb 472 } else {
<> 160:d5399cc887bb 473 return 0;
<> 160:d5399cc887bb 474 }
<> 160:d5399cc887bb 475 }
<> 160:d5399cc887bb 476
<> 160:d5399cc887bb 477 extern "C" long PREFIX(_flen)(FILEHANDLE fh) {
AnnaBridge 167:e84263d55307 478 if (fh < 3) {
AnnaBridge 167:e84263d55307 479 errno = EINVAL;
AnnaBridge 167:e84263d55307 480 return -1;
AnnaBridge 167:e84263d55307 481 }
AnnaBridge 167:e84263d55307 482
AnnaBridge 167:e84263d55307 483 FileHandle* fhc = filehandles[fh-3];
AnnaBridge 167:e84263d55307 484 if (fhc == NULL) {
AnnaBridge 167:e84263d55307 485 errno = EBADF;
AnnaBridge 167:e84263d55307 486 return -1;
AnnaBridge 167:e84263d55307 487 }
<> 160:d5399cc887bb 488
AnnaBridge 167:e84263d55307 489 off_t size = fhc->size();
AnnaBridge 167:e84263d55307 490 if (size < 0) {
AnnaBridge 167:e84263d55307 491 errno = -size;
AnnaBridge 167:e84263d55307 492 return -1;
AnnaBridge 167:e84263d55307 493 }
AnnaBridge 167:e84263d55307 494 if (size > LONG_MAX) {
AnnaBridge 167:e84263d55307 495 errno = EOVERFLOW;
AnnaBridge 167:e84263d55307 496 return -1;
AnnaBridge 167:e84263d55307 497 }
AnnaBridge 167:e84263d55307 498 return size;
<> 160:d5399cc887bb 499 }
<> 160:d5399cc887bb 500 #endif
<> 160:d5399cc887bb 501
<> 160:d5399cc887bb 502
<> 160:d5399cc887bb 503 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
<> 160:d5399cc887bb 504 extern "C" int _fstat(int fd, struct stat *st) {
<> 160:d5399cc887bb 505 if (fd < 3) {
<> 160:d5399cc887bb 506 st->st_mode = S_IFCHR;
<> 160:d5399cc887bb 507 return 0;
<> 160:d5399cc887bb 508 }
<> 160:d5399cc887bb 509 errno = EBADF;
<> 160:d5399cc887bb 510 return -1;
<> 160:d5399cc887bb 511 }
<> 160:d5399cc887bb 512 #endif
<> 160:d5399cc887bb 513
<> 160:d5399cc887bb 514 namespace std {
<> 160:d5399cc887bb 515 extern "C" int remove(const char *path) {
<> 160:d5399cc887bb 516 FilePath fp(path);
AnnaBridge 167:e84263d55307 517 FileSystemHandle *fs = fp.fileSystem();
AnnaBridge 167:e84263d55307 518 if (fs == NULL) {
AnnaBridge 167:e84263d55307 519 errno = ENOENT;
AnnaBridge 167:e84263d55307 520 return -1;
AnnaBridge 167:e84263d55307 521 }
<> 160:d5399cc887bb 522
<> 160:d5399cc887bb 523 int err = fs->remove(fp.fileName());
<> 160:d5399cc887bb 524 if (err < 0) {
<> 160:d5399cc887bb 525 errno = -err;
<> 160:d5399cc887bb 526 return -1;
<> 160:d5399cc887bb 527 } else {
<> 160:d5399cc887bb 528 return 0;
<> 160:d5399cc887bb 529 }
<> 160:d5399cc887bb 530 }
<> 160:d5399cc887bb 531
<> 160:d5399cc887bb 532 extern "C" int rename(const char *oldname, const char *newname) {
<> 160:d5399cc887bb 533 FilePath fpOld(oldname);
<> 160:d5399cc887bb 534 FilePath fpNew(newname);
AnnaBridge 167:e84263d55307 535 FileSystemHandle *fsOld = fpOld.fileSystem();
AnnaBridge 167:e84263d55307 536 FileSystemHandle *fsNew = fpNew.fileSystem();
AnnaBridge 167:e84263d55307 537
AnnaBridge 167:e84263d55307 538 if (fsOld == NULL) {
AnnaBridge 167:e84263d55307 539 errno = ENOENT;
AnnaBridge 167:e84263d55307 540 return -1;
AnnaBridge 167:e84263d55307 541 }
<> 160:d5399cc887bb 542
<> 160:d5399cc887bb 543 /* rename only if both files are on the same FS */
AnnaBridge 167:e84263d55307 544 if (fsOld != fsNew) {
AnnaBridge 167:e84263d55307 545 errno = EXDEV;
AnnaBridge 167:e84263d55307 546 return -1;
AnnaBridge 167:e84263d55307 547 }
<> 160:d5399cc887bb 548
<> 160:d5399cc887bb 549 int err = fsOld->rename(fpOld.fileName(), fpNew.fileName());
<> 160:d5399cc887bb 550 if (err < 0) {
<> 160:d5399cc887bb 551 errno = -err;
<> 160:d5399cc887bb 552 return -1;
<> 160:d5399cc887bb 553 } else {
<> 160:d5399cc887bb 554 return 0;
<> 160:d5399cc887bb 555 }
<> 160:d5399cc887bb 556 }
<> 160:d5399cc887bb 557
<> 160:d5399cc887bb 558 extern "C" char *tmpnam(char *s) {
<> 160:d5399cc887bb 559 errno = EBADF;
<> 160:d5399cc887bb 560 return NULL;
<> 160:d5399cc887bb 561 }
<> 160:d5399cc887bb 562
<> 160:d5399cc887bb 563 extern "C" FILE *tmpfile() {
<> 160:d5399cc887bb 564 errno = EBADF;
<> 160:d5399cc887bb 565 return NULL;
<> 160:d5399cc887bb 566 }
<> 160:d5399cc887bb 567 } // namespace std
<> 160:d5399cc887bb 568
<> 160:d5399cc887bb 569 #ifdef __ARMCC_VERSION
<> 160:d5399cc887bb 570 extern "C" char *_sys_command_string(char *cmd, int len) {
<> 160:d5399cc887bb 571 return NULL;
<> 160:d5399cc887bb 572 }
<> 160:d5399cc887bb 573 #endif
<> 160:d5399cc887bb 574
<> 160:d5399cc887bb 575 extern "C" DIR *opendir(const char *path) {
AnnaBridge 167:e84263d55307 576 FilePath fp(path);
AnnaBridge 167:e84263d55307 577 FileSystemHandle* fs = fp.fileSystem();
AnnaBridge 167:e84263d55307 578 if (fs == NULL) {
AnnaBridge 167:e84263d55307 579 errno = ENOENT;
AnnaBridge 167:e84263d55307 580 return NULL;
AnnaBridge 167:e84263d55307 581 }
<> 160:d5399cc887bb 582
AnnaBridge 167:e84263d55307 583 DirHandle *dir;
AnnaBridge 167:e84263d55307 584 int err = fs->open(&dir, fp.fileName());
<> 160:d5399cc887bb 585 if (err < 0) {
<> 160:d5399cc887bb 586 errno = -err;
AnnaBridge 167:e84263d55307 587 return NULL;
<> 160:d5399cc887bb 588 }
<> 160:d5399cc887bb 589
<> 160:d5399cc887bb 590 return dir;
<> 160:d5399cc887bb 591 }
<> 160:d5399cc887bb 592
<> 160:d5399cc887bb 593 extern "C" struct dirent *readdir(DIR *dir) {
<> 160:d5399cc887bb 594 static struct dirent ent;
<> 160:d5399cc887bb 595 int err = dir->read(&ent);
<> 160:d5399cc887bb 596 if (err < 1) {
<> 160:d5399cc887bb 597 if (err < 0) {
<> 160:d5399cc887bb 598 errno = -err;
<> 160:d5399cc887bb 599 }
<> 160:d5399cc887bb 600 return NULL;
<> 160:d5399cc887bb 601 }
<> 160:d5399cc887bb 602
<> 160:d5399cc887bb 603 return &ent;
<> 160:d5399cc887bb 604 }
<> 160:d5399cc887bb 605
<> 160:d5399cc887bb 606 extern "C" int closedir(DIR *dir) {
<> 160:d5399cc887bb 607 int err = dir->close();
<> 160:d5399cc887bb 608 if (err < 0) {
<> 160:d5399cc887bb 609 errno = -err;
<> 160:d5399cc887bb 610 return -1;
<> 160:d5399cc887bb 611 } else {
<> 160:d5399cc887bb 612 return 0;
<> 160:d5399cc887bb 613 }
<> 160:d5399cc887bb 614 }
<> 160:d5399cc887bb 615
<> 160:d5399cc887bb 616 extern "C" void rewinddir(DIR *dir) {
<> 160:d5399cc887bb 617 dir->rewind();
<> 160:d5399cc887bb 618 }
<> 160:d5399cc887bb 619
<> 160:d5399cc887bb 620 extern "C" off_t telldir(DIR *dir) {
<> 160:d5399cc887bb 621 return dir->tell();
<> 160:d5399cc887bb 622 }
<> 160:d5399cc887bb 623
<> 160:d5399cc887bb 624 extern "C" void seekdir(DIR *dir, off_t off) {
<> 160:d5399cc887bb 625 dir->seek(off);
<> 160:d5399cc887bb 626 }
<> 160:d5399cc887bb 627
<> 160:d5399cc887bb 628 extern "C" int mkdir(const char *path, mode_t mode) {
<> 160:d5399cc887bb 629 FilePath fp(path);
AnnaBridge 167:e84263d55307 630 FileSystemHandle *fs = fp.fileSystem();
<> 160:d5399cc887bb 631 if (fs == NULL) return -1;
<> 160:d5399cc887bb 632
<> 160:d5399cc887bb 633 int err = fs->mkdir(fp.fileName(), mode);
<> 160:d5399cc887bb 634 if (err < 0) {
<> 160:d5399cc887bb 635 errno = -err;
<> 160:d5399cc887bb 636 return -1;
<> 160:d5399cc887bb 637 } else {
<> 160:d5399cc887bb 638 return 0;
<> 160:d5399cc887bb 639 }
<> 160:d5399cc887bb 640 }
<> 160:d5399cc887bb 641
<> 160:d5399cc887bb 642 extern "C" int stat(const char *path, struct stat *st) {
<> 160:d5399cc887bb 643 FilePath fp(path);
AnnaBridge 167:e84263d55307 644 FileSystemHandle *fs = fp.fileSystem();
<> 160:d5399cc887bb 645 if (fs == NULL) return -1;
<> 160:d5399cc887bb 646
<> 160:d5399cc887bb 647 int err = fs->stat(fp.fileName(), st);
<> 160:d5399cc887bb 648 if (err < 0) {
<> 160:d5399cc887bb 649 errno = -err;
<> 160:d5399cc887bb 650 return -1;
<> 160:d5399cc887bb 651 } else {
<> 160:d5399cc887bb 652 return 0;
<> 160:d5399cc887bb 653 }
<> 160:d5399cc887bb 654 }
<> 160:d5399cc887bb 655
<> 160:d5399cc887bb 656 #if defined(TOOLCHAIN_GCC)
<> 160:d5399cc887bb 657 /* prevents the exception handling name demangling code getting pulled in */
<> 160:d5399cc887bb 658 #include "mbed_error.h"
<> 160:d5399cc887bb 659 namespace __gnu_cxx {
<> 160:d5399cc887bb 660 void __verbose_terminate_handler() {
<> 160:d5399cc887bb 661 error("Exception");
<> 160:d5399cc887bb 662 }
<> 160:d5399cc887bb 663 }
<> 160:d5399cc887bb 664 extern "C" WEAK void __cxa_pure_virtual(void);
<> 160:d5399cc887bb 665 extern "C" WEAK void __cxa_pure_virtual(void) {
<> 160:d5399cc887bb 666 exit(1);
<> 160:d5399cc887bb 667 }
<> 160:d5399cc887bb 668
<> 160:d5399cc887bb 669 #endif
<> 160:d5399cc887bb 670
<> 160:d5399cc887bb 671 // Provide implementation of _sbrk (low-level dynamic memory allocation
<> 160:d5399cc887bb 672 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
<> 160:d5399cc887bb 673 // SP. This make it compatible with RTX RTOS thread stacks.
<> 160:d5399cc887bb 674 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
<> 160:d5399cc887bb 675
<> 160:d5399cc887bb 676 #if defined(TARGET_CORTEX_A)
<> 160:d5399cc887bb 677 extern "C" uint32_t __HeapLimit;
<> 160:d5399cc887bb 678 #endif
<> 160:d5399cc887bb 679
<> 160:d5399cc887bb 680 // Turn off the errno macro and use actual global variable instead.
<> 160:d5399cc887bb 681 #undef errno
<> 160:d5399cc887bb 682 extern "C" int errno;
<> 160:d5399cc887bb 683
<> 160:d5399cc887bb 684 // Dynamic memory allocation related syscall.
<> 160:d5399cc887bb 685 #if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453)
<> 160:d5399cc887bb 686 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
<> 160:d5399cc887bb 687 // __wrap__sbrk() is implemented in:
<> 160:d5399cc887bb 688 // TARGET_NUMAKER_PFM_NUC472 hal/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/retarget.c
<> 160:d5399cc887bb 689 // TARGET_NUMAKER_PFM_M453 hal/targets/cmsis/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/retarget.c
<> 160:d5399cc887bb 690 extern "C" void *__wrap__sbrk(int incr);
<> 160:d5399cc887bb 691 extern "C" caddr_t _sbrk(int incr) {
<> 160:d5399cc887bb 692 return (caddr_t) __wrap__sbrk(incr);
<> 160:d5399cc887bb 693 }
<> 160:d5399cc887bb 694 #else
AnnaBridge 167:e84263d55307 695 // Linker defined symbol used by _sbrk to indicate where heap should start.
AnnaBridge 167:e84263d55307 696 extern "C" uint32_t __end__;
<> 160:d5399cc887bb 697 extern "C" caddr_t _sbrk(int incr) {
<> 160:d5399cc887bb 698 static unsigned char* heap = (unsigned char*)&__end__;
<> 160:d5399cc887bb 699 unsigned char* prev_heap = heap;
<> 160:d5399cc887bb 700 unsigned char* new_heap = heap + incr;
<> 160:d5399cc887bb 701
AnnaBridge 167:e84263d55307 702 #if defined(TARGET_CORTEX_A)
<> 160:d5399cc887bb 703 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */
<> 160:d5399cc887bb 704 #else
<> 160:d5399cc887bb 705 if (new_heap >= (unsigned char*)__get_MSP()) {
<> 160:d5399cc887bb 706 #endif
<> 160:d5399cc887bb 707 errno = ENOMEM;
<> 160:d5399cc887bb 708 return (caddr_t)-1;
<> 160:d5399cc887bb 709 }
<> 160:d5399cc887bb 710
<> 160:d5399cc887bb 711 // Additional heap checking if set
<> 160:d5399cc887bb 712 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
<> 160:d5399cc887bb 713 errno = ENOMEM;
<> 160:d5399cc887bb 714 return (caddr_t)-1;
<> 160:d5399cc887bb 715 }
<> 160:d5399cc887bb 716
<> 160:d5399cc887bb 717 heap = new_heap;
<> 160:d5399cc887bb 718 return (caddr_t) prev_heap;
<> 160:d5399cc887bb 719 }
<> 160:d5399cc887bb 720 #endif
<> 160:d5399cc887bb 721 #endif
<> 160:d5399cc887bb 722
<> 160:d5399cc887bb 723 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
<> 160:d5399cc887bb 724 extern "C" void _exit(int return_code) {
<> 160:d5399cc887bb 725 #else
<> 160:d5399cc887bb 726 namespace std {
<> 160:d5399cc887bb 727 extern "C" void exit(int return_code) {
<> 160:d5399cc887bb 728 #endif
<> 160:d5399cc887bb 729
<> 160:d5399cc887bb 730 #if DEVICE_STDIO_MESSAGES
<> 160:d5399cc887bb 731 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
<> 160:d5399cc887bb 732 fflush(stdout);
<> 160:d5399cc887bb 733 fflush(stderr);
<> 160:d5399cc887bb 734 #endif
<> 160:d5399cc887bb 735 #endif
<> 160:d5399cc887bb 736
<> 160:d5399cc887bb 737 #if DEVICE_SEMIHOST
<> 160:d5399cc887bb 738 if (mbed_interface_connected()) {
<> 160:d5399cc887bb 739 semihost_exit();
<> 160:d5399cc887bb 740 }
<> 160:d5399cc887bb 741 #endif
<> 160:d5399cc887bb 742 if (return_code) {
<> 160:d5399cc887bb 743 mbed_die();
<> 160:d5399cc887bb 744 }
<> 160:d5399cc887bb 745
<> 160:d5399cc887bb 746 while (1);
<> 160:d5399cc887bb 747 }
<> 160:d5399cc887bb 748
<> 160:d5399cc887bb 749 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
<> 160:d5399cc887bb 750 } //namespace std
<> 160:d5399cc887bb 751 #endif
<> 160:d5399cc887bb 752
<> 160:d5399cc887bb 753 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
<> 160:d5399cc887bb 754
<> 160:d5399cc887bb 755 // This series of function disable the registration of global destructors
<> 160:d5399cc887bb 756 // in a dynamic table which will be called when the application exit.
<> 160:d5399cc887bb 757 // In mbed, program never exit properly, it dies.
<> 160:d5399cc887bb 758 // More informations about this topic for ARMCC here:
<> 160:d5399cc887bb 759 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
<> 160:d5399cc887bb 760 extern "C" {
<> 160:d5399cc887bb 761 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) {
<> 160:d5399cc887bb 762 return 1;
<> 160:d5399cc887bb 763 }
<> 160:d5399cc887bb 764
<> 160:d5399cc887bb 765 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) {
<> 160:d5399cc887bb 766 return 1;
<> 160:d5399cc887bb 767 }
<> 160:d5399cc887bb 768
<> 160:d5399cc887bb 769 void __cxa_finalize(void *handle) {
<> 160:d5399cc887bb 770 }
<> 160:d5399cc887bb 771
<> 160:d5399cc887bb 772 } // end of extern "C"
<> 160:d5399cc887bb 773
<> 160:d5399cc887bb 774 #endif
<> 160:d5399cc887bb 775
<> 160:d5399cc887bb 776
<> 160:d5399cc887bb 777 #if defined(TOOLCHAIN_GCC)
<> 160:d5399cc887bb 778
<> 160:d5399cc887bb 779 /*
<> 160:d5399cc887bb 780 * Depending on how newlib is configured, it is often not enough to define
<> 160:d5399cc887bb 781 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
<> 160:d5399cc887bb 782 * behavior regarding the registration of handlers with atexit.
<> 160:d5399cc887bb 783 *
<> 160:d5399cc887bb 784 * To overcome this limitation, exit and atexit are overriden here.
<> 160:d5399cc887bb 785 */
<> 160:d5399cc887bb 786 extern "C"{
<> 160:d5399cc887bb 787
<> 160:d5399cc887bb 788 /**
<> 160:d5399cc887bb 789 * @brief Retarget of exit for GCC.
<> 160:d5399cc887bb 790 * @details Unlike the standard version, this function doesn't call any function
<> 160:d5399cc887bb 791 * registered with atexit before calling _exit.
<> 160:d5399cc887bb 792 */
<> 160:d5399cc887bb 793 void __wrap_exit(int return_code) {
<> 160:d5399cc887bb 794 _exit(return_code);
<> 160:d5399cc887bb 795 }
<> 160:d5399cc887bb 796
<> 160:d5399cc887bb 797 /**
<> 160:d5399cc887bb 798 * @brief Retarget atexit from GCC.
<> 160:d5399cc887bb 799 * @details This function will always fail and never register any handler to be
<> 160:d5399cc887bb 800 * called at exit.
<> 160:d5399cc887bb 801 */
<> 160:d5399cc887bb 802 int __wrap_atexit(void (*func)()) {
<> 160:d5399cc887bb 803 return 1;
<> 160:d5399cc887bb 804 }
<> 160:d5399cc887bb 805
<> 160:d5399cc887bb 806 }
<> 160:d5399cc887bb 807
<> 160:d5399cc887bb 808 #endif
<> 160:d5399cc887bb 809
<> 160:d5399cc887bb 810
<> 160:d5399cc887bb 811
<> 160:d5399cc887bb 812 namespace mbed {
<> 160:d5399cc887bb 813
AnnaBridge 167:e84263d55307 814 void mbed_set_unbuffered_stream(std::FILE *_file) {
<> 160:d5399cc887bb 815 #if defined (__ICCARM__)
<> 160:d5399cc887bb 816 char buf[2];
AnnaBridge 167:e84263d55307 817 std::setvbuf(_file,buf,_IONBF,NULL);
<> 160:d5399cc887bb 818 #else
<> 160:d5399cc887bb 819 setbuf(_file, NULL);
<> 160:d5399cc887bb 820 #endif
<> 160:d5399cc887bb 821 }
<> 160:d5399cc887bb 822
AnnaBridge 167:e84263d55307 823 /* Applications are expected to use fdopen()
AnnaBridge 167:e84263d55307 824 * not this function directly. This code had to live here because FILE and FileHandle
AnnaBridge 167:e84263d55307 825 * processes are all linked together here.
AnnaBridge 167:e84263d55307 826 */
AnnaBridge 167:e84263d55307 827 std::FILE *mbed_fdopen(FileHandle *fh, const char *mode)
AnnaBridge 167:e84263d55307 828 {
AnnaBridge 167:e84263d55307 829 char buf[12]; /* :0x12345678 + null byte */
AnnaBridge 167:e84263d55307 830 std::sprintf(buf, ":%p", fh);
AnnaBridge 167:e84263d55307 831 std::FILE *stream = std::fopen(buf, mode);
AnnaBridge 167:e84263d55307 832 /* newlib-nano doesn't appear to ever call _isatty itself, so
AnnaBridge 167:e84263d55307 833 * happily fully buffers an interactive stream. Deal with that here.
AnnaBridge 167:e84263d55307 834 */
AnnaBridge 167:e84263d55307 835 if (stream && fh->isatty()) {
AnnaBridge 167:e84263d55307 836 mbed_set_unbuffered_stream(stream);
AnnaBridge 167:e84263d55307 837 }
AnnaBridge 167:e84263d55307 838 return stream;
AnnaBridge 167:e84263d55307 839 }
AnnaBridge 167:e84263d55307 840
AnnaBridge 167:e84263d55307 841 int mbed_getc(std::FILE *_file){
<> 160:d5399cc887bb 842 #if defined (__ICCARM__)
<> 160:d5399cc887bb 843 /*This is only valid for unbuffered streams*/
<> 160:d5399cc887bb 844 int res = std::fgetc(_file);
<> 160:d5399cc887bb 845 if (res>=0){
<> 160:d5399cc887bb 846 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
<> 160:d5399cc887bb 847 _file->_Rend = _file->_Wend;
<> 160:d5399cc887bb 848 _file->_Next = _file->_Wend;
AnnaBridge 167:e84263d55307 849 }
<> 160:d5399cc887bb 850 return res;
AnnaBridge 167:e84263d55307 851 #else
<> 160:d5399cc887bb 852 return std::fgetc(_file);
AnnaBridge 167:e84263d55307 853 #endif
<> 160:d5399cc887bb 854 }
<> 160:d5399cc887bb 855
AnnaBridge 167:e84263d55307 856 char* mbed_gets(char*s, int size, std::FILE *_file){
<> 160:d5399cc887bb 857 #if defined (__ICCARM__)
<> 160:d5399cc887bb 858 /*This is only valid for unbuffered streams*/
<> 160:d5399cc887bb 859 char *str = fgets(s,size,_file);
<> 160:d5399cc887bb 860 if (str!=NULL){
<> 160:d5399cc887bb 861 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
<> 160:d5399cc887bb 862 _file->_Rend = _file->_Wend;
<> 160:d5399cc887bb 863 _file->_Next = _file->_Wend;
<> 160:d5399cc887bb 864 }
<> 160:d5399cc887bb 865 return str;
AnnaBridge 167:e84263d55307 866 #else
<> 160:d5399cc887bb 867 return std::fgets(s,size,_file);
<> 160:d5399cc887bb 868 #endif
<> 160:d5399cc887bb 869 }
<> 160:d5399cc887bb 870
<> 160:d5399cc887bb 871 } // namespace mbed
<> 160:d5399cc887bb 872
<> 160:d5399cc887bb 873 #if defined (__ICCARM__)
<> 160:d5399cc887bb 874 // Stub out locks when an rtos is not present
<> 160:d5399cc887bb 875 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 876 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 877 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 878 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 879 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 880 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 881 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 882 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
<> 160:d5399cc887bb 883 #elif defined(__CC_ARM)
<> 160:d5399cc887bb 884 // Do nothing
<> 160:d5399cc887bb 885 #elif defined (__GNUC__)
<> 160:d5399cc887bb 886 struct _reent;
<> 160:d5399cc887bb 887 // Stub out locks when an rtos is not present
<> 160:d5399cc887bb 888 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {}
<> 160:d5399cc887bb 889 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {}
<> 160:d5399cc887bb 890 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {}
<> 160:d5399cc887bb 891 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {}
<> 160:d5399cc887bb 892
<> 160:d5399cc887bb 893 extern "C" void __malloc_lock( struct _reent *_r )
<> 160:d5399cc887bb 894 {
<> 160:d5399cc887bb 895 __rtos_malloc_lock(_r);
<> 160:d5399cc887bb 896 }
<> 160:d5399cc887bb 897
<> 160:d5399cc887bb 898 extern "C" void __malloc_unlock( struct _reent *_r )
<> 160:d5399cc887bb 899 {
<> 160:d5399cc887bb 900 __rtos_malloc_unlock(_r);
<> 160:d5399cc887bb 901 }
<> 160:d5399cc887bb 902
<> 160:d5399cc887bb 903 extern "C" void __env_lock( struct _reent *_r )
<> 160:d5399cc887bb 904 {
<> 160:d5399cc887bb 905 __rtos_env_lock(_r);
<> 160:d5399cc887bb 906 }
<> 160:d5399cc887bb 907
<> 160:d5399cc887bb 908 extern "C" void __env_unlock( struct _reent *_r )
<> 160:d5399cc887bb 909 {
<> 160:d5399cc887bb 910 __rtos_env_unlock(_r);
<> 160:d5399cc887bb 911 }
<> 160:d5399cc887bb 912
<> 160:d5399cc887bb 913 #define CXA_GUARD_INIT_DONE (1 << 0)
<> 160:d5399cc887bb 914 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
<> 160:d5399cc887bb 915 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
<> 160:d5399cc887bb 916
<> 160:d5399cc887bb 917 extern "C" int __cxa_guard_acquire(int *guard_object_p)
<> 160:d5399cc887bb 918 {
<> 160:d5399cc887bb 919 uint8_t *guard_object = (uint8_t *)guard_object_p;
<> 160:d5399cc887bb 920 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
<> 160:d5399cc887bb 921 return 0;
<> 160:d5399cc887bb 922 }
<> 160:d5399cc887bb 923 singleton_lock();
<> 160:d5399cc887bb 924 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
<> 160:d5399cc887bb 925 singleton_unlock();
<> 160:d5399cc887bb 926 return 0;
<> 160:d5399cc887bb 927 }
<> 160:d5399cc887bb 928 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
<> 160:d5399cc887bb 929 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
<> 160:d5399cc887bb 930 return 1;
<> 160:d5399cc887bb 931 }
<> 160:d5399cc887bb 932
<> 160:d5399cc887bb 933 extern "C" void __cxa_guard_release(int *guard_object_p)
<> 160:d5399cc887bb 934 {
<> 160:d5399cc887bb 935 uint8_t *guard_object = (uint8_t *)guard_object_p;
<> 160:d5399cc887bb 936 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
<> 160:d5399cc887bb 937 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
<> 160:d5399cc887bb 938 singleton_unlock();
<> 160:d5399cc887bb 939 }
<> 160:d5399cc887bb 940
<> 160:d5399cc887bb 941 extern "C" void __cxa_guard_abort(int *guard_object_p)
<> 160:d5399cc887bb 942 {
<> 160:d5399cc887bb 943 uint8_t *guard_object = (uint8_t *)guard_object_p;
<> 160:d5399cc887bb 944 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
<> 160:d5399cc887bb 945 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
<> 160:d5399cc887bb 946 singleton_unlock();
<> 160:d5399cc887bb 947 }
<> 160:d5399cc887bb 948
<> 160:d5399cc887bb 949 #endif
<> 160:d5399cc887bb 950
<> 160:d5399cc887bb 951 void *operator new(std::size_t count)
<> 160:d5399cc887bb 952 {
<> 160:d5399cc887bb 953 void *buffer = malloc(count);
<> 160:d5399cc887bb 954 if (NULL == buffer) {
<> 160:d5399cc887bb 955 error("Operator new out of memory\r\n");
<> 160:d5399cc887bb 956 }
<> 160:d5399cc887bb 957 return buffer;
<> 160:d5399cc887bb 958 }
<> 160:d5399cc887bb 959
<> 160:d5399cc887bb 960 void *operator new[](std::size_t count)
<> 160:d5399cc887bb 961 {
<> 160:d5399cc887bb 962 void *buffer = malloc(count);
<> 160:d5399cc887bb 963 if (NULL == buffer) {
<> 160:d5399cc887bb 964 error("Operator new[] out of memory\r\n");
<> 160:d5399cc887bb 965 }
<> 160:d5399cc887bb 966 return buffer;
<> 160:d5399cc887bb 967 }
<> 160:d5399cc887bb 968
<> 160:d5399cc887bb 969 void operator delete(void *ptr)
<> 160:d5399cc887bb 970 {
<> 160:d5399cc887bb 971 if (ptr != NULL) {
<> 160:d5399cc887bb 972 free(ptr);
<> 160:d5399cc887bb 973 }
<> 160:d5399cc887bb 974 }
<> 160:d5399cc887bb 975 void operator delete[](void *ptr)
<> 160:d5399cc887bb 976 {
<> 160:d5399cc887bb 977 if (ptr != NULL) {
<> 160:d5399cc887bb 978 free(ptr);
<> 160:d5399cc887bb 979 }
<> 160:d5399cc887bb 980 }
AnnaBridge 167:e84263d55307 981
AnnaBridge 167:e84263d55307 982 #if defined(MBED_CONF_RTOS_PRESENT) && defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
AnnaBridge 167:e84263d55307 983
AnnaBridge 167:e84263d55307 984 static const char* error_msg(int32_t status)
AnnaBridge 167:e84263d55307 985 {
AnnaBridge 167:e84263d55307 986 switch (status) {
AnnaBridge 167:e84263d55307 987 case osError:
AnnaBridge 167:e84263d55307 988 return "Unspecified RTOS error";
AnnaBridge 167:e84263d55307 989 case osErrorTimeout:
AnnaBridge 167:e84263d55307 990 return "Operation not completed within the timeout period";
AnnaBridge 167:e84263d55307 991 case osErrorResource:
AnnaBridge 167:e84263d55307 992 return "Resource not available";
AnnaBridge 167:e84263d55307 993 case osErrorParameter:
AnnaBridge 167:e84263d55307 994 return "Parameter error";
AnnaBridge 167:e84263d55307 995 case osErrorNoMemory:
AnnaBridge 167:e84263d55307 996 return "System is out of memory";
AnnaBridge 167:e84263d55307 997 case osErrorISR:
AnnaBridge 167:e84263d55307 998 return "Not allowed in ISR context";
AnnaBridge 167:e84263d55307 999 default:
AnnaBridge 167:e84263d55307 1000 return "Unknown";
AnnaBridge 167:e84263d55307 1001 }
AnnaBridge 167:e84263d55307 1002 }
AnnaBridge 167:e84263d55307 1003
AnnaBridge 167:e84263d55307 1004 extern "C" void EvrRtxKernelError (int32_t status)
AnnaBridge 167:e84263d55307 1005 {
AnnaBridge 167:e84263d55307 1006 error("Kernel error %i: %s\r\n", status, error_msg(status));
AnnaBridge 167:e84263d55307 1007 }
AnnaBridge 167:e84263d55307 1008
AnnaBridge 167:e84263d55307 1009 extern "C" void EvrRtxThreadError (osThreadId_t thread_id, int32_t status)
AnnaBridge 167:e84263d55307 1010 {
AnnaBridge 167:e84263d55307 1011 error("Thread %p error %i: %s\r\n", thread_id, status, error_msg(status));
AnnaBridge 167:e84263d55307 1012 }
AnnaBridge 167:e84263d55307 1013
AnnaBridge 167:e84263d55307 1014 extern "C" void EvrRtxTimerError (osTimerId_t timer_id, int32_t status)
AnnaBridge 167:e84263d55307 1015 {
AnnaBridge 167:e84263d55307 1016 error("Timer %p error %i: %s\r\n", timer_id, status, error_msg(status));
AnnaBridge 167:e84263d55307 1017 }
AnnaBridge 167:e84263d55307 1018
AnnaBridge 167:e84263d55307 1019 extern "C" void EvrRtxEventFlagsError (osEventFlagsId_t ef_id, int32_t status)
AnnaBridge 167:e84263d55307 1020 {
AnnaBridge 167:e84263d55307 1021 error("Event %p error %i: %s\r\n", ef_id, status, error_msg(status));
AnnaBridge 167:e84263d55307 1022 }
AnnaBridge 167:e84263d55307 1023
AnnaBridge 167:e84263d55307 1024 extern "C" void EvrRtxMutexError (osMutexId_t mutex_id, int32_t status)
AnnaBridge 167:e84263d55307 1025 {
AnnaBridge 167:e84263d55307 1026 error("Mutex %p error %i: %s\r\n", mutex_id, status, error_msg(status));
AnnaBridge 167:e84263d55307 1027 }
AnnaBridge 167:e84263d55307 1028
AnnaBridge 167:e84263d55307 1029 extern "C" void EvrRtxSemaphoreError (osSemaphoreId_t semaphore_id, int32_t status)
AnnaBridge 167:e84263d55307 1030 {
AnnaBridge 167:e84263d55307 1031 // Ignore semaphore overflow, the count will saturate with a returned error
AnnaBridge 167:e84263d55307 1032 if (status == osRtxErrorSemaphoreCountLimit) {
AnnaBridge 167:e84263d55307 1033 return;
AnnaBridge 167:e84263d55307 1034 }
AnnaBridge 167:e84263d55307 1035
AnnaBridge 167:e84263d55307 1036 error("Semaphore %p error %i\r\n", semaphore_id, status);
AnnaBridge 167:e84263d55307 1037 }
AnnaBridge 167:e84263d55307 1038
AnnaBridge 167:e84263d55307 1039 extern "C" void EvrRtxMemoryPoolError (osMemoryPoolId_t mp_id, int32_t status)
AnnaBridge 167:e84263d55307 1040 {
AnnaBridge 167:e84263d55307 1041 error("Memory Pool %p error %i\r\n", mp_id, status);
AnnaBridge 167:e84263d55307 1042 }
AnnaBridge 167:e84263d55307 1043
AnnaBridge 167:e84263d55307 1044 extern "C" void EvrRtxMessageQueueError (osMessageQueueId_t mq_id, int32_t status)
AnnaBridge 167:e84263d55307 1045 {
AnnaBridge 167:e84263d55307 1046 error("Message Queue %p error %i\r\n", mq_id, status);
AnnaBridge 167:e84263d55307 1047 }
AnnaBridge 167:e84263d55307 1048
AnnaBridge 167:e84263d55307 1049 #endif