Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mbed_retarget.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <time.h> 00017 #include "platform/platform.h" 00018 #include "platform/FilePath.h" 00019 #include "hal/serial_api.h" 00020 #include "hal/us_ticker_api.h" 00021 #include "platform/mbed_toolchain.h" 00022 #include "platform/mbed_semihost_api.h" 00023 #include "platform/mbed_interface.h" 00024 #include "platform/SingletonPtr.h" 00025 #include "platform/PlatformMutex.h" 00026 #include "platform/mbed_error.h" 00027 #include "platform/mbed_stats.h" 00028 #include "platform/mbed_critical.h" 00029 #include "platform/mbed_poll.h" 00030 #include "platform/PlatformMutex.h" 00031 #include "drivers/UARTSerial.h" 00032 #include "us_ticker_api.h" 00033 #include "lp_ticker_api.h" 00034 #include <stdlib.h> 00035 #include <string.h> 00036 #include <limits.h> 00037 #ifndef SSIZE_MAX 00038 #define SSIZE_MAX INT_MAX 00039 #endif 00040 #include <stdio.h> 00041 #include <errno.h> 00042 #include "platform/mbed_retarget.h" 00043 00044 static SingletonPtr<PlatformMutex> _mutex; 00045 00046 #if defined(__ARMCC_VERSION) 00047 # if __ARMCC_VERSION >= 6010050 00048 # include <arm_compat.h> 00049 # endif 00050 # include <rt_sys.h> 00051 # include <rt_misc.h> 00052 # include <stdint.h> 00053 # define PREFIX(x) _sys##x 00054 # define OPEN_MAX _SYS_OPEN 00055 # ifdef __MICROLIB 00056 # pragma import(__use_full_stdio) 00057 # endif 00058 00059 #elif defined(__ICCARM__) 00060 # include <yfuns.h> 00061 # define PREFIX(x) _##x 00062 # define OPEN_MAX 16 00063 00064 # define STDIN_FILENO 0 00065 # define STDOUT_FILENO 1 00066 # define STDERR_FILENO 2 00067 00068 #else 00069 # include <sys/syslimits.h> 00070 # define PREFIX(x) x 00071 #endif 00072 00073 #define FILE_HANDLE_RESERVED ((FileHandle*)0xFFFFFFFF) 00074 00075 using namespace mbed; 00076 00077 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00078 // Before version 5.03, we were using a patched version of microlib with proper names 00079 extern const char __stdin_name[] = ":tt"; 00080 extern const char __stdout_name[] = ":tt"; 00081 extern const char __stderr_name[] = ":tt"; 00082 00083 #else 00084 extern const char __stdin_name[] = "/stdin"; 00085 extern const char __stdout_name[] = "/stdout"; 00086 extern const char __stderr_name[] = "/stderr"; 00087 #endif 00088 00089 unsigned char *mbed_heap_start = 0; 00090 uint32_t mbed_heap_size = 0; 00091 00092 /* newlib has the filehandle field in the FILE struct as a short, so 00093 * we can't just return a Filehandle* from _open and instead have to 00094 * put it in a filehandles array and return the index into that array 00095 */ 00096 static FileHandle *filehandles[OPEN_MAX] = { FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED }; 00097 static char stdio_in_prev[OPEN_MAX]; 00098 static char stdio_out_prev[OPEN_MAX]; 00099 static SingletonPtr<PlatformMutex> filehandle_mutex; 00100 00101 namespace mbed { 00102 void mbed_set_unbuffered_stream(std::FILE *_file); 00103 00104 void remove_filehandle(FileHandle *file) { 00105 filehandle_mutex->lock(); 00106 /* Remove all open filehandles for this */ 00107 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00108 if (filehandles[fh_i] == file) { 00109 filehandles[fh_i] = NULL; 00110 } 00111 } 00112 filehandle_mutex->unlock(); 00113 } 00114 } 00115 00116 #if DEVICE_SERIAL 00117 extern int stdio_uart_inited; 00118 extern serial_t stdio_uart; 00119 #endif 00120 00121 /* Private FileHandle to implement backwards-compatible functionality of 00122 * direct HAL serial access for default stdin/stdout/stderr. 00123 * This is not a particularly well-behaved FileHandle for a stream, which 00124 * is why it's not public. People should be using UARTSerial. 00125 */ 00126 class DirectSerial : public FileHandle { 00127 public: 00128 DirectSerial(PinName tx, PinName rx, int baud); 00129 virtual ssize_t write(const void *buffer, size_t size); 00130 virtual ssize_t read(void *buffer, size_t size); 00131 virtual off_t seek(off_t offset, int whence = SEEK_SET) { 00132 return -ESPIPE; 00133 } 00134 virtual off_t size() { 00135 return -EINVAL; 00136 } 00137 virtual int isatty() { 00138 return true; 00139 } 00140 virtual int close() { 00141 return 0; 00142 } 00143 virtual short poll(short events) const; 00144 }; 00145 00146 DirectSerial::DirectSerial(PinName tx, PinName rx, int baud) { 00147 if (stdio_uart_inited) return; 00148 serial_init(&stdio_uart, tx, rx); 00149 serial_baud(&stdio_uart, baud); 00150 } 00151 00152 ssize_t DirectSerial::write(const void *buffer, size_t size) { 00153 const unsigned char *buf = static_cast<const unsigned char *>(buffer); 00154 for (size_t i = 0; i < size; i++) { 00155 serial_putc(&stdio_uart, buf[i]); 00156 } 00157 return size; 00158 } 00159 00160 ssize_t DirectSerial::read(void *buffer, size_t size) { 00161 unsigned char *buf = static_cast<unsigned char *>(buffer); 00162 if (size == 0) { 00163 return 0; 00164 } 00165 buf[0] = serial_getc(&stdio_uart); 00166 return 1; 00167 } 00168 00169 short DirectSerial::poll(short events) const { 00170 short revents = 0; 00171 if ((events & POLLIN) && serial_readable(&stdio_uart)) { 00172 revents |= POLLIN; 00173 } 00174 if ((events & POLLOUT) && serial_writable(&stdio_uart)) { 00175 revents |= POLLOUT; 00176 } 00177 return revents; 00178 } 00179 00180 class Sink : public FileHandle { 00181 public: 00182 virtual ssize_t write(const void *buffer, size_t size); 00183 virtual ssize_t read(void *buffer, size_t size); 00184 virtual off_t seek(off_t offset, int whence = SEEK_SET) { return ESPIPE; } 00185 virtual off_t size() { return -EINVAL; } 00186 virtual int isatty() { return true; } 00187 virtual int close() { return 0; } 00188 }; 00189 00190 ssize_t Sink::write(const void *buffer, size_t size) { 00191 // Just swallow the data - this is historical non-DEVICE_SERIAL behaviour 00192 return size; 00193 } 00194 00195 ssize_t Sink::read(void *buffer, size_t size) { 00196 // Produce 1 zero byte - historical behaviour returned 1 without touching 00197 // the buffer 00198 unsigned char *buf = static_cast<unsigned char *>(buffer); 00199 buf[0] = 0; 00200 return 1; 00201 } 00202 00203 00204 MBED_WEAK FileHandle* mbed::mbed_target_override_console(int fd) 00205 { 00206 return NULL; 00207 } 00208 00209 MBED_WEAK FileHandle* mbed::mbed_override_console(int fd) 00210 { 00211 return NULL; 00212 } 00213 00214 static FileHandle* default_console() 00215 { 00216 #if DEVICE_SERIAL 00217 # if MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL 00218 static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE); 00219 # else 00220 static DirectSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE); 00221 # endif 00222 #else // DEVICE_SERIAL 00223 static Sink console; 00224 #endif 00225 return &console; 00226 } 00227 00228 /* Locate the default console for stdout, stdin, stderr */ 00229 static FileHandle* get_console(int fd) { 00230 FileHandle *fh = mbed_override_console(fd); 00231 if (fh) { 00232 return fh; 00233 } 00234 fh = mbed_target_override_console(fd); 00235 if (fh) { 00236 return fh; 00237 } 00238 return default_console(); 00239 } 00240 00241 /* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */ 00242 static FileHandle* get_fhc(int fd) { 00243 if (fd >= OPEN_MAX) { 00244 return NULL; 00245 } 00246 FileHandle *fh = filehandles[fd]; 00247 if (fh == FILE_HANDLE_RESERVED && fd < 3) { 00248 filehandles[fd] = fh = get_console(fd); 00249 } 00250 return fh; 00251 } 00252 00253 /** 00254 * Sets errno when file opening fails. 00255 * Wipes out the filehandle too. 00256 * 00257 * @param error is a negative error code returned from an mbed function and 00258 * will be negated to store a positive error code in errno 00259 */ 00260 static int handle_open_errors(int error, unsigned filehandle_idx) { 00261 errno = -error; 00262 // Free file handle 00263 filehandles[filehandle_idx] = NULL; 00264 return -1; 00265 } 00266 00267 static inline int openflags_to_posix(int openflags) { 00268 int posix = openflags; 00269 #ifdef __ARMCC_VERSION 00270 if (openflags & OPEN_PLUS) { 00271 posix = O_RDWR; 00272 } else if(openflags & OPEN_W) { 00273 posix = O_WRONLY; 00274 } else if(openflags & OPEN_A) { 00275 posix = O_WRONLY|O_APPEND; 00276 } else { 00277 posix = O_RDONLY; 00278 } 00279 /* a, w, a+, w+ all create if file does not already exist */ 00280 if (openflags & (OPEN_A|OPEN_W)) { 00281 posix |= O_CREAT; 00282 } 00283 /* w and w+ truncate */ 00284 if (openflags & OPEN_W) { 00285 posix |= O_TRUNC; 00286 } 00287 #elif defined(__ICCARM__) 00288 switch (openflags & _LLIO_RDWRMASK) { 00289 case _LLIO_RDONLY: posix = O_RDONLY; break; 00290 case _LLIO_WRONLY: posix = O_WRONLY; break; 00291 case _LLIO_RDWR : posix = O_RDWR ; break; 00292 } 00293 if (openflags & _LLIO_CREAT ) posix |= O_CREAT; 00294 if (openflags & _LLIO_APPEND) posix |= O_APPEND; 00295 if (openflags & _LLIO_TRUNC ) posix |= O_TRUNC; 00296 #elif defined(TOOLCHAIN_GCC) 00297 posix &= ~O_BINARY; 00298 #endif 00299 return posix; 00300 } 00301 00302 static int reserve_filehandle() { 00303 // find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr 00304 filehandle_mutex->lock(); 00305 int fh_i; 00306 for (fh_i = 3; fh_i < OPEN_MAX; fh_i++) { 00307 /* Take a next free filehandle slot available. */ 00308 if (filehandles[fh_i] == NULL) break; 00309 } 00310 if (fh_i >= OPEN_MAX) { 00311 /* Too many file handles have been opened */ 00312 errno = EMFILE; 00313 filehandle_mutex->unlock(); 00314 return -1; 00315 } 00316 filehandles[fh_i] = FILE_HANDLE_RESERVED; 00317 filehandle_mutex->unlock(); 00318 00319 return fh_i; 00320 } 00321 00322 int mbed::bind_to_fd(FileHandle *fh) { 00323 int fh_i = reserve_filehandle(); 00324 if (fh_i < 0) { 00325 return fh_i; 00326 } 00327 00328 filehandles[fh_i] = fh; 00329 stdio_in_prev[fh_i] = 0; 00330 stdio_out_prev[fh_i] = 0; 00331 00332 return fh_i; 00333 } 00334 00335 static int unbind_from_fd(int fd, FileHandle *fh) { 00336 if (filehandles[fd] == fh) { 00337 filehandles[fd] = NULL; 00338 return 0; 00339 } else { 00340 errno = EBADF; 00341 return -1; 00342 } 00343 } 00344 00345 #ifndef __IAR_SYSTEMS_ICC__ 00346 /* IAR provides fdopen itself */ 00347 extern "C" std::FILE* fdopen(int fildes, const char *mode) 00348 { 00349 // This is to avoid scanf and the bloat it brings. 00350 char buf[1 + sizeof fildes]; /* @(integer) */ 00351 MBED_STATIC_ASSERT(sizeof buf == 5, "Integers should be 4 bytes."); 00352 buf[0] = '@'; 00353 memcpy(buf + 1, &fildes, sizeof fildes); 00354 00355 std::FILE *stream = std::fopen(buf, mode); 00356 /* newlib-nano doesn't appear to ever call _isatty itself, so 00357 * happily fully buffers an interactive stream. Deal with that here. 00358 */ 00359 if (stream && isatty(fildes)) { 00360 mbed_set_unbuffered_stream(stream); 00361 } 00362 return stream; 00363 } 00364 #endif 00365 00366 namespace mbed { 00367 std::FILE *fdopen(FileHandle *fh, const char *mode) 00368 { 00369 // First reserve the integer file descriptor 00370 int fd = bind_to_fd(fh); 00371 if (!fd) { 00372 return NULL; 00373 } 00374 // Then bind that to the C stream. If successful, C library 00375 // takes ownership and responsibility to close. 00376 std::FILE *stream = ::fdopen(fd, mode); 00377 if (!stream) { 00378 unbind_from_fd(fd, fh); 00379 } 00380 return stream; 00381 } 00382 } 00383 00384 /* @brief standard c library fopen() retargeting function. 00385 * 00386 * This function is invoked by the standard c library retargeting to handle fopen() 00387 * 00388 * @return 00389 * On success, a valid FILEHANDLE is returned. 00390 * On failure, -1 is returned and errno is set to an appropriate value e.g. 00391 * ENOENT file not found (default errno setting) 00392 * EMFILE the maximum number of open files was exceeded. 00393 * 00394 * */ 00395 extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags) { 00396 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00397 #if !defined(MBED_CONF_RTOS_PRESENT) 00398 // valid only for mbed 2 00399 // for ulib, this is invoked after RAM init, prior c++ 00400 // used as hook, as post stack/heap is not active there 00401 extern void mbed_copy_nvic(void); 00402 extern void mbed_sdk_init(void); 00403 00404 static int mbed_sdk_inited = 0; 00405 if (!mbed_sdk_inited) { 00406 mbed_copy_nvic(); 00407 mbed_sdk_init(); 00408 mbed_sdk_inited = 1; 00409 } 00410 #endif 00411 // Before version 5.03, we were using a patched version of microlib with proper names 00412 // This is the workaround that the microlib author suggested us 00413 static int n = 0; 00414 if (std::strcmp(name, ":tt") == 0 && n < 3) { 00415 return n++; 00416 } 00417 #else 00418 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00419 */ 00420 if (std::strcmp(name, __stdin_name) == 0) { 00421 get_fhc(STDIN_FILENO); 00422 return STDIN_FILENO; 00423 } else if (std::strcmp(name, __stdout_name) == 0) { 00424 get_fhc(STDOUT_FILENO); 00425 return STDOUT_FILENO; 00426 } else if (std::strcmp(name, __stderr_name) == 0) { 00427 get_fhc(STDERR_FILENO); 00428 return STDERR_FILENO; 00429 } 00430 #endif 00431 #ifndef __IAR_SYSTEMS_ICC__ 00432 /* FILENAME: "@(integer)" gives an already-allocated descriptor */ 00433 if (name[0] == '@') { 00434 int fd; 00435 memcpy(&fd, name + 1, sizeof fd); 00436 return fd; 00437 } 00438 #endif 00439 return open(name, openflags_to_posix(openflags)); 00440 } 00441 00442 extern "C" int open(const char *name, int oflag, ...) { 00443 int fh_i = reserve_filehandle(); 00444 if (fh_i < 0) { 00445 return fh_i; 00446 } 00447 00448 FileHandle *res = NULL; 00449 FilePath path(name); 00450 00451 if (!path.exists()) { 00452 /* The first part of the filename (between first 2 '/') is not a 00453 * registered mount point in the namespace. 00454 */ 00455 return handle_open_errors(-ENODEV, fh_i); 00456 } 00457 00458 if (path.isFile()) { 00459 res = path.file(); 00460 } else { 00461 FileSystemHandle *fs = path.fileSystem(); 00462 if (fs == NULL) { 00463 return handle_open_errors(-ENODEV, fh_i); 00464 } 00465 int err = fs->open(&res, path.fileName(), oflag); 00466 if (err) { 00467 return handle_open_errors(err, fh_i); 00468 } 00469 } 00470 00471 filehandles[fh_i] = res; 00472 stdio_in_prev[fh_i] = 0; 00473 stdio_out_prev[fh_i] = 0; 00474 00475 return fh_i; 00476 } 00477 00478 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00479 return close(fh); 00480 } 00481 00482 extern "C" int close(int fh) { 00483 FileHandle* fhc = get_fhc(fh); 00484 filehandles[fh] = NULL; 00485 if (fhc == NULL) { 00486 errno = EBADF; 00487 return -1; 00488 } 00489 00490 int err = fhc->close(); 00491 if (err < 0) { 00492 errno = -err; 00493 return -1; 00494 } else { 00495 return 0; 00496 } 00497 } 00498 00499 static bool convert_crlf(int fd) { 00500 #if MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES 00501 return isatty(fd); 00502 #elif MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 00503 return fd < 3 && isatty(fd); 00504 #else 00505 return false; 00506 #endif 00507 } 00508 00509 #if defined(__ICCARM__) 00510 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00511 #else 00512 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00513 #endif 00514 00515 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT) 00516 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { 00517 error("Error - writing to a file in an ISR or critical section\r\n"); 00518 } 00519 #endif 00520 00521 if (length > SSIZE_MAX) { 00522 errno = EINVAL; 00523 return -1; 00524 } 00525 00526 ssize_t slength = length; 00527 ssize_t written = 0; 00528 00529 if (convert_crlf(fh)) { 00530 // local prev is previous in buffer during seek 00531 // stdio_out_prev[fh] is last thing actually written 00532 char prev = stdio_out_prev[fh]; 00533 // Seek for '\n' without preceding '\r'; if found flush 00534 // preceding and insert '\r'. Continue until end of input. 00535 for (ssize_t cur = 0; cur < slength; cur++) { 00536 if (buffer[cur] == '\n' && prev != '\r') { 00537 ssize_t r; 00538 // flush stuff preceding the \n 00539 if (cur > written) { 00540 r = write(fh, buffer + written, cur - written); 00541 if (r < 0) { 00542 return -1; 00543 } 00544 written += r; 00545 if (written < cur) { 00546 // For some reason, didn't write all - give up now 00547 goto finish; 00548 } 00549 stdio_out_prev[fh] = prev; 00550 } 00551 // insert a \r now, leaving the \n still to be written 00552 r = write(fh, "\r", 1); 00553 if (r < 0) { 00554 return -1; 00555 } 00556 if (r < 1) { 00557 goto finish; 00558 } 00559 stdio_out_prev[fh] = '\r'; 00560 } 00561 prev = buffer[cur]; 00562 } 00563 } 00564 00565 // Flush remaining from conversion, or the whole thing if no conversion 00566 if (written < slength) { 00567 ssize_t r = write(fh, buffer + written, slength - written); 00568 if (r < 0) { 00569 return -1; 00570 } 00571 written += r; 00572 if (written > 0) { 00573 stdio_out_prev[fh] = buffer[written - 1]; 00574 } 00575 } 00576 00577 finish: 00578 #ifdef __ARMCC_VERSION 00579 if (written >= 0) { 00580 return slength - written; 00581 } else { 00582 return written; 00583 } 00584 #else 00585 return written; 00586 #endif 00587 } 00588 00589 extern "C" ssize_t write(int fh, const void *buf, size_t length) { 00590 00591 FileHandle* fhc = get_fhc(fh); 00592 if (fhc == NULL) { 00593 errno = EBADF; 00594 return -1; 00595 } 00596 00597 ssize_t ret = fhc->write(buf, length); 00598 if (ret < 0) { 00599 errno = -ret; 00600 return -1; 00601 } else { 00602 return ret; 00603 } 00604 } 00605 00606 #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 00607 extern "C" void PREFIX(_exit)(int return_code) { 00608 while(1) {} 00609 } 00610 00611 extern "C" void _ttywrch(int ch) { 00612 char c = ch; 00613 write(STDOUT_FILENO, &c, 1); 00614 } 00615 #endif 00616 00617 #if defined(__ICCARM__) 00618 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00619 #else 00620 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00621 #endif 00622 00623 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT) 00624 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { 00625 error("Error - reading from a file in an ISR or critical section\r\n"); 00626 } 00627 #endif 00628 00629 if (length > SSIZE_MAX) { 00630 errno = EINVAL; 00631 return -1; 00632 } 00633 00634 ssize_t bytes_read = 0; 00635 00636 if (convert_crlf(fh)) { 00637 while (true) { 00638 char c; 00639 ssize_t r = read(fh, &c, 1); 00640 if (r < 0) { 00641 return -1; 00642 } 00643 if (r == 0) { 00644 return bytes_read; 00645 } 00646 if ((c == '\r' && stdio_in_prev[fh] != '\n') || 00647 (c == '\n' && stdio_in_prev[fh] != '\r')) { 00648 stdio_in_prev[fh] = c; 00649 *buffer = '\n'; 00650 break; 00651 } else if ((c == '\r' && stdio_in_prev[fh] == '\n') || 00652 (c == '\n' && stdio_in_prev[fh] == '\r')) { 00653 stdio_in_prev[fh] = c; 00654 continue; 00655 } else { 00656 stdio_in_prev[fh] = c; 00657 *buffer = c; 00658 break; 00659 } 00660 } 00661 bytes_read = 1; 00662 } else { 00663 bytes_read = read(fh, buffer, length); 00664 } 00665 00666 #ifdef __ARMCC_VERSION 00667 if (bytes_read < 0) { 00668 return -1; 00669 } else if (bytes_read == 0) { 00670 return 0x80000000 | length; // weird EOF indication 00671 } else { 00672 return (ssize_t)length - bytes_read; 00673 } 00674 #else 00675 return bytes_read; 00676 #endif 00677 } 00678 00679 extern "C" ssize_t read(int fh, void *buf, size_t length) { 00680 00681 FileHandle* fhc = get_fhc(fh); 00682 if (fhc == NULL) { 00683 errno = EBADF; 00684 return -1; 00685 } 00686 00687 ssize_t ret = fhc->read(buf, length); 00688 if (ret < 0) { 00689 errno = -ret; 00690 return -1; 00691 } else { 00692 return ret; 00693 } 00694 } 00695 00696 00697 #ifdef __ARMCC_VERSION 00698 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00699 #else 00700 extern "C" int _isatty(FILEHANDLE fh) 00701 #endif 00702 { 00703 return isatty(fh); 00704 } 00705 00706 extern "C" int isatty(int fh) { 00707 FileHandle* fhc = get_fhc(fh); 00708 if (fhc == NULL) { 00709 errno = EBADF; 00710 return 0; 00711 } 00712 00713 int tty = fhc->isatty(); 00714 if (tty < 0) { 00715 errno = -tty; 00716 return 0; 00717 } else { 00718 return tty; 00719 } 00720 } 00721 00722 extern "C" 00723 #if defined(__ARMCC_VERSION) 00724 int _sys_seek(FILEHANDLE fh, long offset) 00725 #elif defined(__ICCARM__) 00726 long __lseek(int fh, long offset, int whence) 00727 #else 00728 int _lseek(FILEHANDLE fh, int offset, int whence) 00729 #endif 00730 { 00731 #if defined(__ARMCC_VERSION) 00732 int whence = SEEK_SET; 00733 #endif 00734 00735 off_t off = lseek(fh, offset, whence); 00736 // Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference 00737 if (off > INT_MAX) { 00738 errno = EOVERFLOW; 00739 return -1; 00740 } 00741 return off; 00742 } 00743 00744 extern "C" off_t lseek(int fh, off_t offset, int whence) { 00745 FileHandle* fhc = get_fhc(fh); 00746 if (fhc == NULL) { 00747 errno = EBADF; 00748 return -1; 00749 } 00750 00751 off_t off = fhc->seek(offset, whence); 00752 if (off < 0) { 00753 errno = -off; 00754 return -1; 00755 } 00756 return off; 00757 } 00758 00759 #ifdef __ARMCC_VERSION 00760 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00761 return fsync(fh); 00762 } 00763 #endif 00764 00765 extern "C" int fsync(int fh) { 00766 FileHandle* fhc = get_fhc(fh); 00767 if (fhc == NULL) { 00768 errno = EBADF; 00769 return -1; 00770 } 00771 00772 int err = fhc->sync(); 00773 if (err < 0) { 00774 errno = -err; 00775 return -1; 00776 } else { 00777 return 0; 00778 } 00779 } 00780 00781 #ifdef __ARMCC_VERSION 00782 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00783 FileHandle* fhc = get_fhc(fh); 00784 if (fhc == NULL) { 00785 errno = EBADF; 00786 return -1; 00787 } 00788 00789 off_t size = fhc->size(); 00790 if (size < 0) { 00791 errno = -size; 00792 return -1; 00793 } 00794 if (size > LONG_MAX) { 00795 errno = EOVERFLOW; 00796 return -1; 00797 } 00798 return size; 00799 } 00800 00801 extern "C" char Image$$RW_IRAM1$$ZI$$Limit[]; 00802 00803 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) 00804 { 00805 uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit; 00806 uint32_t sp_limit = __current_sp(); 00807 00808 zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned 00809 00810 struct __initial_stackheap r; 00811 r.heap_base = zi_limit; 00812 r.heap_limit = sp_limit; 00813 return r; 00814 } 00815 00816 extern "C" __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) { 00817 return _mbed_user_setup_stackheap(R0, R1, R2, R3); 00818 } 00819 00820 #endif 00821 00822 00823 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00824 extern "C" int _fstat(int fh, struct stat *st) { 00825 return fstat(fh, st); 00826 } 00827 #endif 00828 00829 extern "C" int fstat(int fh, struct stat *st) { 00830 FileHandle* fhc = get_fhc(fh); 00831 if (fhc == NULL) { 00832 errno = EBADF; 00833 return -1; 00834 } 00835 00836 st->st_mode = fhc->isatty() ? S_IFCHR : S_IFREG; 00837 st->st_size = fhc->size(); 00838 return 0; 00839 } 00840 00841 extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout) 00842 { 00843 if (nfds > OPEN_MAX) { 00844 errno = EINVAL; 00845 return -1; 00846 } 00847 00848 struct mbed::pollfh fhs[OPEN_MAX]; 00849 for (nfds_t n = 0; n < nfds; n++) { 00850 // Underlying FileHandle poll returns POLLNVAL if given NULL, so 00851 // we don't need to take special action. 00852 fhs[n].fh = get_fhc(fds[n].fd); 00853 fhs[n].events = fds[n].events; 00854 } 00855 int ret = poll(fhs, nfds, timeout); 00856 for (nfds_t n = 0; n < nfds; n++) { 00857 fds[n].revents = fhs[n].revents; 00858 } 00859 return ret; 00860 } 00861 00862 namespace std { 00863 extern "C" int remove(const char *path) { 00864 FilePath fp(path); 00865 FileSystemHandle *fs = fp.fileSystem(); 00866 if (fs == NULL) { 00867 errno = ENODEV; 00868 return -1; 00869 } 00870 00871 int err = fs->remove(fp.fileName()); 00872 if (err < 0) { 00873 errno = -err; 00874 return -1; 00875 } else { 00876 return 0; 00877 } 00878 } 00879 00880 extern "C" int rename(const char *oldname, const char *newname) { 00881 FilePath fpOld(oldname); 00882 FilePath fpNew(newname); 00883 FileSystemHandle *fsOld = fpOld.fileSystem(); 00884 FileSystemHandle *fsNew = fpNew.fileSystem(); 00885 00886 if (fsOld == NULL) { 00887 errno = ENODEV; 00888 return -1; 00889 } 00890 00891 /* rename only if both files are on the same FS */ 00892 if (fsOld != fsNew) { 00893 errno = EXDEV; 00894 return -1; 00895 } 00896 00897 int err = fsOld->rename(fpOld.fileName(), fpNew.fileName()); 00898 if (err < 0) { 00899 errno = -err; 00900 return -1; 00901 } else { 00902 return 0; 00903 } 00904 } 00905 00906 extern "C" char *tmpnam(char *s) { 00907 errno = EBADF; 00908 return NULL; 00909 } 00910 00911 extern "C" FILE *tmpfile() { 00912 errno = EBADF; 00913 return NULL; 00914 } 00915 } // namespace std 00916 00917 #ifdef __ARMCC_VERSION 00918 extern "C" char *_sys_command_string(char *cmd, int len) { 00919 return NULL; 00920 } 00921 #endif 00922 00923 extern "C" DIR *opendir(const char *path) { 00924 FilePath fp(path); 00925 FileSystemHandle* fs = fp.fileSystem(); 00926 if (fs == NULL) { 00927 errno = ENODEV; 00928 return NULL; 00929 } 00930 00931 DirHandle *dir; 00932 int err = fs->open(&dir, fp.fileName()); 00933 if (err < 0) { 00934 errno = -err; 00935 return NULL; 00936 } 00937 00938 return dir; 00939 } 00940 00941 extern "C" struct dirent *readdir(DIR *dir) { 00942 static struct dirent ent; 00943 int err = dir->read(&ent); 00944 if (err < 1) { 00945 if (err < 0) { 00946 errno = -err; 00947 } 00948 return NULL; 00949 } 00950 00951 return &ent; 00952 } 00953 00954 extern "C" int closedir(DIR *dir) { 00955 int err = dir->close(); 00956 if (err < 0) { 00957 errno = -err; 00958 return -1; 00959 } else { 00960 return 0; 00961 } 00962 } 00963 00964 extern "C" void rewinddir(DIR *dir) { 00965 dir->rewind(); 00966 } 00967 00968 extern "C" off_t telldir(DIR *dir) { 00969 return dir->tell(); 00970 } 00971 00972 extern "C" void seekdir(DIR *dir, off_t off) { 00973 dir->seek(off); 00974 } 00975 00976 extern "C" int mkdir(const char *path, mode_t mode) { 00977 FilePath fp(path); 00978 FileSystemHandle *fs = fp.fileSystem(); 00979 if (fs == NULL) { 00980 errno = ENODEV; 00981 return -1; 00982 } 00983 00984 int err = fs->mkdir(fp.fileName(), mode); 00985 if (err < 0) { 00986 errno = -err; 00987 return -1; 00988 } else { 00989 return 0; 00990 } 00991 } 00992 00993 extern "C" int stat(const char *path, struct stat *st) { 00994 FilePath fp(path); 00995 FileSystemHandle *fs = fp.fileSystem(); 00996 if (fs == NULL) { 00997 errno = ENODEV; 00998 return -1; 00999 } 01000 01001 int err = fs->stat(fp.fileName(), st); 01002 if (err < 0) { 01003 errno = -err; 01004 return -1; 01005 } else { 01006 return 0; 01007 } 01008 } 01009 01010 extern "C" int statvfs(const char *path, struct statvfs *buf) { 01011 FilePath fp(path); 01012 FileSystemHandle *fs = fp.fileSystem(); 01013 if (fs == NULL) { 01014 errno = ENODEV; 01015 return -1; 01016 } 01017 01018 int err = fs->statvfs(fp.fileName(), buf); 01019 if (err < 0) { 01020 errno = -err; 01021 return -1; 01022 } else { 01023 return 0; 01024 } 01025 } 01026 01027 #if defined(TOOLCHAIN_GCC) 01028 /* prevents the exception handling name demangling code getting pulled in */ 01029 #include "mbed_error.h" 01030 namespace __gnu_cxx { 01031 void __verbose_terminate_handler() { 01032 error("Exception"); 01033 } 01034 } 01035 extern "C" WEAK void __cxa_pure_virtual(void); 01036 extern "C" WEAK void __cxa_pure_virtual(void) { 01037 exit(1); 01038 } 01039 01040 #endif 01041 01042 // Provide implementation of _sbrk (low-level dynamic memory allocation 01043 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 01044 // SP. This make it compatible with RTX RTOS thread stacks. 01045 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 01046 01047 #if defined(TARGET_CORTEX_A) 01048 extern "C" uint32_t __HeapLimit; 01049 #endif 01050 01051 // Turn off the errno macro and use actual global variable instead. 01052 #undef errno 01053 extern "C" int errno; 01054 01055 // Dynamic memory allocation related syscall. 01056 #if defined(TARGET_NUVOTON) 01057 01058 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions). 01059 // __wrap__sbrk() is implemented in: 01060 // TARGET_NUMAKER_PFM_NUC472 targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c 01061 // TARGET_NUMAKER_PFM_M453 targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/m451_retarget.c 01062 extern "C" void *__wrap__sbrk(int incr); 01063 extern "C" caddr_t _sbrk(int incr) { 01064 return (caddr_t) __wrap__sbrk(incr); 01065 } 01066 #else 01067 // Linker defined symbol used by _sbrk to indicate where heap should start. 01068 extern "C" uint32_t __end__; 01069 // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory. 01070 extern "C" WEAK caddr_t _sbrk(int incr) { 01071 static unsigned char* heap = (unsigned char*)&__end__; 01072 unsigned char* prev_heap = heap; 01073 unsigned char* new_heap = heap + incr; 01074 01075 #if defined(TARGET_CORTEX_A) 01076 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */ 01077 #else 01078 if (new_heap >= (unsigned char*)__get_MSP()) { 01079 #endif 01080 errno = ENOMEM; 01081 return (caddr_t)-1; 01082 } 01083 01084 // Additional heap checking if set 01085 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) { 01086 errno = ENOMEM; 01087 return (caddr_t)-1; 01088 } 01089 01090 heap = new_heap; 01091 return (caddr_t) prev_heap; 01092 } 01093 #endif 01094 #endif 01095 01096 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 01097 extern "C" void _exit(int return_code) { 01098 #else 01099 namespace std { 01100 extern "C" void exit(int return_code) { 01101 #endif 01102 01103 #if DEVICE_STDIO_MESSAGES 01104 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT 01105 fflush(stdout); 01106 fflush(stderr); 01107 #endif 01108 #endif 01109 01110 #if DEVICE_SEMIHOST 01111 if (mbed_interface_connected()) { 01112 semihost_exit(); 01113 } 01114 #endif 01115 if (return_code) { 01116 mbed_die(); 01117 } 01118 01119 while (1); 01120 } 01121 01122 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR) 01123 } //namespace std 01124 #endif 01125 01126 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC) 01127 01128 // This series of function disable the registration of global destructors 01129 // in a dynamic table which will be called when the application exit. 01130 // In mbed, program never exit properly, it dies. 01131 // More informations about this topic for ARMCC here: 01132 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html 01133 extern "C" { 01134 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) { 01135 return 1; 01136 } 01137 01138 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) { 01139 return 1; 01140 } 01141 01142 void __cxa_finalize(void *handle) { 01143 } 01144 01145 } // end of extern "C" 01146 01147 #endif 01148 01149 01150 #if defined(TOOLCHAIN_GCC) 01151 01152 /* 01153 * Depending on how newlib is configured, it is often not enough to define 01154 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the 01155 * behavior regarding the registration of handlers with atexit. 01156 * 01157 * To overcome this limitation, exit and atexit are overriden here. 01158 */ 01159 extern "C"{ 01160 01161 /** 01162 * @brief Retarget of exit for GCC. 01163 * @details Unlike the standard version, this function doesn't call any function 01164 * registered with atexit before calling _exit. 01165 */ 01166 void __wrap_exit(int return_code) { 01167 _exit(return_code); 01168 } 01169 01170 /** 01171 * @brief Retarget atexit from GCC. 01172 * @details This function will always fail and never register any handler to be 01173 * called at exit. 01174 */ 01175 int __wrap_atexit(void (*func)()) { 01176 return 1; 01177 } 01178 01179 } 01180 01181 #endif 01182 01183 01184 01185 namespace mbed { 01186 01187 void mbed_set_unbuffered_stream(std::FILE *_file) { 01188 #if defined (__ICCARM__) 01189 char buf[2]; 01190 std::setvbuf(_file,buf,_IONBF,NULL); 01191 #else 01192 setbuf(_file, NULL); 01193 #endif 01194 } 01195 01196 int mbed_getc(std::FILE *_file){ 01197 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) 01198 /*This is only valid for unbuffered streams*/ 01199 int res = std::fgetc(_file); 01200 if (res>=0){ 01201 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 01202 _file->_Rend = _file->_Wend; 01203 _file->_Next = _file->_Wend; 01204 } 01205 return res; 01206 #else 01207 return std::fgetc(_file); 01208 #endif 01209 } 01210 01211 char* mbed_gets(char*s, int size, std::FILE *_file){ 01212 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) 01213 /*This is only valid for unbuffered streams*/ 01214 char *str = fgets(s,size,_file); 01215 if (str!=NULL){ 01216 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 01217 _file->_Rend = _file->_Wend; 01218 _file->_Next = _file->_Wend; 01219 } 01220 return str; 01221 #else 01222 return std::fgets(s,size,_file); 01223 #endif 01224 } 01225 01226 } // namespace mbed 01227 01228 #if defined (__ICCARM__) 01229 // Stub out locks when an rtos is not present 01230 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {} 01231 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {} 01232 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {} 01233 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {} 01234 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {} 01235 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {} 01236 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {} 01237 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {} 01238 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000) 01239 #pragma section="__iar_tls$$DATA" 01240 extern "C" WEAK void *__aeabi_read_tp (void) { 01241 // Thread Local storage is not supported, using main thread memory for errno 01242 return __section_begin("__iar_tls$$DATA"); 01243 } 01244 #endif 01245 #elif defined(__CC_ARM) 01246 // Do nothing 01247 #elif defined (__GNUC__) 01248 struct _reent; 01249 // Stub out locks when an rtos is not present 01250 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {} 01251 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {} 01252 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {} 01253 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {} 01254 01255 extern "C" void __malloc_lock( struct _reent *_r ) 01256 { 01257 __rtos_malloc_lock(_r); 01258 } 01259 01260 extern "C" void __malloc_unlock( struct _reent *_r ) 01261 { 01262 __rtos_malloc_unlock(_r); 01263 } 01264 01265 extern "C" void __env_lock( struct _reent *_r ) 01266 { 01267 __rtos_env_lock(_r); 01268 } 01269 01270 extern "C" void __env_unlock( struct _reent *_r ) 01271 { 01272 __rtos_env_unlock(_r); 01273 } 01274 01275 #endif 01276 01277 #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) 01278 01279 #define CXA_GUARD_INIT_DONE (1 << 0) 01280 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1) 01281 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS) 01282 01283 extern "C" int __cxa_guard_acquire(int *guard_object_p) 01284 { 01285 uint8_t *guard_object = (uint8_t *)guard_object_p; 01286 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 01287 return 0; 01288 } 01289 singleton_lock(); 01290 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 01291 singleton_unlock(); 01292 return 0; 01293 } 01294 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK)); 01295 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS; 01296 return 1; 01297 } 01298 01299 extern "C" void __cxa_guard_release(int *guard_object_p) 01300 { 01301 uint8_t *guard_object = (uint8_t *)guard_object_p; 01302 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01303 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE; 01304 singleton_unlock(); 01305 } 01306 01307 extern "C" void __cxa_guard_abort(int *guard_object_p) 01308 { 01309 uint8_t *guard_object = (uint8_t *)guard_object_p; 01310 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01311 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS; 01312 singleton_unlock(); 01313 } 01314 01315 #endif 01316 01317 #if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__)) 01318 01319 // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp 01320 // provide the implementation for these. Note: this needs to use the wrappers 01321 // instead of malloc()/free() as the caller address would point to wrappers, 01322 // not the caller of "new" or "delete". 01323 extern "C" void* malloc_wrapper(size_t size, const void* caller); 01324 extern "C" void free_wrapper(void *ptr, const void* caller); 01325 01326 void *operator new(std::size_t count) 01327 { 01328 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR()); 01329 if (NULL == buffer) { 01330 error("Operator new out of memory\r\n"); 01331 } 01332 return buffer; 01333 } 01334 01335 void *operator new[](std::size_t count) 01336 { 01337 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR()); 01338 if (NULL == buffer) { 01339 error("Operator new[] out of memory\r\n"); 01340 } 01341 return buffer; 01342 } 01343 01344 void *operator new(std::size_t count, const std::nothrow_t& tag) 01345 { 01346 return malloc_wrapper(count, MBED_CALLER_ADDR()); 01347 } 01348 01349 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01350 { 01351 return malloc_wrapper(count, MBED_CALLER_ADDR()); 01352 } 01353 01354 void operator delete(void *ptr) 01355 { 01356 free_wrapper(ptr, MBED_CALLER_ADDR()); 01357 } 01358 void operator delete[](void *ptr) 01359 { 01360 free_wrapper(ptr, MBED_CALLER_ADDR()); 01361 } 01362 01363 #elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__) 01364 01365 #include <reent.h> 01366 01367 extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller); 01368 extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller); 01369 01370 void *operator new(std::size_t count) 01371 { 01372 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01373 if (NULL == buffer) { 01374 error("Operator new out of memory\r\n"); 01375 } 01376 return buffer; 01377 } 01378 01379 void *operator new[](std::size_t count) 01380 { 01381 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01382 if (NULL == buffer) { 01383 error("Operator new[] out of memory\r\n"); 01384 } 01385 return buffer; 01386 } 01387 01388 void *operator new(std::size_t count, const std::nothrow_t& tag) 01389 { 01390 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01391 } 01392 01393 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01394 { 01395 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01396 } 01397 01398 void operator delete(void *ptr) 01399 { 01400 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR()); 01401 } 01402 01403 void operator delete[](void *ptr) 01404 { 01405 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR()); 01406 } 01407 01408 #else 01409 01410 void *operator new(std::size_t count) 01411 { 01412 void *buffer = malloc(count); 01413 if (NULL == buffer) { 01414 error("Operator new out of memory\r\n"); 01415 } 01416 return buffer; 01417 } 01418 01419 void *operator new[](std::size_t count) 01420 { 01421 void *buffer = malloc(count); 01422 if (NULL == buffer) { 01423 error("Operator new[] out of memory\r\n"); 01424 } 01425 return buffer; 01426 } 01427 01428 void *operator new(std::size_t count, const std::nothrow_t& tag) 01429 { 01430 return malloc(count); 01431 } 01432 01433 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01434 { 01435 return malloc(count); 01436 } 01437 01438 void operator delete(void *ptr) 01439 { 01440 free(ptr); 01441 } 01442 void operator delete[](void *ptr) 01443 { 01444 free(ptr); 01445 } 01446 01447 #endif 01448 01449 /* @brief standard c library clock() function. 01450 * 01451 * This function returns the number of clock ticks elapsed since the start of the program. 01452 * 01453 * @note Synchronization level: Thread safe 01454 * 01455 * @return 01456 * the number of clock ticks elapsed since the start of the program. 01457 * 01458 * */ 01459 extern "C" clock_t clock() 01460 { 01461 _mutex->lock(); 01462 clock_t t = ticker_read(get_us_ticker_data()); 01463 t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time 01464 _mutex->unlock(); 01465 return t; 01466 } 01467 01468 // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info 01469 MBED_WEAK const ticker_info_t* us_ticker_get_info() 01470 { 01471 static const ticker_info_t info = { 01472 1000000, 01473 32 01474 }; 01475 return &info; 01476 } 01477 01478 // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info 01479 MBED_WEAK const ticker_info_t* lp_ticker_get_info() 01480 { 01481 static const ticker_info_t info = { 01482 1000000, 01483 32 01484 }; 01485 return &info; 01486 }
Generated on Tue Jul 12 2022 13:24:57 by
1.7.2