From Ben Katz mbed-dev library. Removed unnecessary target files to reduce the overall size by a factor of 10 to make it easier to import into the online IDE.

Dependents:   motor_driver motor_driver_screaming_fix

Committer:
saloutos
Date:
Thu Nov 26 04:08:56 2020 +0000
Revision:
0:083111ae2a11
first commit of leaned mbed dev lib

Who changed what in which revision?

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