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) || defined(TWO_RAM_REGIONS)) 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 // TARGET_STM32L4 targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L4/l4_retarget.c 01063 extern "C" void *__wrap__sbrk(int incr); 01064 extern "C" caddr_t _sbrk(int incr) { 01065 return (caddr_t) __wrap__sbrk(incr); 01066 } 01067 #else 01068 // Linker defined symbol used by _sbrk to indicate where heap should start. 01069 extern "C" uint32_t __end__; 01070 // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory. 01071 extern "C" WEAK caddr_t _sbrk(int incr) { 01072 static unsigned char* heap = (unsigned char*)&__end__; 01073 unsigned char* prev_heap = heap; 01074 unsigned char* new_heap = heap + incr; 01075 01076 #if defined(TARGET_CORTEX_A) 01077 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */ 01078 #else 01079 if (new_heap >= (unsigned char*)__get_MSP()) { 01080 #endif 01081 errno = ENOMEM; 01082 return (caddr_t)-1; 01083 } 01084 01085 // Additional heap checking if set 01086 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) { 01087 errno = ENOMEM; 01088 return (caddr_t)-1; 01089 } 01090 01091 heap = new_heap; 01092 return (caddr_t) prev_heap; 01093 } 01094 #endif 01095 #endif 01096 01097 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 01098 extern "C" void _exit(int return_code) { 01099 #else 01100 namespace std { 01101 extern "C" void exit(int return_code) { 01102 #endif 01103 01104 #if DEVICE_STDIO_MESSAGES 01105 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT 01106 fflush(stdout); 01107 fflush(stderr); 01108 #endif 01109 #endif 01110 01111 #if DEVICE_SEMIHOST 01112 if (mbed_interface_connected()) { 01113 semihost_exit(); 01114 } 01115 #endif 01116 if (return_code) { 01117 mbed_die(); 01118 } 01119 01120 while (1); 01121 } 01122 01123 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR) 01124 } //namespace std 01125 #endif 01126 01127 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC) 01128 01129 // This series of function disable the registration of global destructors 01130 // in a dynamic table which will be called when the application exit. 01131 // In mbed, program never exit properly, it dies. 01132 // More informations about this topic for ARMCC here: 01133 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html 01134 extern "C" { 01135 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) { 01136 return 1; 01137 } 01138 01139 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) { 01140 return 1; 01141 } 01142 01143 void __cxa_finalize(void *handle) { 01144 } 01145 01146 } // end of extern "C" 01147 01148 #endif 01149 01150 01151 #if defined(TOOLCHAIN_GCC) 01152 01153 /* 01154 * Depending on how newlib is configured, it is often not enough to define 01155 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the 01156 * behavior regarding the registration of handlers with atexit. 01157 * 01158 * To overcome this limitation, exit and atexit are overriden here. 01159 */ 01160 extern "C"{ 01161 01162 /** 01163 * @brief Retarget of exit for GCC. 01164 * @details Unlike the standard version, this function doesn't call any function 01165 * registered with atexit before calling _exit. 01166 */ 01167 void __wrap_exit(int return_code) { 01168 _exit(return_code); 01169 } 01170 01171 /** 01172 * @brief Retarget atexit from GCC. 01173 * @details This function will always fail and never register any handler to be 01174 * called at exit. 01175 */ 01176 int __wrap_atexit(void (*func)()) { 01177 return 1; 01178 } 01179 01180 } 01181 01182 #endif 01183 01184 01185 01186 namespace mbed { 01187 01188 void mbed_set_unbuffered_stream(std::FILE *_file) { 01189 #if defined (__ICCARM__) 01190 char buf[2]; 01191 std::setvbuf(_file,buf,_IONBF,NULL); 01192 #else 01193 setbuf(_file, NULL); 01194 #endif 01195 } 01196 01197 int mbed_getc(std::FILE *_file){ 01198 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) 01199 /*This is only valid for unbuffered streams*/ 01200 int res = std::fgetc(_file); 01201 if (res>=0){ 01202 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 01203 _file->_Rend = _file->_Wend; 01204 _file->_Next = _file->_Wend; 01205 } 01206 return res; 01207 #else 01208 return std::fgetc(_file); 01209 #endif 01210 } 01211 01212 char* mbed_gets(char*s, int size, std::FILE *_file){ 01213 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) 01214 /*This is only valid for unbuffered streams*/ 01215 char *str = fgets(s,size,_file); 01216 if (str!=NULL){ 01217 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 01218 _file->_Rend = _file->_Wend; 01219 _file->_Next = _file->_Wend; 01220 } 01221 return str; 01222 #else 01223 return std::fgets(s,size,_file); 01224 #endif 01225 } 01226 01227 } // namespace mbed 01228 01229 #if defined (__ICCARM__) 01230 // Stub out locks when an rtos is not present 01231 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {} 01232 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {} 01233 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {} 01234 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {} 01235 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {} 01236 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {} 01237 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {} 01238 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {} 01239 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000) 01240 #pragma section="__iar_tls$$DATA" 01241 extern "C" WEAK void *__aeabi_read_tp (void) { 01242 // Thread Local storage is not supported, using main thread memory for errno 01243 return __section_begin("__iar_tls$$DATA"); 01244 } 01245 #endif 01246 #elif defined(__CC_ARM) 01247 // Do nothing 01248 #elif defined (__GNUC__) 01249 struct _reent; 01250 // Stub out locks when an rtos is not present 01251 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {} 01252 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {} 01253 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {} 01254 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {} 01255 01256 extern "C" void __malloc_lock( struct _reent *_r ) 01257 { 01258 __rtos_malloc_lock(_r); 01259 } 01260 01261 extern "C" void __malloc_unlock( struct _reent *_r ) 01262 { 01263 __rtos_malloc_unlock(_r); 01264 } 01265 01266 extern "C" void __env_lock( struct _reent *_r ) 01267 { 01268 __rtos_env_lock(_r); 01269 } 01270 01271 extern "C" void __env_unlock( struct _reent *_r ) 01272 { 01273 __rtos_env_unlock(_r); 01274 } 01275 01276 #endif 01277 01278 #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) 01279 01280 #define CXA_GUARD_INIT_DONE (1 << 0) 01281 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1) 01282 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS) 01283 01284 extern "C" int __cxa_guard_acquire(int *guard_object_p) 01285 { 01286 uint8_t *guard_object = (uint8_t *)guard_object_p; 01287 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 01288 return 0; 01289 } 01290 singleton_lock(); 01291 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 01292 singleton_unlock(); 01293 return 0; 01294 } 01295 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK)); 01296 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS; 01297 return 1; 01298 } 01299 01300 extern "C" void __cxa_guard_release(int *guard_object_p) 01301 { 01302 uint8_t *guard_object = (uint8_t *)guard_object_p; 01303 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01304 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE; 01305 singleton_unlock(); 01306 } 01307 01308 extern "C" void __cxa_guard_abort(int *guard_object_p) 01309 { 01310 uint8_t *guard_object = (uint8_t *)guard_object_p; 01311 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01312 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS; 01313 singleton_unlock(); 01314 } 01315 01316 #endif 01317 01318 #if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__)) 01319 01320 // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp 01321 // provide the implementation for these. Note: this needs to use the wrappers 01322 // instead of malloc()/free() as the caller address would point to wrappers, 01323 // not the caller of "new" or "delete". 01324 extern "C" void* malloc_wrapper(size_t size, const void* caller); 01325 extern "C" void free_wrapper(void *ptr, const void* caller); 01326 01327 void *operator new(std::size_t count) 01328 { 01329 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR()); 01330 if (NULL == buffer) { 01331 error("Operator new out of memory\r\n"); 01332 } 01333 return buffer; 01334 } 01335 01336 void *operator new[](std::size_t count) 01337 { 01338 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR()); 01339 if (NULL == buffer) { 01340 error("Operator new[] out of memory\r\n"); 01341 } 01342 return buffer; 01343 } 01344 01345 void *operator new(std::size_t count, const std::nothrow_t& tag) 01346 { 01347 return malloc_wrapper(count, MBED_CALLER_ADDR()); 01348 } 01349 01350 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01351 { 01352 return malloc_wrapper(count, MBED_CALLER_ADDR()); 01353 } 01354 01355 void operator delete(void *ptr) 01356 { 01357 free_wrapper(ptr, MBED_CALLER_ADDR()); 01358 } 01359 void operator delete[](void *ptr) 01360 { 01361 free_wrapper(ptr, MBED_CALLER_ADDR()); 01362 } 01363 01364 #elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__) 01365 01366 #include <reent.h> 01367 01368 extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller); 01369 extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller); 01370 01371 void *operator new(std::size_t count) 01372 { 01373 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01374 if (NULL == buffer) { 01375 error("Operator new out of memory\r\n"); 01376 } 01377 return buffer; 01378 } 01379 01380 void *operator new[](std::size_t count) 01381 { 01382 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01383 if (NULL == buffer) { 01384 error("Operator new[] out of memory\r\n"); 01385 } 01386 return buffer; 01387 } 01388 01389 void *operator new(std::size_t count, const std::nothrow_t& tag) 01390 { 01391 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01392 } 01393 01394 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01395 { 01396 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01397 } 01398 01399 void operator delete(void *ptr) 01400 { 01401 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR()); 01402 } 01403 01404 void operator delete[](void *ptr) 01405 { 01406 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR()); 01407 } 01408 01409 #else 01410 01411 void *operator new(std::size_t count) 01412 { 01413 void *buffer = malloc(count); 01414 if (NULL == buffer) { 01415 error("Operator new out of memory\r\n"); 01416 } 01417 return buffer; 01418 } 01419 01420 void *operator new[](std::size_t count) 01421 { 01422 void *buffer = malloc(count); 01423 if (NULL == buffer) { 01424 error("Operator new[] out of memory\r\n"); 01425 } 01426 return buffer; 01427 } 01428 01429 void *operator new(std::size_t count, const std::nothrow_t& tag) 01430 { 01431 return malloc(count); 01432 } 01433 01434 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01435 { 01436 return malloc(count); 01437 } 01438 01439 void operator delete(void *ptr) 01440 { 01441 free(ptr); 01442 } 01443 void operator delete[](void *ptr) 01444 { 01445 free(ptr); 01446 } 01447 01448 #endif 01449 01450 /* @brief standard c library clock() function. 01451 * 01452 * This function returns the number of clock ticks elapsed since the start of the program. 01453 * 01454 * @note Synchronization level: Thread safe 01455 * 01456 * @return 01457 * the number of clock ticks elapsed since the start of the program. 01458 * 01459 * */ 01460 extern "C" clock_t clock() 01461 { 01462 _mutex->lock(); 01463 clock_t t = ticker_read(get_us_ticker_data()); 01464 t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time 01465 _mutex->unlock(); 01466 return t; 01467 } 01468 01469 // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info 01470 MBED_WEAK const ticker_info_t* us_ticker_get_info() 01471 { 01472 static const ticker_info_t info = { 01473 1000000, 01474 32 01475 }; 01476 return &info; 01477 } 01478 01479 // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info 01480 MBED_WEAK const ticker_info_t* lp_ticker_get_info() 01481 { 01482 static const ticker_info_t info = { 01483 1000000, 01484 32 01485 }; 01486 return &info; 01487 }
Generated on Tue Jul 12 2022 14:24:27 by
