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