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