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.
Fork of mbed-dev by
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:59:33 by
1.7.2
