2013-02-18 15:32:11 +00:00
/* mbed Microcontroller Library
2015-02-12 08:14:26 +00:00
* Copyright ( c ) 2006 - 2015 ARM Limited
2018-11-09 11:31:20 +00:00
* SPDX - License - Identifier : Apache - 2.0
2013-02-18 15:32:11 +00:00
*
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
2019-01-14 10:22:15 +00:00
2017-09-14 10:07:51 +00:00
# include <time.h>
2016-10-01 07:11:36 +00:00
# include "platform/platform.h"
2017-03-07 16:40:37 +00:00
# include "platform/FilePath.h"
2016-10-01 07:11:36 +00:00
# include "hal/serial_api.h"
2017-09-14 10:07:51 +00:00
# include "hal/us_ticker_api.h"
2017-01-27 11:10:28 +00:00
# include "platform/mbed_toolchain.h"
# include "platform/mbed_semihost_api.h"
2016-10-01 07:11:36 +00:00
# include "platform/mbed_interface.h"
# include "platform/SingletonPtr.h"
# include "platform/PlatformMutex.h"
# include "platform/mbed_error.h"
# include "platform/mbed_stats.h"
2017-05-24 20:12:52 +00:00
# include "platform/mbed_critical.h"
2017-11-23 09:53:22 +00:00
# include "platform/mbed_poll.h"
2017-09-14 10:07:51 +00:00
# include "platform/PlatformMutex.h"
2017-11-23 15:44:33 +00:00
# include "drivers/UARTSerial.h"
2017-09-19 18:58:34 +00:00
# include "us_ticker_api.h"
# include "lp_ticker_api.h"
2016-08-01 14:07:35 +00:00
# include <stdlib.h>
2016-08-13 22:12:03 +00:00
# include <string.h>
2017-03-28 14:28:38 +00:00
# include <limits.h>
2017-11-23 15:44:33 +00:00
# ifndef SSIZE_MAX
# define SSIZE_MAX INT_MAX
2015-02-12 08:14:26 +00:00
# endif
# include <stdio.h>
2013-02-18 15:32:11 +00:00
# include <errno.h>
2017-03-01 22:45:55 +00:00
# include "platform/mbed_retarget.h"
2013-02-18 15:32:11 +00:00
2017-09-14 10:07:51 +00:00
static SingletonPtr < PlatformMutex > _mutex ;
2013-02-18 15:32:11 +00:00
# if defined(__ARMCC_VERSION)
2017-08-17 18:08:52 +00:00
# if __ARMCC_VERSION >= 6010050
# include <arm_compat.h>
# endif
2013-02-18 15:32:11 +00:00
# include <rt_sys.h>
2017-08-17 18:08:52 +00:00
# include <rt_misc.h>
# include <stdint.h>
2013-02-18 15:32:11 +00:00
# define PREFIX(x) _sys##x
# define OPEN_MAX _SYS_OPEN
# ifdef __MICROLIB
2019-02-19 16:48:21 +00:00
# if __ARMCC_VERSION >= 6010050
asm ( " .global __use_full_stdio \n " ) ;
# else
# pragma import(__use_full_stdio)
# endif
2013-02-18 15:32:11 +00:00
# endif
# elif defined(__ICCARM__)
# include <yfuns.h>
# define PREFIX(x) _##x
# define OPEN_MAX 16
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
# else
# include <sys / syslimits.h>
# define PREFIX(x) x
# endif
2017-11-23 15:44:33 +00:00
# define FILE_HANDLE_RESERVED ((FileHandle*)0xFFFFFFFF)
2016-05-31 22:57:41 +00:00
2018-04-11 16:53:06 +00:00
/**
* Macros for setting console flow control .
*/
# define CONSOLE_FLOWCONTROL_RTS 1
# define CONSOLE_FLOWCONTROL_CTS 2
# define CONSOLE_FLOWCONTROL_RTSCTS 3
# define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
# define mbed_console_concat(x) mbed_console_concat_(x)
# define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
2013-02-18 15:32:11 +00:00
using namespace mbed ;
2013-04-24 14:29:23 +00:00
# if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
// Before version 5.03, we were using a patched version of microlib with proper names
extern const char __stdin_name [ ] = " :tt " ;
extern const char __stdout_name [ ] = " :tt " ;
extern const char __stderr_name [ ] = " :tt " ;
# else
2013-02-18 15:32:11 +00:00
extern const char __stdin_name [ ] = " /stdin " ;
extern const char __stdout_name [ ] = " /stdout " ;
extern const char __stderr_name [ ] = " /stderr " ;
2013-04-24 14:29:23 +00:00
# endif
2013-02-18 15:32:11 +00:00
2016-07-29 20:29:56 +00:00
unsigned char * mbed_heap_start = 0 ;
uint32_t mbed_heap_size = 0 ;
2013-02-18 15:32:11 +00:00
/* newlib has the filehandle field in the FILE struct as a short, so
* we can ' t just return a Filehandle * from _open and instead have to
* put it in a filehandles array and return the index into that array
*/
2017-11-23 15:44:33 +00:00
static FileHandle * filehandles [ OPEN_MAX ] = { FILE_HANDLE_RESERVED , FILE_HANDLE_RESERVED , FILE_HANDLE_RESERVED } ;
static char stdio_in_prev [ OPEN_MAX ] ;
static char stdio_out_prev [ OPEN_MAX ] ;
2016-06-27 23:55:07 +00:00
static SingletonPtr < PlatformMutex > filehandle_mutex ;
2013-02-18 15:32:11 +00:00
2017-02-13 19:19:57 +00:00
namespace mbed {
2017-11-23 11:09:21 +00:00
void mbed_set_unbuffered_stream ( std : : FILE * _file ) ;
2018-06-27 14:09:15 +00:00
void remove_filehandle ( FileHandle * file )
{
2016-06-27 23:55:07 +00:00
filehandle_mutex - > lock ( ) ;
2013-02-18 15:32:11 +00:00
/* Remove all open filehandles for this */
2018-06-27 14:09:15 +00:00
for ( unsigned int fh_i = 0 ; fh_i < sizeof ( filehandles ) / sizeof ( * filehandles ) ; fh_i + + ) {
2017-02-13 19:19:57 +00:00
if ( filehandles [ fh_i ] = = file ) {
2013-02-18 15:32:11 +00:00
filehandles [ fh_i ] = NULL ;
}
}
2016-06-27 23:55:07 +00:00
filehandle_mutex - > unlock ( ) ;
2013-02-18 15:32:11 +00:00
}
2017-02-13 19:19:57 +00:00
}
2013-02-18 15:32:11 +00:00
# if DEVICE_SERIAL
extern int stdio_uart_inited ;
extern serial_t stdio_uart ;
2017-11-23 15:44:33 +00:00
/* Private FileHandle to implement backwards-compatible functionality of
* direct HAL serial access for default stdin / stdout / stderr .
* This is not a particularly well - behaved FileHandle for a stream , which
* is why it ' s not public . People should be using UARTSerial .
*/
class DirectSerial : public FileHandle {
public :
DirectSerial ( PinName tx , PinName rx , int baud ) ;
virtual ssize_t write ( const void * buffer , size_t size ) ;
virtual ssize_t read ( void * buffer , size_t size ) ;
2018-06-27 14:09:15 +00:00
virtual off_t seek ( off_t offset , int whence = SEEK_SET )
{
2017-11-23 15:44:33 +00:00
return - ESPIPE ;
}
2018-06-27 14:09:15 +00:00
virtual off_t size ( )
{
2017-11-23 15:44:33 +00:00
return - EINVAL ;
}
2018-06-27 14:09:15 +00:00
virtual int isatty ( )
{
2017-11-23 15:44:33 +00:00
return true ;
}
2018-06-27 14:09:15 +00:00
virtual int close ( )
{
2017-11-23 15:44:33 +00:00
return 0 ;
}
virtual short poll ( short events ) const ;
} ;
2018-06-27 14:09:15 +00:00
DirectSerial : : DirectSerial ( PinName tx , PinName rx , int baud )
{
if ( stdio_uart_inited ) {
return ;
}
2017-11-23 15:44:33 +00:00
serial_init ( & stdio_uart , tx , rx ) ;
serial_baud ( & stdio_uart , baud ) ;
2018-04-11 16:53:06 +00:00
# if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
serial_set_flow_control ( & stdio_uart , FlowControlRTS , STDIO_UART_RTS , NC ) ;
# elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
serial_set_flow_control ( & stdio_uart , FlowControlCTS , NC , STDIO_UART_CTS ) ;
# elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
serial_set_flow_control ( & stdio_uart , FlowControlRTSCTS , STDIO_UART_RTS , STDIO_UART_CTS ) ;
# endif
2017-11-23 15:44:33 +00:00
}
2018-06-27 14:09:15 +00:00
ssize_t DirectSerial : : write ( const void * buffer , size_t size )
{
2017-11-23 15:44:33 +00:00
const unsigned char * buf = static_cast < const unsigned char * > ( buffer ) ;
for ( size_t i = 0 ; i < size ; i + + ) {
serial_putc ( & stdio_uart , buf [ i ] ) ;
}
return size ;
}
2018-06-27 14:09:15 +00:00
ssize_t DirectSerial : : read ( void * buffer , size_t size )
{
2017-11-23 15:44:33 +00:00
unsigned char * buf = static_cast < unsigned char * > ( buffer ) ;
if ( size = = 0 ) {
return 0 ;
}
buf [ 0 ] = serial_getc ( & stdio_uart ) ;
return 1 ;
}
2018-06-27 14:09:15 +00:00
short DirectSerial : : poll ( short events ) const
{
2017-11-23 15:44:33 +00:00
short revents = 0 ;
if ( ( events & POLLIN ) & & serial_readable ( & stdio_uart ) ) {
revents | = POLLIN ;
}
if ( ( events & POLLOUT ) & & serial_writable ( & stdio_uart ) ) {
revents | = POLLOUT ;
}
return revents ;
}
2018-05-12 15:26:09 +00:00
# endif
2017-11-23 15:44:33 +00:00
class Sink : public FileHandle {
public :
virtual ssize_t write ( const void * buffer , size_t size ) ;
virtual ssize_t read ( void * buffer , size_t size ) ;
2018-06-27 14:09:15 +00:00
virtual off_t seek ( off_t offset , int whence = SEEK_SET )
{
return ESPIPE ;
}
virtual off_t size ( )
{
return - EINVAL ;
}
virtual int isatty ( )
{
return true ;
}
virtual int close ( )
{
return 0 ;
}
2017-11-23 15:44:33 +00:00
} ;
2018-06-27 14:09:15 +00:00
ssize_t Sink : : write ( const void * buffer , size_t size )
{
2017-11-23 15:44:33 +00:00
// Just swallow the data - this is historical non-DEVICE_SERIAL behaviour
return size ;
}
2018-06-27 14:09:15 +00:00
ssize_t Sink : : read ( void * buffer , size_t size )
{
2017-11-23 15:44:33 +00:00
// Produce 1 zero byte - historical behaviour returned 1 without touching
// the buffer
unsigned char * buf = static_cast < unsigned char * > ( buffer ) ;
buf [ 0 ] = 0 ;
return 1 ;
}
2018-06-27 14:09:15 +00:00
MBED_WEAK FileHandle * mbed : : mbed_target_override_console ( int fd )
2017-11-23 15:44:33 +00:00
{
return NULL ;
}
2018-06-27 14:09:15 +00:00
MBED_WEAK FileHandle * mbed : : mbed_override_console ( int fd )
2017-11-23 15:44:33 +00:00
{
return NULL ;
}
2018-06-27 14:09:15 +00:00
static FileHandle * default_console ( )
2017-11-23 15:44:33 +00:00
{
# if DEVICE_SERIAL
# if MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL
static UARTSerial console ( STDIO_UART_TX , STDIO_UART_RX , MBED_CONF_PLATFORM_STDIO_BAUD_RATE ) ;
2018-04-11 16:53:06 +00:00
# if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
2018-06-27 14:09:15 +00:00
console . set_flow_control ( SerialBase : : RTS , STDIO_UART_RTS , NC ) ;
2018-04-11 16:53:06 +00:00
# elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
2018-06-27 14:09:15 +00:00
console . set_flow_control ( SerialBase : : CTS , NC , STDIO_UART_CTS ) ;
2018-04-11 16:53:06 +00:00
# elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
2018-06-27 14:09:15 +00:00
console . set_flow_control ( SerialBase : : RTSCTS , STDIO_UART_RTS , STDIO_UART_CTS ) ;
2018-04-11 16:53:06 +00:00
# endif
2017-11-23 15:44:33 +00:00
# else
static DirectSerial console ( STDIO_UART_TX , STDIO_UART_RX , MBED_CONF_PLATFORM_STDIO_BAUD_RATE ) ;
# endif
# else // DEVICE_SERIAL
static Sink console ;
2013-02-18 15:32:11 +00:00
# endif
2017-11-23 15:44:33 +00:00
return & console ;
}
/* Locate the default console for stdout, stdin, stderr */
2018-06-27 14:09:15 +00:00
static FileHandle * get_console ( int fd )
{
2017-11-23 15:44:33 +00:00
FileHandle * fh = mbed_override_console ( fd ) ;
if ( fh ) {
return fh ;
}
fh = mbed_target_override_console ( fd ) ;
if ( fh ) {
return fh ;
}
return default_console ( ) ;
}
/* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
2018-06-27 14:09:15 +00:00
static FileHandle * get_fhc ( int fd )
{
2017-11-23 15:44:33 +00:00
if ( fd > = OPEN_MAX ) {
return NULL ;
}
FileHandle * fh = filehandles [ fd ] ;
if ( fh = = FILE_HANDLE_RESERVED & & fd < 3 ) {
filehandles [ fd ] = fh = get_console ( fd ) ;
}
return fh ;
2013-02-18 15:32:11 +00:00
}
2017-03-28 14:28:38 +00:00
/**
* Sets errno when file opening fails .
* Wipes out the filehandle too .
2017-05-23 17:07:24 +00:00
*
* @ param error is a negative error code returned from an mbed function and
* will be negated to store a positive error code in errno
2017-03-28 14:28:38 +00:00
*/
2018-06-27 14:09:15 +00:00
static int handle_open_errors ( int error , unsigned filehandle_idx )
{
2017-03-28 14:28:38 +00:00
errno = - error ;
// Free file handle
filehandles [ filehandle_idx ] = NULL ;
return - 1 ;
}
2018-06-27 14:09:15 +00:00
static inline int openflags_to_posix ( int openflags )
{
2017-11-23 09:53:22 +00:00
int posix = openflags ;
2013-02-18 15:32:11 +00:00
# ifdef __ARMCC_VERSION
2017-11-23 09:53:22 +00:00
if ( openflags & OPEN_PLUS ) {
2013-02-18 15:32:11 +00:00
posix = O_RDWR ;
2018-06-27 14:09:15 +00:00
} else if ( openflags & OPEN_W ) {
2013-02-18 15:32:11 +00:00
posix = O_WRONLY ;
2018-06-27 14:09:15 +00:00
} else if ( openflags & OPEN_A ) {
posix = O_WRONLY | O_APPEND ;
2013-02-18 15:32:11 +00:00
} else {
posix = O_RDONLY ;
}
/* a, w, a+, w+ all create if file does not already exist */
2018-06-27 14:09:15 +00:00
if ( openflags & ( OPEN_A | OPEN_W ) ) {
2013-02-18 15:32:11 +00:00
posix | = O_CREAT ;
}
/* w and w+ truncate */
2017-11-23 09:53:22 +00:00
if ( openflags & OPEN_W ) {
2013-02-18 15:32:11 +00:00
posix | = O_TRUNC ;
}
# elif defined(__ICCARM__)
2017-11-23 09:53:22 +00:00
switch ( openflags & _LLIO_RDWRMASK ) {
2018-06-27 14:09:15 +00:00
case _LLIO_RDONLY :
posix = O_RDONLY ;
break ;
case _LLIO_WRONLY :
posix = O_WRONLY ;
break ;
case _LLIO_RDWR :
posix = O_RDWR ;
break ;
}
if ( openflags & _LLIO_CREAT ) {
posix | = O_CREAT ;
}
if ( openflags & _LLIO_APPEND ) {
posix | = O_APPEND ;
}
if ( openflags & _LLIO_TRUNC ) {
posix | = O_TRUNC ;
2013-02-18 15:32:11 +00:00
}
2016-03-08 22:13:00 +00:00
# elif defined(TOOLCHAIN_GCC)
posix & = ~ O_BINARY ;
2013-02-18 15:32:11 +00:00
# endif
2016-03-08 22:13:00 +00:00
return posix ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
static int reserve_filehandle ( )
{
2017-11-23 11:09:21 +00:00
// find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr
filehandle_mutex - > lock ( ) ;
int fh_i ;
for ( fh_i = 3 ; fh_i < OPEN_MAX ; fh_i + + ) {
/* Take a next free filehandle slot available. */
2018-06-27 14:09:15 +00:00
if ( filehandles [ fh_i ] = = NULL ) {
break ;
}
2017-11-23 11:09:21 +00:00
}
if ( fh_i > = OPEN_MAX ) {
/* Too many file handles have been opened */
errno = EMFILE ;
filehandle_mutex - > unlock ( ) ;
return - 1 ;
}
2017-11-23 15:44:33 +00:00
filehandles [ fh_i ] = FILE_HANDLE_RESERVED ;
2017-11-23 11:09:21 +00:00
filehandle_mutex - > unlock ( ) ;
return fh_i ;
}
2018-06-27 14:09:15 +00:00
int mbed : : bind_to_fd ( FileHandle * fh )
{
2018-05-02 10:56:32 +00:00
int fildes = reserve_filehandle ( ) ;
if ( fildes < 0 ) {
return fildes ;
2017-11-23 11:09:21 +00:00
}
2018-05-02 10:56:32 +00:00
filehandles [ fildes ] = fh ;
stdio_in_prev [ fildes ] = 0 ;
stdio_out_prev [ fildes ] = 0 ;
2017-11-23 11:09:21 +00:00
2018-05-02 10:56:32 +00:00
return fildes ;
2017-11-23 11:09:21 +00:00
}
2018-06-27 14:09:15 +00:00
static int unbind_from_fd ( int fd , FileHandle * fh )
{
2017-11-23 11:09:21 +00:00
if ( filehandles [ fd ] = = fh ) {
filehandles [ fd ] = NULL ;
return 0 ;
} else {
errno = EBADF ;
return - 1 ;
}
}
# ifndef __IAR_SYSTEMS_ICC__
/* IAR provides fdopen itself */
2018-06-27 14:09:15 +00:00
extern " C " std : : FILE * fdopen ( int fildes , const char * mode )
2017-11-23 11:09:21 +00:00
{
// This is to avoid scanf and the bloat it brings.
char buf [ 1 + sizeof fildes ] ; /* @(integer) */
MBED_STATIC_ASSERT ( sizeof buf = = 5 , " Integers should be 4 bytes. " ) ;
buf [ 0 ] = ' @ ' ;
memcpy ( buf + 1 , & fildes , sizeof fildes ) ;
std : : FILE * stream = std : : fopen ( buf , mode ) ;
/* newlib-nano doesn't appear to ever call _isatty itself, so
* happily fully buffers an interactive stream . Deal with that here .
*/
if ( stream & & isatty ( fildes ) ) {
mbed_set_unbuffered_stream ( stream ) ;
}
return stream ;
}
# endif
namespace mbed {
std : : FILE * fdopen ( FileHandle * fh , const char * mode )
{
// First reserve the integer file descriptor
int fd = bind_to_fd ( fh ) ;
if ( ! fd ) {
return NULL ;
}
// Then bind that to the C stream. If successful, C library
// takes ownership and responsibility to close.
std : : FILE * stream = : : fdopen ( fd , mode ) ;
if ( ! stream ) {
unbind_from_fd ( fd , fh ) ;
}
return stream ;
}
}
2018-06-27 14:09:15 +00:00
/* @brief standard c library fopen() retargeting function.
2017-01-19 18:30:19 +00:00
*
* This function is invoked by the standard c library retargeting to handle fopen ( )
*
* @ return
* On success , a valid FILEHANDLE is returned .
* On failure , - 1 is returned and errno is set to an appropriate value e . g .
2018-06-27 14:09:15 +00:00
* ENOENT file not found ( default errno setting )
* EMFILE the maximum number of open files was exceeded .
2017-01-19 18:30:19 +00:00
*
* */
2018-06-27 14:09:15 +00:00
extern " C " FILEHANDLE PREFIX ( _open ) ( const char * name , int openflags )
{
2017-11-23 11:09:21 +00:00
# if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
2017-06-29 13:35:00 +00:00
# if !defined(MBED_CONF_RTOS_PRESENT)
// valid only for mbed 2
// for ulib, this is invoked after RAM init, prior c++
// used as hook, as post stack/heap is not active there
extern void mbed_copy_nvic ( void ) ;
extern void mbed_sdk_init ( void ) ;
static int mbed_sdk_inited = 0 ;
if ( ! mbed_sdk_inited ) {
mbed_copy_nvic ( ) ;
mbed_sdk_init ( ) ;
mbed_sdk_inited = 1 ;
}
# endif
2013-07-08 16:31:04 +00:00
// Before version 5.03, we were using a patched version of microlib with proper names
// This is the workaround that the microlib author suggested us
static int n = 0 ;
2017-11-23 15:44:33 +00:00
if ( std : : strcmp ( name , " :tt " ) = = 0 & & n < 3 ) {
return n + + ;
}
2017-11-23 11:09:21 +00:00
# else
2013-02-18 15:32:11 +00:00
/* Use the posix convention that stdin,out,err are filehandles 0,1,2.
*/
if ( std : : strcmp ( name , __stdin_name ) = = 0 ) {
2017-11-23 15:44:33 +00:00
get_fhc ( STDIN_FILENO ) ;
return STDIN_FILENO ;
2013-02-18 15:32:11 +00:00
} else if ( std : : strcmp ( name , __stdout_name ) = = 0 ) {
2017-11-23 15:44:33 +00:00
get_fhc ( STDOUT_FILENO ) ;
return STDOUT_FILENO ;
2013-05-30 09:56:18 +00:00
} else if ( std : : strcmp ( name , __stderr_name ) = = 0 ) {
2017-11-23 15:44:33 +00:00
get_fhc ( STDERR_FILENO ) ;
return STDERR_FILENO ;
2013-02-18 15:32:11 +00:00
}
2017-11-23 11:09:21 +00:00
# endif
# ifndef __IAR_SYSTEMS_ICC__
/* FILENAME: "@(integer)" gives an already-allocated descriptor */
if ( name [ 0 ] = = ' @ ' ) {
int fd ;
memcpy ( & fd , name + 1 , sizeof fd ) ;
return fd ;
2013-02-18 15:32:11 +00:00
}
2017-11-23 11:09:21 +00:00
# endif
return open ( name , openflags_to_posix ( openflags ) ) ;
}
2018-06-27 14:09:15 +00:00
extern " C " int open ( const char * name , int oflag , . . . )
{
2018-05-02 10:56:32 +00:00
int fildes = reserve_filehandle ( ) ;
if ( fildes < 0 ) {
return fildes ;
2013-02-18 15:32:11 +00:00
}
2017-03-01 22:23:03 +00:00
FileHandle * res = NULL ;
2017-11-23 11:09:21 +00:00
FilePath path ( name ) ;
2013-02-18 15:32:11 +00:00
2017-11-23 11:09:21 +00:00
if ( ! path . exists ( ) ) {
/* The first part of the filename (between first 2 '/') is not a
* registered mount point in the namespace .
*/
2018-05-02 10:56:32 +00:00
return handle_open_errors ( - ENODEV , fildes ) ;
2017-11-23 11:09:21 +00:00
}
2013-02-18 15:32:11 +00:00
2017-11-23 11:09:21 +00:00
if ( path . isFile ( ) ) {
res = path . file ( ) ;
2013-02-18 15:32:11 +00:00
} else {
2017-11-23 11:09:21 +00:00
FileSystemHandle * fs = path . fileSystem ( ) ;
if ( fs = = NULL ) {
2018-05-02 10:56:32 +00:00
return handle_open_errors ( - ENODEV , fildes ) ;
2017-03-28 14:28:38 +00:00
}
2017-11-23 11:09:21 +00:00
int err = fs - > open ( & res , path . fileName ( ) , oflag ) ;
if ( err ) {
2018-05-02 10:56:32 +00:00
return handle_open_errors ( err , fildes ) ;
2013-02-18 15:32:11 +00:00
}
}
2018-05-02 10:56:32 +00:00
filehandles [ fildes ] = res ;
stdio_in_prev [ fildes ] = 0 ;
stdio_out_prev [ fildes ] = 0 ;
2013-02-18 15:32:11 +00:00
2018-05-02 10:56:32 +00:00
return fildes ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " int PREFIX ( _close ) ( FILEHANDLE fh )
{
2017-11-23 09:53:22 +00:00
return close ( fh ) ;
}
2013-02-18 15:32:11 +00:00
2018-06-27 14:09:15 +00:00
extern " C " int close ( int fildes )
{
FileHandle * fhc = get_fhc ( fildes ) ;
2018-05-02 10:56:32 +00:00
filehandles [ fildes ] = NULL ;
2017-03-28 14:28:38 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
2013-02-18 15:32:11 +00:00
2017-02-13 23:49:57 +00:00
int err = fhc - > close ( ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
static bool convert_crlf ( int fd )
{
2017-11-23 15:44:33 +00:00
# if MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
return isatty ( fd ) ;
# elif MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
return fd < 3 & & isatty ( fd ) ;
# else
return false ;
# endif
}
2013-02-18 15:32:11 +00:00
# if defined(__ICCARM__)
2018-06-27 14:09:15 +00:00
extern " C " size_t __write ( int fh , const unsigned char * buffer , size_t length )
{
2013-02-18 15:32:11 +00:00
# else
2018-06-27 14:09:15 +00:00
extern " C " int PREFIX ( _write ) ( FILEHANDLE fh , const unsigned char * buffer , unsigned int length , int mode )
{
2013-02-18 15:32:11 +00:00
# endif
2017-01-20 15:23:39 +00:00
2017-06-08 20:26:22 +00:00
# if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
2017-05-24 20:12:52 +00:00
if ( core_util_is_isr_active ( ) | | ! core_util_are_interrupts_enabled ( ) ) {
2018-05-23 17:19:09 +00:00
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 ) ;
2017-05-24 20:12:52 +00:00
}
# endif
2017-11-23 15:44:33 +00:00
if ( length > SSIZE_MAX ) {
errno = EINVAL ;
return - 1 ;
}
ssize_t slength = length ;
ssize_t written = 0 ;
if ( convert_crlf ( fh ) ) {
// local prev is previous in buffer during seek
// stdio_out_prev[fh] is last thing actually written
char prev = stdio_out_prev [ fh ] ;
// Seek for '\n' without preceding '\r'; if found flush
// preceding and insert '\r'. Continue until end of input.
for ( ssize_t cur = 0 ; cur < slength ; cur + + ) {
if ( buffer [ cur ] = = ' \n ' & & prev ! = ' \r ' ) {
ssize_t r ;
// flush stuff preceding the \n
if ( cur > written ) {
r = write ( fh , buffer + written , cur - written ) ;
if ( r < 0 ) {
return - 1 ;
}
written + = r ;
if ( written < cur ) {
// For some reason, didn't write all - give up now
goto finish ;
}
stdio_out_prev [ fh ] = prev ;
}
// insert a \r now, leaving the \n still to be written
r = write ( fh , " \r " , 1 ) ;
if ( r < 0 ) {
return - 1 ;
}
if ( r < 1 ) {
goto finish ;
}
stdio_out_prev [ fh ] = ' \r ' ;
2016-06-07 14:43:40 +00:00
}
2017-11-23 15:44:33 +00:00
prev = buffer [ cur ] ;
2016-06-16 01:57:25 +00:00
}
2017-11-23 15:44:33 +00:00
}
// Flush remaining from conversion, or the whole thing if no conversion
if ( written < slength ) {
ssize_t r = write ( fh , buffer + written , slength - written ) ;
if ( r < 0 ) {
2017-03-28 14:28:38 +00:00
return - 1 ;
}
2017-11-23 15:44:33 +00:00
written + = r ;
if ( written > 0 ) {
stdio_out_prev [ fh ] = buffer [ written - 1 ] ;
2017-02-13 23:49:57 +00:00
}
2013-02-18 15:32:11 +00:00
}
2017-11-23 15:44:33 +00:00
finish :
2013-02-18 15:32:11 +00:00
# ifdef __ARMCC_VERSION
2017-11-23 09:53:22 +00:00
if ( written > = 0 ) {
2017-11-23 15:44:33 +00:00
return slength - written ;
2017-11-23 09:53:22 +00:00
} else {
return written ;
}
2013-02-18 15:32:11 +00:00
# else
2017-11-23 09:53:22 +00:00
return written ;
2013-02-18 15:32:11 +00:00
# endif
}
2018-06-27 14:09:15 +00:00
extern " C " ssize_t write ( int fildes , const void * buf , size_t length )
{
2017-01-20 15:23:39 +00:00
2018-06-27 14:09:15 +00:00
FileHandle * fhc = get_fhc ( fildes ) ;
2017-11-23 15:44:33 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
2017-05-24 20:12:52 +00:00
}
2017-11-23 15:44:33 +00:00
ssize_t ret = fhc - > write ( buf , length ) ;
if ( ret < 0 ) {
errno = - ret ;
return - 1 ;
2013-02-18 15:32:11 +00:00
} else {
2017-11-23 15:44:33 +00:00
return ret ;
2013-02-18 15:32:11 +00:00
}
}
2017-08-17 18:06:35 +00:00
# if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
2018-06-27 14:09:15 +00:00
extern " C " void PREFIX ( _exit ) ( int return_code )
{
while ( 1 ) { }
2017-08-17 18:06:35 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " void _ttywrch ( int ch )
{
2017-11-23 15:44:33 +00:00
char c = ch ;
write ( STDOUT_FILENO , & c , 1 ) ;
2017-08-17 18:06:35 +00:00
}
# endif
2013-02-18 15:32:11 +00:00
# if defined(__ICCARM__)
2018-06-27 14:09:15 +00:00
extern " C " size_t __read ( int fh , unsigned char * buffer , size_t length )
{
2013-02-18 15:32:11 +00:00
# else
2018-06-27 14:09:15 +00:00
extern " C " int PREFIX ( _read ) ( FILEHANDLE fh , unsigned char * buffer , unsigned int length , int mode )
{
2013-02-18 15:32:11 +00:00
# endif
2017-01-20 15:23:39 +00:00
2017-06-08 20:26:22 +00:00
# if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
2017-05-24 20:12:52 +00:00
if ( core_util_is_isr_active ( ) | | ! core_util_are_interrupts_enabled ( ) ) {
2018-05-23 17:19:09 +00:00
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 ) ;
2017-05-24 20:12:52 +00:00
}
# endif
2017-11-23 15:44:33 +00:00
if ( length > SSIZE_MAX ) {
errno = EINVAL ;
return - 1 ;
}
ssize_t bytes_read = 0 ;
if ( convert_crlf ( fh ) ) {
2016-06-07 15:08:07 +00:00
while ( true ) {
2017-11-23 15:44:33 +00:00
char c ;
ssize_t r = read ( fh , & c , 1 ) ;
if ( r < 0 ) {
return - 1 ;
}
if ( r = = 0 ) {
return bytes_read ;
}
if ( ( c = = ' \r ' & & stdio_in_prev [ fh ] ! = ' \n ' ) | |
2018-06-27 14:09:15 +00:00
( c = = ' \n ' & & stdio_in_prev [ fh ] ! = ' \r ' ) ) {
2017-11-23 15:44:33 +00:00
stdio_in_prev [ fh ] = c ;
2016-06-07 15:08:07 +00:00
* buffer = ' \n ' ;
break ;
2017-11-23 15:44:33 +00:00
} else if ( ( c = = ' \r ' & & stdio_in_prev [ fh ] = = ' \n ' ) | |
( c = = ' \n ' & & stdio_in_prev [ fh ] = = ' \r ' ) ) {
stdio_in_prev [ fh ] = c ;
2016-06-07 15:08:07 +00:00
continue ;
} else {
2017-11-23 15:44:33 +00:00
stdio_in_prev [ fh ] = c ;
2016-06-07 15:08:07 +00:00
* buffer = c ;
break ;
}
}
2017-11-23 15:44:33 +00:00
bytes_read = 1 ;
2013-02-18 15:32:11 +00:00
} else {
2017-11-23 15:44:33 +00:00
bytes_read = read ( fh , buffer , length ) ;
2013-02-18 15:32:11 +00:00
}
2017-11-23 15:44:33 +00:00
2013-02-18 15:32:11 +00:00
# ifdef __ARMCC_VERSION
2017-11-23 15:44:33 +00:00
if ( bytes_read < 0 ) {
return - 1 ;
} else if ( bytes_read = = 0 ) {
return 0x80000000 | length ; // weird EOF indication
} else {
return ( ssize_t ) length - bytes_read ;
}
2013-02-18 15:32:11 +00:00
# else
2017-11-23 15:44:33 +00:00
return bytes_read ;
2013-02-18 15:32:11 +00:00
# endif
}
2018-06-27 14:09:15 +00:00
extern " C " ssize_t read ( int fildes , void * buf , size_t length )
{
2017-11-23 15:44:33 +00:00
2018-06-27 14:09:15 +00:00
FileHandle * fhc = get_fhc ( fildes ) ;
2017-11-23 15:44:33 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
ssize_t ret = fhc - > read ( buf , length ) ;
if ( ret < 0 ) {
errno = - ret ;
return - 1 ;
} else {
return ret ;
2013-02-18 15:32:11 +00:00
}
}
2017-02-15 23:21:50 +00:00
2013-02-18 15:32:11 +00:00
# ifdef __ARMCC_VERSION
extern " C " int PREFIX ( _istty ) ( FILEHANDLE fh )
# else
extern " C " int _isatty ( FILEHANDLE fh )
# endif
{
2017-11-23 09:53:22 +00:00
return isatty ( fh ) ;
}
2013-02-18 15:32:11 +00:00
2018-06-27 14:09:15 +00:00
extern " C " int isatty ( int fildes )
{
FileHandle * fhc = get_fhc ( fildes ) ;
2017-03-28 14:28:38 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return 0 ;
}
2013-02-18 15:32:11 +00:00
2017-03-28 14:28:38 +00:00
int tty = fhc - > isatty ( ) ;
if ( tty < 0 ) {
errno = - tty ;
2017-02-13 23:49:57 +00:00
return 0 ;
2017-03-28 14:28:38 +00:00
} else {
return tty ;
2017-02-13 23:49:57 +00:00
}
2013-02-18 15:32:11 +00:00
}
extern " C "
# if defined(__ARMCC_VERSION)
2017-03-28 14:28:38 +00:00
int _sys_seek ( FILEHANDLE fh , long offset )
2013-02-18 15:32:11 +00:00
# elif defined(__ICCARM__)
long __lseek ( int fh , long offset , int whence )
# else
int _lseek ( FILEHANDLE fh , int offset , int whence )
# endif
{
2017-03-28 14:28:38 +00:00
# if defined(__ARMCC_VERSION)
int whence = SEEK_SET ;
# endif
2017-09-26 20:10:04 +00:00
2017-11-23 09:53:22 +00:00
off_t off = lseek ( fh , offset , whence ) ;
// Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference
if ( off > INT_MAX ) {
errno = EOVERFLOW ;
2017-03-28 14:28:38 +00:00
return - 1 ;
}
2017-11-23 09:53:22 +00:00
return off ;
}
2013-02-18 15:32:11 +00:00
2018-06-27 14:09:15 +00:00
extern " C " off_t lseek ( int fildes , off_t offset , int whence )
{
FileHandle * fhc = get_fhc ( fildes ) ;
2017-03-28 14:28:38 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
2013-02-18 15:32:11 +00:00
2017-03-28 14:28:38 +00:00
off_t off = fhc - > seek ( offset , whence ) ;
if ( off < 0 ) {
errno = - off ;
return - 1 ;
}
return off ;
2013-02-18 15:32:11 +00:00
}
2018-06-07 11:23:38 +00:00
extern " C " int ftruncate ( int fildes , off_t length )
{
FileHandle * fhc = get_fhc ( fildes ) ;
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
int err = fhc - > truncate ( length ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
}
2013-02-18 15:32:11 +00:00
# ifdef __ARMCC_VERSION
2018-06-27 14:09:15 +00:00
extern " C " int PREFIX ( _ensure ) ( FILEHANDLE fh )
{
2017-11-23 09:53:22 +00:00
return fsync ( fh ) ;
}
# endif
2013-02-18 15:32:11 +00:00
2018-06-27 14:09:15 +00:00
extern " C " int fsync ( int fildes )
{
FileHandle * fhc = get_fhc ( fildes ) ;
2017-03-28 14:28:38 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
2013-02-18 15:32:11 +00:00
2017-02-13 23:49:57 +00:00
int err = fhc - > sync ( ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2013-02-18 15:32:11 +00:00
}
2017-11-23 09:53:22 +00:00
# ifdef __ARMCC_VERSION
2018-06-27 14:09:15 +00:00
extern " C " long PREFIX ( _flen ) ( FILEHANDLE fh )
{
FileHandle * fhc = get_fhc ( fh ) ;
2017-03-28 14:28:38 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
2013-02-18 15:32:11 +00:00
2017-03-28 14:28:38 +00:00
off_t size = fhc - > size ( ) ;
if ( size < 0 ) {
errno = - size ;
return - 1 ;
}
if ( size > LONG_MAX ) {
errno = EOVERFLOW ;
return - 1 ;
}
return size ;
2013-02-18 15:32:11 +00:00
}
2017-08-17 18:08:52 +00:00
2019-01-14 10:22:15 +00:00
// Do not compile this code for TFM secure target
# if !defined(COMPONENT_SPE) || !defined(TARGET_TFM)
2019-02-06 23:21:21 +00:00
# if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
__asm ( " .global __use_two_region_memory \n \t " ) ;
__asm ( " .global __use_no_semihosting \n \t " ) ;
2019-01-31 11:49:22 +00:00
# else
2019-02-06 23:21:21 +00:00
# pragma import(__use_two_region_memory)
# endif
# if !defined(HEAP_START)
// Heap here is considered starting after ZI ends to Stack start
2019-02-10 23:17:17 +00:00
extern uint32_t Image $ $ ARM_LIB_STACK $ $ ZI $ $ Base [ ] ;
2019-02-07 22:47:32 +00:00
extern uint32_t Image $ $ RW_IRAM1 $ $ ZI $ $ Limit [ ] ;
2019-02-06 23:21:21 +00:00
# define HEAP_START Image$$RW_IRAM1$$ZI$$Limit
2019-02-10 23:17:17 +00:00
# define HEAP_SIZE ((uint32_t)((uint32_t) Image$$ARM_LIB_STACK$$ZI$$Base - (uint32_t) HEAP_START))
2019-01-31 11:49:22 +00:00
# endif
2017-08-17 18:08:52 +00:00
2019-02-07 22:47:32 +00:00
# define HEAP_LIMIT ((uint32_t)((uint32_t)HEAP_START + (uint32_t)HEAP_SIZE))
2019-02-06 23:21:21 +00:00
2019-02-07 22:47:32 +00:00
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 )
2019-01-31 13:53:49 +00:00
{
2019-02-06 23:21:21 +00:00
uint32_t heap_base = ( uint32_t ) HEAP_START ;
2017-08-17 18:08:52 +00:00
struct __initial_stackheap r ;
2019-02-06 23:21:21 +00:00
// Ensure heap_base is 8-byte aligned
heap_base = ( heap_base + 7 ) & ~ 0x7 ;
r . heap_base = ( uint32_t ) heap_base ;
2019-01-31 11:49:22 +00:00
r . heap_limit = ( uint32_t ) HEAP_LIMIT ;
2019-02-06 23:21:21 +00:00
2017-08-17 18:08:52 +00:00
return r ;
}
2019-02-07 22:47:32 +00:00
extern " C " __value_in_regs struct __argc_argv $ Super $ $ __rt_lib_init ( unsigned heapbase , unsigned heaptop ) ;
2019-01-31 11:49:22 +00:00
2019-01-31 13:53:49 +00:00
extern " C " __value_in_regs struct __argc_argv $ Sub $ $ __rt_lib_init ( unsigned heapbase , unsigned heaptop )
2019-01-31 11:49:22 +00:00
{
2019-02-06 23:21:21 +00:00
return $ Super $ $ __rt_lib_init ( ( unsigned ) HEAP_START , ( unsigned ) HEAP_LIMIT ) ;
2019-01-31 11:49:22 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " __value_in_regs struct __initial_stackheap __user_setup_stackheap ( uint32_t R0 , uint32_t R1 , uint32_t R2 , uint32_t R3 )
{
2017-08-17 18:08:52 +00:00
return _mbed_user_setup_stackheap ( R0 , R1 , R2 , R3 ) ;
}
2019-01-14 10:22:15 +00:00
# endif // !defined(COMPONENT_SPE) || !defined(TARGET_TFM)
2013-02-18 15:32:11 +00:00
# endif
# if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
2018-06-27 14:09:15 +00:00
extern " C " int _fstat ( int fh , struct stat * st )
{
2017-11-23 09:53:22 +00:00
return fstat ( fh , st ) ;
}
# endif
2017-09-26 20:10:04 +00:00
2018-06-27 14:09:15 +00:00
extern " C " int fstat ( int fildes , struct stat * st )
{
FileHandle * fhc = get_fhc ( fildes ) ;
2017-09-26 20:10:04 +00:00
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
st - > st_mode = fhc - > isatty ( ) ? S_IFCHR : S_IFREG ;
st - > st_size = fhc - > size ( ) ;
return 0 ;
2013-02-18 15:32:11 +00:00
}
2017-11-23 09:53:22 +00:00
2018-06-27 14:09:15 +00:00
extern " C " int fcntl ( int fildes , int cmd , . . . )
{
2018-05-02 10:59:22 +00:00
FileHandle * fhc = get_fhc ( fildes ) ;
if ( fhc = = NULL ) {
errno = EBADF ;
return - 1 ;
}
switch ( cmd ) {
case F_GETFL : {
int flags = 0 ;
if ( fhc - > is_blocking ( ) ) {
flags | = O_NONBLOCK ;
}
return flags ;
}
case F_SETFL : {
va_list ap ;
va_start ( ap , cmd ) ;
int flags = va_arg ( ap , int ) ;
va_end ( ap ) ;
int ret = fhc - > set_blocking ( flags & O_NONBLOCK ) ;
if ( ret < 0 ) {
errno = - ret ;
return - 1 ;
}
return 0 ;
}
default : {
errno = EINVAL ;
return - 1 ;
}
}
}
2017-11-23 09:53:22 +00:00
extern " C " int poll ( struct pollfd fds [ ] , nfds_t nfds , int timeout )
{
if ( nfds > OPEN_MAX ) {
errno = EINVAL ;
return - 1 ;
}
struct mbed : : pollfh fhs [ OPEN_MAX ] ;
for ( nfds_t n = 0 ; n < nfds ; n + + ) {
// Underlying FileHandle poll returns POLLNVAL if given NULL, so
// we don't need to take special action.
2017-11-23 15:44:33 +00:00
fhs [ n ] . fh = get_fhc ( fds [ n ] . fd ) ;
2017-11-23 09:53:22 +00:00
fhs [ n ] . events = fds [ n ] . events ;
}
int ret = poll ( fhs , nfds , timeout ) ;
for ( nfds_t n = 0 ; n < nfds ; n + + ) {
fds [ n ] . revents = fhs [ n ] . revents ;
}
return ret ;
}
2013-02-18 15:32:11 +00:00
namespace std {
2018-06-27 14:09:15 +00:00
extern " C " int remove ( const char * path )
{
2013-02-18 15:32:11 +00:00
FilePath fp ( path ) ;
2017-03-30 19:36:21 +00:00
FileSystemHandle * fs = fp . fileSystem ( ) ;
2017-03-28 14:28:38 +00:00
if ( fs = = NULL ) {
2017-10-24 16:52:06 +00:00
errno = ENODEV ;
2017-03-28 14:28:38 +00:00
return - 1 ;
}
2013-02-18 15:32:11 +00:00
2017-02-13 23:49:57 +00:00
int err = fs - > remove ( fp . fileName ( ) ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " int rename ( const char * oldname , const char * newname )
{
2014-08-13 09:19:03 +00:00
FilePath fpOld ( oldname ) ;
FilePath fpNew ( newname ) ;
2017-03-30 19:36:21 +00:00
FileSystemHandle * fsOld = fpOld . fileSystem ( ) ;
FileSystemHandle * fsNew = fpNew . fileSystem ( ) ;
2014-08-13 09:19:03 +00:00
2017-03-28 14:28:38 +00:00
if ( fsOld = = NULL ) {
2017-10-24 16:52:06 +00:00
errno = ENODEV ;
2017-03-28 14:28:38 +00:00
return - 1 ;
}
2014-08-13 09:19:03 +00:00
/* rename only if both files are on the same FS */
2017-03-28 14:28:38 +00:00
if ( fsOld ! = fsNew ) {
errno = EXDEV ;
return - 1 ;
}
2014-08-13 09:19:03 +00:00
2017-02-13 23:49:57 +00:00
int err = fsOld - > rename ( fpOld . fileName ( ) , fpNew . fileName ( ) ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " char * tmpnam ( char * s )
{
2017-01-20 15:23:39 +00:00
errno = EBADF ;
2013-02-18 15:32:11 +00:00
return NULL ;
}
2018-06-27 14:09:15 +00:00
extern " C " FILE * tmpfile ( )
{
2017-01-20 15:23:39 +00:00
errno = EBADF ;
2013-02-18 15:32:11 +00:00
return NULL ;
}
} // namespace std
# ifdef __ARMCC_VERSION
2018-06-27 14:09:15 +00:00
extern " C " char * _sys_command_string ( char * cmd , int len )
{
2013-02-18 15:32:11 +00:00
return NULL ;
}
# endif
2018-06-27 14:09:15 +00:00
extern " C " DIR * opendir ( const char * path )
{
2013-02-18 15:32:11 +00:00
FilePath fp ( path ) ;
2018-06-27 14:09:15 +00:00
FileSystemHandle * fs = fp . fileSystem ( ) ;
2017-03-28 14:28:38 +00:00
if ( fs = = NULL ) {
2017-10-24 16:52:06 +00:00
errno = ENODEV ;
2017-03-28 14:28:38 +00:00
return NULL ;
}
2013-02-18 15:32:11 +00:00
2017-03-30 19:36:21 +00:00
DirHandle * dir ;
int err = fs - > open ( & dir , fp . fileName ( ) ) ;
2017-02-13 23:49:57 +00:00
if ( err < 0 ) {
errno = - err ;
2017-03-30 19:36:21 +00:00
return NULL ;
2017-02-13 19:19:57 +00:00
}
return dir ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " struct dirent * readdir ( DIR * dir )
{
2017-02-13 19:19:57 +00:00
static struct dirent ent ;
2017-02-23 02:14:50 +00:00
int err = dir - > read ( & ent ) ;
if ( err < 1 ) {
if ( err < 0 ) {
errno = - err ;
}
2017-02-13 19:19:57 +00:00
return NULL ;
}
return & ent ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " int closedir ( DIR * dir )
{
2017-02-13 23:49:57 +00:00
int err = dir - > close ( ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " void rewinddir ( DIR * dir )
{
2017-02-13 19:19:57 +00:00
dir - > rewind ( ) ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " off_t telldir ( DIR * dir )
{
2017-02-13 19:19:57 +00:00
return dir - > tell ( ) ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " void seekdir ( DIR * dir , off_t off )
{
2017-02-13 19:19:57 +00:00
dir - > seek ( off ) ;
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " int mkdir ( const char * path , mode_t mode )
{
2013-02-18 15:32:11 +00:00
FilePath fp ( path ) ;
2017-03-30 19:36:21 +00:00
FileSystemHandle * fs = fp . fileSystem ( ) ;
2017-10-24 16:52:06 +00:00
if ( fs = = NULL ) {
errno = ENODEV ;
return - 1 ;
}
2013-02-18 15:32:11 +00:00
2017-02-13 23:49:57 +00:00
int err = fs - > mkdir ( fp . fileName ( ) , mode ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2013-02-18 15:32:11 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " int stat ( const char * path , struct stat * st )
{
2017-01-19 15:30:06 +00:00
FilePath fp ( path ) ;
2017-03-30 19:36:21 +00:00
FileSystemHandle * fs = fp . fileSystem ( ) ;
2017-10-24 16:52:06 +00:00
if ( fs = = NULL ) {
errno = ENODEV ;
return - 1 ;
}
2017-01-19 15:30:06 +00:00
2017-02-13 23:49:57 +00:00
int err = fs - > stat ( fp . fileName ( ) , st ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
2017-01-19 15:30:06 +00:00
}
2018-06-27 14:09:15 +00:00
extern " C " int statvfs ( const char * path , struct statvfs * buf )
{
2017-12-28 22:38:20 +00:00
FilePath fp ( path ) ;
FileSystemHandle * fs = fp . fileSystem ( ) ;
if ( fs = = NULL ) {
errno = ENODEV ;
return - 1 ;
}
int err = fs - > statvfs ( fp . fileName ( ) , buf ) ;
if ( err < 0 ) {
errno = - err ;
return - 1 ;
} else {
return 0 ;
}
}
2013-08-02 16:56:11 +00:00
# if defined(TOOLCHAIN_GCC)
2013-02-18 15:32:11 +00:00
/* prevents the exception handling name demangling code getting pulled in */
2014-08-14 14:16:47 +00:00
# include "mbed_error.h"
2013-02-18 15:32:11 +00:00
namespace __gnu_cxx {
2018-06-27 14:09:15 +00:00
void __verbose_terminate_handler ( )
{
MBED_ERROR1 ( MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_CLIB_EXCEPTION ) , " Exception " , 0 ) ;
}
2013-02-18 15:32:11 +00:00
}
2013-07-29 15:54:22 +00:00
extern " C " WEAK void __cxa_pure_virtual ( void ) ;
2018-06-27 14:09:15 +00:00
extern " C " WEAK void __cxa_pure_virtual ( void )
{
2013-07-29 15:54:22 +00:00
exit ( 1 ) ;
}
2013-02-18 15:32:11 +00:00
# endif
2013-08-07 11:39:13 +00:00
2013-08-31 01:15:25 +00:00
// Provide implementation of _sbrk (low-level dynamic memory allocation
// routine) for GCC_ARM which compares new heap pointer with MSP instead of
// SP. This make it compatible with RTX RTOS thread stacks.
2019-02-13 22:19:53 +00:00
# if defined(TOOLCHAIN_GCC_ARM)
2013-08-31 01:15:25 +00:00
2019-02-07 22:47:32 +00:00
extern " C " uint32_t __end__ ;
extern " C " uint32_t __HeapLimit ;
2015-02-26 07:35:45 +00:00
2013-08-31 01:15:25 +00:00
// Turn off the errno macro and use actual global variable instead.
# undef errno
extern " C " int errno ;
2017-12-06 16:19:20 +00:00
// Weak attribute allows user to override, e.g. to use external RAM for dynamic memory.
2018-06-27 14:09:15 +00:00
extern " C " WEAK caddr_t _sbrk ( int incr )
{
2019-02-11 00:26:34 +00:00
static uint32_t heap = ( uint32_t ) & __end__ ;
uint32_t prev_heap = heap ;
uint32_t new_heap = heap + incr ;
2013-08-31 01:15:25 +00:00
2019-02-06 23:21:21 +00:00
/* __HeapLimit is end of heap section */
2019-02-21 23:20:49 +00:00
if ( new_heap > ( uint32_t ) & __HeapLimit ) {
2016-07-29 20:29:56 +00:00
errno = ENOMEM ;
2018-06-27 14:09:15 +00:00
return ( caddr_t ) - 1 ;
2016-07-29 20:29:56 +00:00
}
2019-02-11 00:26:34 +00:00
heap = new_heap ;
2013-08-31 01:15:25 +00:00
return ( caddr_t ) prev_heap ;
}
# endif
2014-12-09 13:30:34 +00:00
2019-02-13 22:19:53 +00:00
# if defined(TOOLCHAIN_GCC_ARM)
2018-06-27 14:09:15 +00:00
extern " C " void _exit ( int return_code )
{
2015-02-12 08:14:26 +00:00
# else
2015-02-16 10:10:34 +00:00
namespace std {
2018-06-27 14:09:15 +00:00
extern " C " void exit ( int return_code )
{
2015-02-12 08:14:26 +00:00
# endif
# if DEVICE_STDIO_MESSAGES
2016-09-30 22:20:37 +00:00
# if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
2015-02-12 08:14:26 +00:00
fflush ( stdout ) ;
fflush ( stderr ) ;
2018-09-10 08:15:51 +00:00
fsync ( STDOUT_FILENO ) ;
fsync ( STDERR_FILENO ) ;
2015-02-12 08:14:26 +00:00
# endif
2016-09-19 09:33:48 +00:00
# endif
2015-02-12 08:14:26 +00:00
# if DEVICE_SEMIHOST
if ( mbed_interface_connected ( ) ) {
semihost_exit ( ) ;
}
# endif
if ( return_code ) {
mbed_die ( ) ;
}
while ( 1 ) ;
}
2019-02-13 22:19:53 +00:00
# if !defined(TOOLCHAIN_GCC_ARM)
2015-02-16 10:10:34 +00:00
} //namespace std
# endif
2016-09-19 14:17:39 +00:00
# if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
2016-09-19 12:29:29 +00:00
// This series of function disable the registration of global destructors
// in a dynamic table which will be called when the application exit.
// In mbed, program never exit properly, it dies.
// More informations about this topic for ARMCC here:
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
extern " C " {
2018-06-27 14:09:15 +00:00
int __aeabi_atexit ( void * object , void ( * dtor ) ( void * /*this*/ ) , void * handle )
{
return 1 ;
}
2016-09-19 12:29:29 +00:00
2018-06-27 14:09:15 +00:00
int __cxa_atexit ( void ( * dtor ) ( void * /*this*/ ) , void * object , void * handle )
{
return 1 ;
}
2016-09-19 12:29:29 +00:00
2018-06-27 14:09:15 +00:00
void __cxa_finalize ( void * handle )
{
}
2016-09-19 12:29:29 +00:00
} // end of extern "C"
2016-09-19 14:17:39 +00:00
# endif
# if defined(TOOLCHAIN_GCC)
/*
* Depending on how newlib is configured , it is often not enough to define
* __aeabi_atexit , __cxa_atexit and __cxa_finalize in order to override the
* behavior regarding the registration of handlers with atexit .
*
* To overcome this limitation , exit and atexit are overriden here .
*/
2018-06-27 14:09:15 +00:00
extern " C " {
2016-09-19 14:17:39 +00:00
2018-06-27 14:09:15 +00:00
/**
* @ brief Retarget of exit for GCC .
* @ details Unlike the standard version , this function doesn ' t call any function
* registered with atexit before calling _exit .
*/
void __wrap_exit ( int return_code )
{
_exit ( return_code ) ;
}
2016-09-19 14:17:39 +00:00
2018-06-27 14:09:15 +00:00
/**
* @ brief Retarget atexit from GCC .
* @ details This function will always fail and never register any handler to be
* called at exit .
*/
int __wrap_atexit ( void ( * func ) ( ) )
{
return 1 ;
}
2016-09-19 14:17:39 +00:00
}
2016-09-19 12:29:29 +00:00
# endif
2015-02-12 08:14:26 +00:00
2014-12-09 13:30:34 +00:00
namespace mbed {
2018-06-27 14:09:15 +00:00
void mbed_set_unbuffered_stream ( std : : FILE * _file )
{
2014-12-09 13:30:34 +00:00
# if defined (__ICCARM__)
char buf [ 2 ] ;
2018-06-27 14:09:15 +00:00
std : : setvbuf ( _file , buf , _IONBF , NULL ) ;
2014-12-09 13:30:34 +00:00
# else
setbuf ( _file , NULL ) ;
# endif
}
2016-08-13 22:12:03 +00:00
} // namespace mbed
2016-05-21 19:46:56 +00:00
# if defined (__ICCARM__)
// Stub out locks when an rtos is not present
extern " C " WEAK void __iar_system_Mtxinit ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_system_Mtxdst ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_system_Mtxlock ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_system_Mtxunlock ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_file_Mtxinit ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_file_Mtxdst ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_file_Mtxlock ( __iar_Rmtx * mutex ) { }
extern " C " WEAK void __iar_file_Mtxunlock ( __iar_Rmtx * mutex ) { }
2017-08-22 22:17:07 +00:00
# if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
2017-11-17 19:08:14 +00:00
# pragma section="__iar_tls$$DATA"
2018-06-27 14:09:15 +00:00
extern " C " WEAK void * __aeabi_read_tp ( void )
{
// Thread Local storage is not supported, using main thread memory for errno
return __section_begin ( " __iar_tls$$DATA " ) ;
2017-11-17 19:08:14 +00:00
}
2017-08-17 20:39:12 +00:00
# endif
2016-06-12 15:29:06 +00:00
# elif defined(__CC_ARM)
// Do nothing
# elif defined (__GNUC__)
struct _reent ;
// Stub out locks when an rtos is not present
2018-06-27 14:09:15 +00:00
extern " C " WEAK void __rtos_malloc_lock ( struct _reent * _r ) { }
extern " C " WEAK void __rtos_malloc_unlock ( struct _reent * _r ) { }
extern " C " WEAK void __rtos_env_lock ( struct _reent * _r ) { }
extern " C " WEAK void __rtos_env_unlock ( struct _reent * _r ) { }
2016-06-12 15:29:06 +00:00
2018-06-27 14:09:15 +00:00
extern " C " void __malloc_lock ( struct _reent * _r )
2016-06-12 15:29:06 +00:00
{
__rtos_malloc_lock ( _r ) ;
}
2018-06-27 14:09:15 +00:00
extern " C " void __malloc_unlock ( struct _reent * _r )
2016-06-12 15:29:06 +00:00
{
__rtos_malloc_unlock ( _r ) ;
}
2018-06-27 14:09:15 +00:00
extern " C " void __env_lock ( struct _reent * _r )
2016-06-12 15:29:06 +00:00
{
__rtos_env_lock ( _r ) ;
}
2018-06-27 14:09:15 +00:00
extern " C " void __env_unlock ( struct _reent * _r )
2016-06-12 15:29:06 +00:00
{
__rtos_env_unlock ( _r ) ;
}
2016-08-26 21:05:58 +00:00
2017-12-01 16:47:18 +00:00
# endif
2019-01-29 09:53:50 +00:00
# if defined (__GNUC__) || defined (__ARMCC_VERSION)
2017-12-01 16:47:18 +00:00
2016-08-26 21:05:58 +00:00
# define CXA_GUARD_INIT_DONE (1 << 0)
# define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
# define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
extern " C " int __cxa_guard_acquire ( int * guard_object_p )
{
uint8_t * guard_object = ( uint8_t * ) guard_object_p ;
2019-01-29 09:48:40 +00:00
if ( ( core_util_atomic_load_u8 ( guard_object ) & CXA_GUARD_MASK ) = = CXA_GUARD_INIT_DONE ) {
2016-08-26 21:05:58 +00:00
return 0 ;
}
singleton_lock ( ) ;
2019-01-29 09:48:40 +00:00
uint8_t guard = * guard_object ;
if ( ( guard & CXA_GUARD_MASK ) = = CXA_GUARD_INIT_DONE ) {
2016-08-26 21:05:58 +00:00
singleton_unlock ( ) ;
return 0 ;
}
2019-01-29 09:48:40 +00:00
MBED_ASSERT ( ( guard & CXA_GUARD_MASK ) = = 0 ) ;
core_util_atomic_store_u8 ( guard_object , guard | CXA_GUARD_INIT_IN_PROGRESS ) ;
2016-08-26 21:05:58 +00:00
return 1 ;
}
extern " C " void __cxa_guard_release ( int * guard_object_p )
{
uint8_t * guard_object = ( uint8_t * ) guard_object_p ;
2019-01-29 09:48:40 +00:00
uint8_t guard = * guard_object ;
MBED_ASSERT ( ( guard & CXA_GUARD_MASK ) = = CXA_GUARD_INIT_IN_PROGRESS ) ;
core_util_atomic_store_u8 ( guard_object , ( guard & ~ CXA_GUARD_MASK ) | CXA_GUARD_INIT_DONE ) ;
2016-08-26 21:05:58 +00:00
singleton_unlock ( ) ;
}
extern " C " void __cxa_guard_abort ( int * guard_object_p )
{
uint8_t * guard_object = ( uint8_t * ) guard_object_p ;
2019-01-29 09:48:40 +00:00
uint8_t guard = * guard_object ;
MBED_ASSERT ( ( guard & CXA_GUARD_MASK ) = = CXA_GUARD_INIT_IN_PROGRESS ) ;
core_util_atomic_store_u8 ( guard_object , guard & ~ CXA_GUARD_INIT_IN_PROGRESS ) ;
2016-08-26 21:05:58 +00:00
singleton_unlock ( ) ;
}
2016-05-21 19:46:56 +00:00
# endif
2019-01-29 09:53:50 +00:00
# if defined(MBED_MEM_TRACING_ENABLED) && (defined(__ARMCC_VERSION) || defined(__ICCARM__))
2017-11-08 11:12:00 +00:00
// If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
// provide the implementation for these. Note: this needs to use the wrappers
// instead of malloc()/free() as the caller address would point to wrappers,
// not the caller of "new" or "delete".
2018-06-27 14:09:15 +00:00
extern " C " void * malloc_wrapper ( size_t size , const void * caller ) ;
extern " C " void free_wrapper ( void * ptr , const void * caller ) ;
void * operator new ( std : : size_t count )
2017-11-08 11:12:00 +00:00
{
void * buffer = malloc_wrapper ( count , MBED_CALLER_ADDR ( ) ) ;
if ( NULL = = buffer ) {
2018-05-23 17:19:09 +00:00
MBED_ERROR1 ( MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_OUT_OF_MEMORY ) , " Operator new out of memory \r \n " , count ) ;
2017-11-08 11:12:00 +00:00
}
return buffer ;
}
void * operator new [ ] ( std : : size_t count )
{
void * buffer = malloc_wrapper ( count , MBED_CALLER_ADDR ( ) ) ;
if ( NULL = = buffer ) {
error ( " Operator new[] out of memory \r \n " ) ;
}
return buffer ;
}
2018-06-27 14:09:15 +00:00
void * operator new ( std : : size_t count , const std : : nothrow_t & tag )
2017-11-08 11:12:00 +00:00
{
return malloc_wrapper ( count , MBED_CALLER_ADDR ( ) ) ;
}
2018-06-27 14:09:15 +00:00
void * operator new [ ] ( std : : size_t count , const std : : nothrow_t & tag )
2017-11-08 11:12:00 +00:00
{
return malloc_wrapper ( count , MBED_CALLER_ADDR ( ) ) ;
}
2018-06-27 14:09:15 +00:00
void operator delete ( void * ptr )
2017-11-08 11:12:00 +00:00
{
free_wrapper ( ptr , MBED_CALLER_ADDR ( ) ) ;
}
void operator delete [ ] ( void * ptr )
{
free_wrapper ( ptr , MBED_CALLER_ADDR ( ) ) ;
}
2018-10-19 20:44:46 +00:00
# elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__)
2017-11-24 14:08:28 +00:00
# include <reent.h>
2018-06-27 14:09:15 +00:00
extern " C " void * malloc_wrapper ( struct _reent * r , size_t size , void * caller ) ;
extern " C " void free_wrapper ( struct _reent * r , void * ptr , void * caller ) ;
2017-11-24 14:08:28 +00:00
2018-06-27 14:09:15 +00:00
void * operator new ( std : : size_t count )
2017-11-24 14:08:28 +00:00
{
void * buffer = malloc_wrapper ( _REENT , count , MBED_CALLER_ADDR ( ) ) ;
if ( NULL = = buffer ) {
2018-05-23 17:19:09 +00:00
MBED_ERROR1 ( MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_OUT_OF_MEMORY ) , " Operator new out of memory \r \n " , count ) ;
2017-11-24 14:08:28 +00:00
}
return buffer ;
}
void * operator new [ ] ( std : : size_t count )
{
void * buffer = malloc_wrapper ( _REENT , count , MBED_CALLER_ADDR ( ) ) ;
if ( NULL = = buffer ) {
2018-05-23 17:19:09 +00:00
MBED_ERROR1 ( MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_OUT_OF_MEMORY ) , " Operator new out of memory \r \n " , count ) ;
2017-11-24 14:08:28 +00:00
}
return buffer ;
}
2018-06-27 14:09:15 +00:00
void * operator new ( std : : size_t count , const std : : nothrow_t & tag )
2017-11-24 14:08:28 +00:00
{
return malloc_wrapper ( _REENT , count , MBED_CALLER_ADDR ( ) ) ;
}
2018-06-27 14:09:15 +00:00
void * operator new [ ] ( std : : size_t count , const std : : nothrow_t & tag )
2017-11-24 14:08:28 +00:00
{
return malloc_wrapper ( _REENT , count , MBED_CALLER_ADDR ( ) ) ;
}
2018-06-27 14:09:15 +00:00
void operator delete ( void * ptr )
2017-11-24 14:08:28 +00:00
{
free_wrapper ( _REENT , ptr , MBED_CALLER_ADDR ( ) ) ;
}
void operator delete [ ] ( void * ptr )
{
free_wrapper ( _REENT , ptr , MBED_CALLER_ADDR ( ) ) ;
}
2017-11-08 11:12:00 +00:00
# else
2017-11-24 14:08:28 +00:00
2018-06-27 14:09:15 +00:00
void * operator new ( std : : size_t count )
2016-08-01 14:07:35 +00:00
{
void * buffer = malloc ( count ) ;
if ( NULL = = buffer ) {
2018-05-23 17:19:09 +00:00
MBED_ERROR1 ( MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_OUT_OF_MEMORY ) , " Operator new out of memory \r \n " , count ) ;
2016-08-01 14:07:35 +00:00
}
return buffer ;
}
void * operator new [ ] ( std : : size_t count )
{
void * buffer = malloc ( count ) ;
if ( NULL = = buffer ) {
2018-05-23 17:19:09 +00:00
MBED_ERROR1 ( MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_OUT_OF_MEMORY ) , " Operator new[] out of memory \r \n " , count ) ;
2016-08-01 14:07:35 +00:00
}
return buffer ;
}
2018-06-27 14:09:15 +00:00
void * operator new ( std : : size_t count , const std : : nothrow_t & tag )
2017-09-21 17:37:25 +00:00
{
return malloc ( count ) ;
}
2018-06-27 14:09:15 +00:00
void * operator new [ ] ( std : : size_t count , const std : : nothrow_t & tag )
2017-09-21 17:37:25 +00:00
{
return malloc ( count ) ;
}
2018-06-27 14:09:15 +00:00
void operator delete ( void * ptr )
2016-08-01 14:07:35 +00:00
{
2017-11-24 08:23:23 +00:00
free ( ptr ) ;
2016-08-01 14:07:35 +00:00
}
void operator delete [ ] ( void * ptr )
{
2017-11-24 08:23:23 +00:00
free ( ptr ) ;
2016-08-01 14:07:35 +00:00
}
2017-09-14 10:07:51 +00:00
2017-11-08 11:12:00 +00:00
# endif
2017-09-14 10:07:51 +00:00
/* @brief standard c library clock() function.
*
* This function returns the number of clock ticks elapsed since the start of the program .
*
* @ note Synchronization level : Thread safe
*
* @ return
* the number of clock ticks elapsed since the start of the program .
*
* */
extern " C " clock_t clock ( )
{
_mutex - > lock ( ) ;
2017-09-25 20:43:02 +00:00
clock_t t = ticker_read ( get_us_ticker_data ( ) ) ;
2017-09-14 10:07:51 +00:00
t / = 1000000 / CLOCKS_PER_SEC ; // convert to processor time
_mutex - > unlock ( ) ;
return t ;
}
2017-09-19 18:58:34 +00:00
// temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info
2018-06-27 14:09:15 +00:00
MBED_WEAK const ticker_info_t * us_ticker_get_info ( )
2017-09-19 18:58:34 +00:00
{
static const ticker_info_t info = {
1000000 ,
32
} ;
return & info ;
}
// temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info
2018-06-27 14:09:15 +00:00
MBED_WEAK const ticker_info_t * lp_ticker_get_info ( )
2017-09-19 18:58:34 +00:00
{
static const ticker_info_t info = {
1000000 ,
32
} ;
return & info ;
}