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