mbed library sources. Supersedes mbed-src.

Dependents:   BREAK_SENSOR_LED

Fork of mbed-dev by mbed official

Committer:
Anythingconnected
Date:
Mon Dec 18 10:14:27 2017 +0000
Revision:
180:d79f997829d6
Parent:
179:b0033dcd6934
Getting byte by byte read to work

Who changed what in which revision?

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