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 fildes = reserve_filehandle(); 00348 if (fildes < 0) { 00349 return fildes; 00350 } 00351 00352 filehandles[fildes] = fh; 00353 stdio_in_prev[fildes] = 0; 00354 stdio_out_prev[fildes] = 0; 00355 00356 return fildes; 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 fildes = reserve_filehandle(); 00468 if (fildes < 0) { 00469 return fildes; 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, fildes); 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, fildes); 00488 } 00489 int err = fs->open(&res, path.fileName(), oflag); 00490 if (err) { 00491 return handle_open_errors(err, fildes); 00492 } 00493 } 00494 00495 filehandles[fildes] = res; 00496 stdio_in_prev[fildes] = 0; 00497 stdio_out_prev[fildes] = 0; 00498 00499 return fildes; 00500 } 00501 00502 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00503 return close(fh); 00504 } 00505 00506 extern "C" int close(int fildes) { 00507 FileHandle* fhc = get_fhc(fildes); 00508 filehandles[fildes] = 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 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); 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 fildes, const void *buf, size_t length) { 00614 00615 FileHandle* fhc = get_fhc(fildes); 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 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); 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 fildes, void *buf, size_t length) { 00704 00705 FileHandle* fhc = get_fhc(fildes); 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 fildes) { 00731 FileHandle* fhc = get_fhc(fildes); 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 fildes, off_t offset, int whence) { 00769 FileHandle* fhc = get_fhc(fildes); 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 fildes) { 00790 FileHandle* fhc = get_fhc(fildes); 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 fildes, struct stat *st) { 00854 FileHandle* fhc = get_fhc(fildes); 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 fcntl(int fildes, int cmd, ...) { 00866 FileHandle *fhc = get_fhc(fildes); 00867 if (fhc == NULL) { 00868 errno = EBADF; 00869 return -1; 00870 } 00871 00872 switch (cmd) { 00873 case F_GETFL: { 00874 int flags = 0; 00875 if (fhc->is_blocking()) { 00876 flags |= O_NONBLOCK; 00877 } 00878 return flags; 00879 } 00880 case F_SETFL: { 00881 va_list ap; 00882 va_start(ap, cmd); 00883 int flags = va_arg(ap, int); 00884 va_end(ap); 00885 int ret = fhc->set_blocking(flags & O_NONBLOCK); 00886 if (ret < 0) { 00887 errno = -ret; 00888 return -1; 00889 } 00890 return 0; 00891 } 00892 00893 default: { 00894 errno = EINVAL; 00895 return -1; 00896 } 00897 } 00898 } 00899 00900 extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout) 00901 { 00902 if (nfds > OPEN_MAX) { 00903 errno = EINVAL; 00904 return -1; 00905 } 00906 00907 struct mbed::pollfh fhs[OPEN_MAX]; 00908 for (nfds_t n = 0; n < nfds; n++) { 00909 // Underlying FileHandle poll returns POLLNVAL if given NULL, so 00910 // we don't need to take special action. 00911 fhs[n].fh = get_fhc(fds[n].fd); 00912 fhs[n].events = fds[n].events; 00913 } 00914 int ret = poll(fhs, nfds, timeout); 00915 for (nfds_t n = 0; n < nfds; n++) { 00916 fds[n].revents = fhs[n].revents; 00917 } 00918 return ret; 00919 } 00920 00921 namespace std { 00922 extern "C" int remove(const char *path) { 00923 FilePath fp(path); 00924 FileSystemHandle *fs = fp.fileSystem(); 00925 if (fs == NULL) { 00926 errno = ENODEV; 00927 return -1; 00928 } 00929 00930 int err = fs->remove(fp.fileName()); 00931 if (err < 0) { 00932 errno = -err; 00933 return -1; 00934 } else { 00935 return 0; 00936 } 00937 } 00938 00939 extern "C" int rename(const char *oldname, const char *newname) { 00940 FilePath fpOld(oldname); 00941 FilePath fpNew(newname); 00942 FileSystemHandle *fsOld = fpOld.fileSystem(); 00943 FileSystemHandle *fsNew = fpNew.fileSystem(); 00944 00945 if (fsOld == NULL) { 00946 errno = ENODEV; 00947 return -1; 00948 } 00949 00950 /* rename only if both files are on the same FS */ 00951 if (fsOld != fsNew) { 00952 errno = EXDEV; 00953 return -1; 00954 } 00955 00956 int err = fsOld->rename(fpOld.fileName(), fpNew.fileName()); 00957 if (err < 0) { 00958 errno = -err; 00959 return -1; 00960 } else { 00961 return 0; 00962 } 00963 } 00964 00965 extern "C" char *tmpnam(char *s) { 00966 errno = EBADF; 00967 return NULL; 00968 } 00969 00970 extern "C" FILE *tmpfile() { 00971 errno = EBADF; 00972 return NULL; 00973 } 00974 } // namespace std 00975 00976 #ifdef __ARMCC_VERSION 00977 extern "C" char *_sys_command_string(char *cmd, int len) { 00978 return NULL; 00979 } 00980 #endif 00981 00982 extern "C" DIR *opendir(const char *path) { 00983 FilePath fp(path); 00984 FileSystemHandle* fs = fp.fileSystem(); 00985 if (fs == NULL) { 00986 errno = ENODEV; 00987 return NULL; 00988 } 00989 00990 DirHandle *dir; 00991 int err = fs->open(&dir, fp.fileName()); 00992 if (err < 0) { 00993 errno = -err; 00994 return NULL; 00995 } 00996 00997 return dir; 00998 } 00999 01000 extern "C" struct dirent *readdir(DIR *dir) { 01001 static struct dirent ent; 01002 int err = dir->read(&ent); 01003 if (err < 1) { 01004 if (err < 0) { 01005 errno = -err; 01006 } 01007 return NULL; 01008 } 01009 01010 return &ent; 01011 } 01012 01013 extern "C" int closedir(DIR *dir) { 01014 int err = dir->close(); 01015 if (err < 0) { 01016 errno = -err; 01017 return -1; 01018 } else { 01019 return 0; 01020 } 01021 } 01022 01023 extern "C" void rewinddir(DIR *dir) { 01024 dir->rewind(); 01025 } 01026 01027 extern "C" off_t telldir(DIR *dir) { 01028 return dir->tell(); 01029 } 01030 01031 extern "C" void seekdir(DIR *dir, off_t off) { 01032 dir->seek(off); 01033 } 01034 01035 extern "C" int mkdir(const char *path, mode_t mode) { 01036 FilePath fp(path); 01037 FileSystemHandle *fs = fp.fileSystem(); 01038 if (fs == NULL) { 01039 errno = ENODEV; 01040 return -1; 01041 } 01042 01043 int err = fs->mkdir(fp.fileName(), mode); 01044 if (err < 0) { 01045 errno = -err; 01046 return -1; 01047 } else { 01048 return 0; 01049 } 01050 } 01051 01052 extern "C" int stat(const char *path, struct stat *st) { 01053 FilePath fp(path); 01054 FileSystemHandle *fs = fp.fileSystem(); 01055 if (fs == NULL) { 01056 errno = ENODEV; 01057 return -1; 01058 } 01059 01060 int err = fs->stat(fp.fileName(), st); 01061 if (err < 0) { 01062 errno = -err; 01063 return -1; 01064 } else { 01065 return 0; 01066 } 01067 } 01068 01069 extern "C" int statvfs(const char *path, struct statvfs *buf) { 01070 FilePath fp(path); 01071 FileSystemHandle *fs = fp.fileSystem(); 01072 if (fs == NULL) { 01073 errno = ENODEV; 01074 return -1; 01075 } 01076 01077 int err = fs->statvfs(fp.fileName(), buf); 01078 if (err < 0) { 01079 errno = -err; 01080 return -1; 01081 } else { 01082 return 0; 01083 } 01084 } 01085 01086 #if defined(TOOLCHAIN_GCC) 01087 /* prevents the exception handling name demangling code getting pulled in */ 01088 #include "mbed_error.h" 01089 namespace __gnu_cxx { 01090 void __verbose_terminate_handler() { 01091 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_CLIB_EXCEPTION),"Exception", 0); 01092 } 01093 } 01094 extern "C" WEAK void __cxa_pure_virtual(void); 01095 extern "C" WEAK void __cxa_pure_virtual(void) { 01096 exit(1); 01097 } 01098 01099 #endif 01100 01101 // Provide implementation of _sbrk (low-level dynamic memory allocation 01102 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 01103 // SP. This make it compatible with RTX RTOS thread stacks. 01104 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 01105 01106 #if defined(TARGET_CORTEX_A) 01107 extern "C" uint32_t __HeapLimit; 01108 #endif 01109 01110 // Turn off the errno macro and use actual global variable instead. 01111 #undef errno 01112 extern "C" int errno; 01113 01114 // Dynamic memory allocation related syscall. 01115 #if (defined(TARGET_NUVOTON) || defined(TWO_RAM_REGIONS)) 01116 01117 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions). 01118 // __wrap__sbrk() is implemented in: 01119 // TARGET_NUMAKER_PFM_NUC472 targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c 01120 // TARGET_NUMAKER_PFM_M453 targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/m451_retarget.c 01121 // TARGET_STM32L4 targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L4/l4_retarget.c 01122 extern "C" void *__wrap__sbrk(int incr); 01123 extern "C" caddr_t _sbrk(int incr) { 01124 return (caddr_t) __wrap__sbrk(incr); 01125 } 01126 #else 01127 // Linker defined symbol used by _sbrk to indicate where heap should start. 01128 extern "C" uint32_t __end__; 01129 // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory. 01130 extern "C" WEAK caddr_t _sbrk(int incr) { 01131 static unsigned char* heap = (unsigned char*)&__end__; 01132 unsigned char* prev_heap = heap; 01133 unsigned char* new_heap = heap + incr; 01134 01135 #if defined(TARGET_CORTEX_A) 01136 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */ 01137 #else 01138 if (new_heap >= (unsigned char*)__get_MSP()) { 01139 #endif 01140 errno = ENOMEM; 01141 return (caddr_t)-1; 01142 } 01143 01144 // Additional heap checking if set 01145 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) { 01146 errno = ENOMEM; 01147 return (caddr_t)-1; 01148 } 01149 01150 heap = new_heap; 01151 return (caddr_t) prev_heap; 01152 } 01153 #endif 01154 #endif 01155 01156 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR) 01157 extern "C" void _exit(int return_code) { 01158 #else 01159 namespace std { 01160 extern "C" void exit(int return_code) { 01161 #endif 01162 01163 #if DEVICE_STDIO_MESSAGES 01164 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT 01165 fflush(stdout); 01166 fflush(stderr); 01167 #endif 01168 #endif 01169 01170 #if DEVICE_SEMIHOST 01171 if (mbed_interface_connected()) { 01172 semihost_exit(); 01173 } 01174 #endif 01175 if (return_code) { 01176 mbed_die(); 01177 } 01178 01179 while (1); 01180 } 01181 01182 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR) 01183 } //namespace std 01184 #endif 01185 01186 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC) 01187 01188 // This series of function disable the registration of global destructors 01189 // in a dynamic table which will be called when the application exit. 01190 // In mbed, program never exit properly, it dies. 01191 // More informations about this topic for ARMCC here: 01192 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html 01193 extern "C" { 01194 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) { 01195 return 1; 01196 } 01197 01198 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) { 01199 return 1; 01200 } 01201 01202 void __cxa_finalize(void *handle) { 01203 } 01204 01205 } // end of extern "C" 01206 01207 #endif 01208 01209 01210 #if defined(TOOLCHAIN_GCC) 01211 01212 /* 01213 * Depending on how newlib is configured, it is often not enough to define 01214 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the 01215 * behavior regarding the registration of handlers with atexit. 01216 * 01217 * To overcome this limitation, exit and atexit are overriden here. 01218 */ 01219 extern "C"{ 01220 01221 /** 01222 * @brief Retarget of exit for GCC. 01223 * @details Unlike the standard version, this function doesn't call any function 01224 * registered with atexit before calling _exit. 01225 */ 01226 void __wrap_exit(int return_code) { 01227 _exit(return_code); 01228 } 01229 01230 /** 01231 * @brief Retarget atexit from GCC. 01232 * @details This function will always fail and never register any handler to be 01233 * called at exit. 01234 */ 01235 int __wrap_atexit(void (*func)()) { 01236 return 1; 01237 } 01238 01239 } 01240 01241 #endif 01242 01243 01244 01245 namespace mbed { 01246 01247 void mbed_set_unbuffered_stream(std::FILE *_file) { 01248 #if defined (__ICCARM__) 01249 char buf[2]; 01250 std::setvbuf(_file,buf,_IONBF,NULL); 01251 #else 01252 setbuf(_file, NULL); 01253 #endif 01254 } 01255 01256 int mbed_getc(std::FILE *_file){ 01257 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) 01258 /*This is only valid for unbuffered streams*/ 01259 int res = std::fgetc(_file); 01260 if (res>=0){ 01261 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 01262 _file->_Rend = _file->_Wend; 01263 _file->_Next = _file->_Wend; 01264 } 01265 return res; 01266 #else 01267 return std::fgetc(_file); 01268 #endif 01269 } 01270 01271 char* mbed_gets(char*s, int size, std::FILE *_file){ 01272 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000) 01273 /*This is only valid for unbuffered streams*/ 01274 char *str = fgets(s,size,_file); 01275 if (str!=NULL){ 01276 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 01277 _file->_Rend = _file->_Wend; 01278 _file->_Next = _file->_Wend; 01279 } 01280 return str; 01281 #else 01282 return std::fgets(s,size,_file); 01283 #endif 01284 } 01285 01286 } // namespace mbed 01287 01288 #if defined (__ICCARM__) 01289 // Stub out locks when an rtos is not present 01290 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {} 01291 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {} 01292 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {} 01293 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {} 01294 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {} 01295 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {} 01296 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {} 01297 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {} 01298 #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000) 01299 #pragma section="__iar_tls$$DATA" 01300 extern "C" WEAK void *__aeabi_read_tp (void) { 01301 // Thread Local storage is not supported, using main thread memory for errno 01302 return __section_begin("__iar_tls$$DATA"); 01303 } 01304 #endif 01305 #elif defined(__CC_ARM) 01306 // Do nothing 01307 #elif defined (__GNUC__) 01308 struct _reent; 01309 // Stub out locks when an rtos is not present 01310 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {} 01311 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {} 01312 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {} 01313 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {} 01314 01315 extern "C" void __malloc_lock( struct _reent *_r ) 01316 { 01317 __rtos_malloc_lock(_r); 01318 } 01319 01320 extern "C" void __malloc_unlock( struct _reent *_r ) 01321 { 01322 __rtos_malloc_unlock(_r); 01323 } 01324 01325 extern "C" void __env_lock( struct _reent *_r ) 01326 { 01327 __rtos_env_lock(_r); 01328 } 01329 01330 extern "C" void __env_unlock( struct _reent *_r ) 01331 { 01332 __rtos_env_unlock(_r); 01333 } 01334 01335 #endif 01336 01337 #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) 01338 01339 #define CXA_GUARD_INIT_DONE (1 << 0) 01340 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1) 01341 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS) 01342 01343 extern "C" int __cxa_guard_acquire(int *guard_object_p) 01344 { 01345 uint8_t *guard_object = (uint8_t *)guard_object_p; 01346 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 01347 return 0; 01348 } 01349 singleton_lock(); 01350 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) { 01351 singleton_unlock(); 01352 return 0; 01353 } 01354 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK)); 01355 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS; 01356 return 1; 01357 } 01358 01359 extern "C" void __cxa_guard_release(int *guard_object_p) 01360 { 01361 uint8_t *guard_object = (uint8_t *)guard_object_p; 01362 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01363 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE; 01364 singleton_unlock(); 01365 } 01366 01367 extern "C" void __cxa_guard_abort(int *guard_object_p) 01368 { 01369 uint8_t *guard_object = (uint8_t *)guard_object_p; 01370 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK)); 01371 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS; 01372 singleton_unlock(); 01373 } 01374 01375 #endif 01376 01377 #if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) 01378 01379 // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp 01380 // provide the implementation for these. Note: this needs to use the wrappers 01381 // instead of malloc()/free() as the caller address would point to wrappers, 01382 // not the caller of "new" or "delete". 01383 extern "C" void* malloc_wrapper(size_t size, const void* caller); 01384 extern "C" void free_wrapper(void *ptr, const void* caller); 01385 01386 void *operator new(std::size_t count) 01387 { 01388 void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR()); 01389 if (NULL == buffer) { 01390 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count); 01391 } 01392 return buffer; 01393 } 01394 01395 void *operator new[](std::size_t count) 01396 { 01397 void *buffer = malloc_wrapper(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, const std::nothrow_t& tag) 01405 { 01406 return malloc_wrapper(count, MBED_CALLER_ADDR()); 01407 } 01408 01409 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01410 { 01411 return malloc_wrapper(count, MBED_CALLER_ADDR()); 01412 } 01413 01414 void operator delete(void *ptr) 01415 { 01416 free_wrapper(ptr, MBED_CALLER_ADDR()); 01417 } 01418 void operator delete[](void *ptr) 01419 { 01420 free_wrapper(ptr, MBED_CALLER_ADDR()); 01421 } 01422 01423 #elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__) 01424 01425 #include <reent.h> 01426 01427 extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller); 01428 extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller); 01429 01430 void *operator new(std::size_t count) 01431 { 01432 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01433 if (NULL == buffer) { 01434 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count); 01435 } 01436 return buffer; 01437 } 01438 01439 void *operator new[](std::size_t count) 01440 { 01441 void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01442 if (NULL == buffer) { 01443 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count); 01444 } 01445 return buffer; 01446 } 01447 01448 void *operator new(std::size_t count, const std::nothrow_t& tag) 01449 { 01450 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01451 } 01452 01453 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01454 { 01455 return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR()); 01456 } 01457 01458 void operator delete(void *ptr) 01459 { 01460 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR()); 01461 } 01462 01463 void operator delete[](void *ptr) 01464 { 01465 free_wrapper(_REENT, ptr, MBED_CALLER_ADDR()); 01466 } 01467 01468 #else 01469 01470 void *operator new(std::size_t count) 01471 { 01472 void *buffer = malloc(count); 01473 if (NULL == buffer) { 01474 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count); 01475 } 01476 return buffer; 01477 } 01478 01479 void *operator new[](std::size_t count) 01480 { 01481 void *buffer = malloc(count); 01482 if (NULL == buffer) { 01483 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new[] out of memory\r\n", count); 01484 } 01485 return buffer; 01486 } 01487 01488 void *operator new(std::size_t count, const std::nothrow_t& tag) 01489 { 01490 return malloc(count); 01491 } 01492 01493 void *operator new[](std::size_t count, const std::nothrow_t& tag) 01494 { 01495 return malloc(count); 01496 } 01497 01498 void operator delete(void *ptr) 01499 { 01500 free(ptr); 01501 } 01502 void operator delete[](void *ptr) 01503 { 01504 free(ptr); 01505 } 01506 01507 #endif 01508 01509 /* @brief standard c library clock() function. 01510 * 01511 * This function returns the number of clock ticks elapsed since the start of the program. 01512 * 01513 * @note Synchronization level: Thread safe 01514 * 01515 * @return 01516 * the number of clock ticks elapsed since the start of the program. 01517 * 01518 * */ 01519 extern "C" clock_t clock() 01520 { 01521 _mutex->lock(); 01522 clock_t t = ticker_read(get_us_ticker_data()); 01523 t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time 01524 _mutex->unlock(); 01525 return t; 01526 } 01527 01528 // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info 01529 MBED_WEAK const ticker_info_t* us_ticker_get_info() 01530 { 01531 static const ticker_info_t info = { 01532 1000000, 01533 32 01534 }; 01535 return &info; 01536 } 01537 01538 // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info 01539 MBED_WEAK const ticker_info_t* lp_ticker_get_info() 01540 { 01541 static const ticker_info_t info = { 01542 1000000, 01543 32 01544 }; 01545 return &info; 01546 }
Generated on Tue Jul 12 2022 12:45:29 by
1.7.2