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