Elijah Stanger-Jones / mbed-dev-f303
Committer:
elijahsj
Date:
Mon Nov 09 00:02:47 2020 -0500
Revision:
1:8a094db1347f
test

Who changed what in which revision?

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