mirror of https://github.com/ARMmbed/mbed-os.git
mbed_retarget: Add a minimal console implementation to provide basic functionalities
The retarget code allocates an array of FileHandle* for console and file handling (filehandles). A tiny target only needs a console (putc/getc). There is no need for file handling. The POSIX layer and the array of FileHandle* is not required for small targets that only need a console ; this code is optionally compiled out if the configuration parameter platform.stdio-minimal-console-only is set to `"true"`.pull/11796/head
parent
734072ffc3
commit
051991fafb
|
@ -45,6 +45,7 @@ public:
|
||||||
Stream(const char *name = NULL);
|
Stream(const char *name = NULL);
|
||||||
virtual ~Stream();
|
virtual ~Stream();
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
int putc(int c);
|
int putc(int c);
|
||||||
int puts(const char *s);
|
int puts(const char *s);
|
||||||
int getc();
|
int getc();
|
||||||
|
@ -59,7 +60,7 @@ public:
|
||||||
return _file;
|
return _file;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
virtual int close();
|
virtual int close();
|
||||||
virtual ssize_t write(const void *buffer, size_t length);
|
virtual ssize_t write(const void *buffer, size_t length);
|
||||||
virtual ssize_t read(void *buffer, size_t length);
|
virtual ssize_t read(void *buffer, size_t length);
|
||||||
|
@ -70,10 +71,13 @@ protected:
|
||||||
virtual int sync();
|
virtual int sync();
|
||||||
virtual off_t size();
|
virtual off_t size();
|
||||||
|
|
||||||
|
protected:
|
||||||
virtual int _putc(int c) = 0;
|
virtual int _putc(int c) = 0;
|
||||||
virtual int _getc() = 0;
|
virtual int _getc() = 0;
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
std::FILE *_file;
|
std::FILE *_file;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
/** Acquire exclusive access to this object.
|
/** Acquire exclusive access to this object.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -373,7 +373,7 @@ private:
|
||||||
template <class Callable, class... Args>
|
template <class Callable, class... Args>
|
||||||
void call_once(once_flag &flag, Callable&& f, Args&&... args)
|
void call_once(once_flag &flag, Callable&& f, Args&&... args)
|
||||||
{
|
{
|
||||||
if (!(core_util_atomic_load_explicit(&flag.__guard, mbed_memory_order_acquire) & 1)) {
|
if (!(core_util_atomic_load_explicit((uint8_t *)&flag.__guard, mbed_memory_order_acquire) & 1)) {
|
||||||
if (__cxa_guard_acquire(&flag.__guard)) {
|
if (__cxa_guard_acquire(&flag.__guard)) {
|
||||||
mstd::invoke(mstd::forward<Callable>(f), mstd::forward<Args>(args)...);
|
mstd::invoke(mstd::forward<Callable>(f), mstd::forward<Args>(args)...);
|
||||||
__cxa_guard_release(&flag.__guard);
|
__cxa_guard_release(&flag.__guard);
|
||||||
|
|
|
@ -12,7 +12,12 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
"stdio-buffered-serial": {
|
"stdio-buffered-serial": {
|
||||||
"help": "(Applies if target.console-uart is true.) Use UARTSerial driver to obtain buffered serial I/O on stdin/stdout/stderr. If false, unbuffered serial_getc and serial_putc are used directly.",
|
"help": "(Applies if target.console-uart is true and stdio-minimal-console-only is false.) Use UARTSerial driver to obtain buffered serial I/O on stdin/stdout/stderr. If false, unbuffered serial_getc and serial_putc are used directly.",
|
||||||
|
"value": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"stdio-minimal-console-only": {
|
||||||
|
"help": "(Ignores stdio-buffered-serial) Creates a console for basic unbuffered I/O operations. Enable if your application does not require file handles to access the serial interface. The POSIX `fsync` function will always an error.",
|
||||||
"value": false
|
"value": false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ typedef unsigned int gid_t; ///< Group ID
|
||||||
/** \addtogroup platform-public-api */
|
/** \addtogroup platform-public-api */
|
||||||
/** @{*/
|
/** @{*/
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
/**
|
/**
|
||||||
* \defgroup platform_retarget Retarget functions
|
* \defgroup platform_retarget Retarget functions
|
||||||
* @{
|
* @{
|
||||||
|
@ -90,7 +91,6 @@ typedef unsigned int gid_t; ///< Group ID
|
||||||
/* DIR declarations must also be here */
|
/* DIR declarations must also be here */
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
namespace mbed {
|
namespace mbed {
|
||||||
|
|
||||||
class FileHandle;
|
class FileHandle;
|
||||||
class DirHandle;
|
class DirHandle;
|
||||||
|
|
||||||
|
@ -185,6 +185,7 @@ typedef mbed::DirHandle DIR;
|
||||||
#else
|
#else
|
||||||
typedef struct Dir DIR;
|
typedef struct Dir DIR;
|
||||||
#endif
|
#endif
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
/* The intent of this section is to unify the errno error values to match
|
/* The intent of this section is to unify the errno error values to match
|
||||||
* the POSIX definitions for the GCC_ARM, ARMCC and IAR compilers. This is
|
* the POSIX definitions for the GCC_ARM, ARMCC and IAR compilers. This is
|
||||||
|
@ -559,6 +560,7 @@ struct pollfd {
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
int open(const char *path, int oflag, ...);
|
int open(const char *path, int oflag, ...);
|
||||||
#ifndef __IAR_SYSTEMS_ICC__ /* IAR provides fdopen itself */
|
#ifndef __IAR_SYSTEMS_ICC__ /* IAR provides fdopen itself */
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
@ -567,12 +569,14 @@ extern "C" {
|
||||||
FILE *fdopen(int fildes, const char *mode);
|
FILE *fdopen(int fildes, const char *mode);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
ssize_t write(int fildes, const void *buf, size_t nbyte);
|
ssize_t write(int fildes, const void *buf, size_t nbyte);
|
||||||
ssize_t read(int fildes, void *buf, size_t nbyte);
|
ssize_t read(int fildes, void *buf, size_t nbyte);
|
||||||
|
int fsync(int fildes);
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
off_t lseek(int fildes, off_t offset, int whence);
|
off_t lseek(int fildes, off_t offset, int whence);
|
||||||
int ftruncate(int fildes, off_t length);
|
int ftruncate(int fildes, off_t length);
|
||||||
int isatty(int fildes);
|
int isatty(int fildes);
|
||||||
int fsync(int fildes);
|
|
||||||
int fstat(int fildes, struct stat *st);
|
int fstat(int fildes, struct stat *st);
|
||||||
int fcntl(int fildes, int cmd, ...);
|
int fcntl(int fildes, int cmd, ...);
|
||||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||||
|
@ -586,11 +590,12 @@ extern "C" {
|
||||||
long telldir(DIR *);
|
long telldir(DIR *);
|
||||||
void seekdir(DIR *, long);
|
void seekdir(DIR *, long);
|
||||||
int mkdir(const char *name, mode_t n);
|
int mkdir(const char *name, mode_t n);
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}; // extern "C"
|
}; // extern "C"
|
||||||
|
|
||||||
namespace mbed {
|
namespace mbed {
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
/** This call is an analogue to POSIX fdopen().
|
/** This call is an analogue to POSIX fdopen().
|
||||||
*
|
*
|
||||||
* It associates a C stream to an already-opened FileHandle, to allow you to
|
* It associates a C stream to an already-opened FileHandle, to allow you to
|
||||||
|
@ -619,6 +624,33 @@ std::FILE *fdopen(mbed::FileHandle *fh, const char *mode);
|
||||||
*/
|
*/
|
||||||
int bind_to_fd(mbed::FileHandle *fh);
|
int bind_to_fd(mbed::FileHandle *fh);
|
||||||
|
|
||||||
|
#else
|
||||||
|
/** Targets may implement this to override how to write to the console.
|
||||||
|
*
|
||||||
|
* If the target has provided minimal_console_putc, this is called
|
||||||
|
* to give the target a chance to specify an alternative minimal console.
|
||||||
|
*
|
||||||
|
* If this is not provided, serial_putc will be used if
|
||||||
|
* `target.console-uart` is `true`, else there will not be an output.
|
||||||
|
*
|
||||||
|
* @param c The char to write
|
||||||
|
* @return The written char
|
||||||
|
*/
|
||||||
|
int minimal_console_putc(int c);
|
||||||
|
|
||||||
|
/** Targets may implement this to override how to read from the console.
|
||||||
|
*
|
||||||
|
* If the target has provided minimal_console_getc, this is called
|
||||||
|
* to give the target a chance to specify an alternative minimal console.
|
||||||
|
*
|
||||||
|
* If this is not provided, serial_getc will be used if
|
||||||
|
* `target.console-uart` is `true`, else no input would be captured.
|
||||||
|
*
|
||||||
|
* @return The char read from the serial port
|
||||||
|
*/
|
||||||
|
int minimal_console_getc();
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
} // namespace mbed
|
} // namespace mbed
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
|
@ -20,9 +20,14 @@
|
||||||
|
|
||||||
namespace mbed {
|
namespace mbed {
|
||||||
|
|
||||||
Stream::Stream(const char *name) : FileLike(name), _file(NULL)
|
Stream::Stream(const char *name) :
|
||||||
|
FileLike(name)
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
, _file(NULL)
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
{
|
{
|
||||||
// No lock needed in constructor
|
// No lock needed in constructor
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
/* open ourselves */
|
/* open ourselves */
|
||||||
_file = fdopen(this, "w+");
|
_file = fdopen(this, "w+");
|
||||||
// fdopen() will make us buffered because Stream::isatty()
|
// fdopen() will make us buffered because Stream::isatty()
|
||||||
|
@ -33,14 +38,18 @@ Stream::Stream(const char *name) : FileLike(name), _file(NULL)
|
||||||
} else {
|
} else {
|
||||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED), "Stream obj failure", _file);
|
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED), "Stream obj failure", _file);
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream::~Stream()
|
Stream::~Stream()
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
// No lock can be used in destructor
|
// No lock can be used in destructor
|
||||||
fclose(_file);
|
fclose(_file);
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
int Stream::putc(int c)
|
int Stream::putc(int c)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
@ -73,6 +82,7 @@ char *Stream::gets(char *s, int size)
|
||||||
unlock();
|
unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
int Stream::close()
|
int Stream::close()
|
||||||
{
|
{
|
||||||
|
@ -142,6 +152,8 @@ off_t Stream::size()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
int Stream::printf(const char *format, ...)
|
int Stream::printf(const char *format, ...)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
@ -184,4 +196,6 @@ int Stream::vscanf(const char *format, std::va_list args)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
} // namespace mbed
|
} // namespace mbed
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <mstd_mutex>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#include "platform/FilePath.h"
|
#include "platform/FilePath.h"
|
||||||
|
@ -75,6 +76,12 @@ asm(" .global __use_full_stdio\n");
|
||||||
# define PREFIX(x) x
|
# define PREFIX(x) x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
# define RETARGET_OPEN_MAX OPEN_MAX
|
||||||
|
#else
|
||||||
|
# define RETARGET_OPEN_MAX 3
|
||||||
|
#endif // MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
#define FILE_HANDLE_RESERVED ((FileHandle*)0xFFFFFFFF)
|
#define FILE_HANDLE_RESERVED ((FileHandle*)0xFFFFFFFF)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,20 +111,25 @@ extern const char __stderr_name[] = "/stderr";
|
||||||
unsigned char *mbed_heap_start = 0;
|
unsigned char *mbed_heap_start = 0;
|
||||||
uint32_t mbed_heap_size = 0;
|
uint32_t mbed_heap_size = 0;
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
/* newlib has the filehandle field in the FILE struct as a short, so
|
/* 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
|
* 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
|
* put it in a filehandles array and return the index into that array
|
||||||
*/
|
*/
|
||||||
static FileHandle *filehandles[OPEN_MAX] = { FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED };
|
static FileHandle *filehandles[RETARGET_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];
|
|
||||||
static SingletonPtr<PlatformMutex> filehandle_mutex;
|
static SingletonPtr<PlatformMutex> filehandle_mutex;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
|
static char stdio_in_prev[RETARGET_OPEN_MAX];
|
||||||
|
static char stdio_out_prev[RETARGET_OPEN_MAX];
|
||||||
|
|
||||||
namespace mbed {
|
namespace mbed {
|
||||||
void mbed_set_unbuffered_stream(std::FILE *_file);
|
void mbed_set_unbuffered_stream(std::FILE *_file);
|
||||||
|
|
||||||
void remove_filehandle(FileHandle *file)
|
void remove_filehandle(FileHandle *file)
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
filehandle_mutex->lock();
|
filehandle_mutex->lock();
|
||||||
/* Remove all open filehandles for this */
|
/* Remove all open filehandles for this */
|
||||||
for (unsigned int fh_i = 0; fh_i < sizeof(filehandles) / sizeof(*filehandles); fh_i++) {
|
for (unsigned int fh_i = 0; fh_i < sizeof(filehandles) / sizeof(*filehandles); fh_i++) {
|
||||||
|
@ -126,6 +138,7 @@ void remove_filehandle(FileHandle *file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filehandle_mutex->unlock();
|
filehandle_mutex->unlock();
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +221,36 @@ short DirectSerial::poll(short events) const
|
||||||
}
|
}
|
||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
# if MBED_CONF_TARGET_CONSOLE_UART
|
||||||
|
|
||||||
|
static void do_serial_init()
|
||||||
|
{
|
||||||
|
if (stdio_uart_inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
|
||||||
|
serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
|
||||||
|
#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
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_serial_init_once()
|
||||||
|
{
|
||||||
|
static mstd::once_flag once;
|
||||||
|
mstd::call_once(once, do_serial_init);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MBED_CONF_TARGET_CONSOLE_UART
|
||||||
|
#endif // MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
|
#endif // DEVICE_SERIAL
|
||||||
|
|
||||||
class Sink : public FileHandle {
|
class Sink : public FileHandle {
|
||||||
public:
|
public:
|
||||||
|
@ -247,7 +289,7 @@ ssize_t Sink::read(void *buffer, size_t size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
MBED_WEAK FileHandle *mbed::mbed_target_override_console(int fd)
|
MBED_WEAK FileHandle *mbed::mbed_target_override_console(int fd)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -292,11 +334,14 @@ static FileHandle *get_console(int fd)
|
||||||
}
|
}
|
||||||
return default_console();
|
return default_console();
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
|
namespace mbed {
|
||||||
/* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
|
/* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
|
||||||
FileHandle *mbed::mbed_file_handle(int fd)
|
FileHandle *mbed_file_handle(int fd)
|
||||||
{
|
{
|
||||||
if (fd >= OPEN_MAX) {
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
if (fd >= RETARGET_OPEN_MAX) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
FileHandle *fh = filehandles[fd];
|
FileHandle *fh = filehandles[fd];
|
||||||
|
@ -304,8 +349,14 @@ FileHandle *mbed::mbed_file_handle(int fd)
|
||||||
filehandles[fd] = fh = get_console(fd);
|
filehandles[fd] = fh = get_console(fd);
|
||||||
}
|
}
|
||||||
return fh;
|
return fh;
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
/**
|
/**
|
||||||
* Sets errno when file opening fails.
|
* Sets errno when file opening fails.
|
||||||
* Wipes out the filehandle too.
|
* Wipes out the filehandle too.
|
||||||
|
@ -374,13 +425,13 @@ static int reserve_filehandle()
|
||||||
// find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr
|
// find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr
|
||||||
filehandle_mutex->lock();
|
filehandle_mutex->lock();
|
||||||
int fh_i;
|
int fh_i;
|
||||||
for (fh_i = 3; fh_i < OPEN_MAX; fh_i++) {
|
for (fh_i = 3; fh_i < RETARGET_OPEN_MAX; fh_i++) {
|
||||||
/* Take a next free filehandle slot available. */
|
/* Take a next free filehandle slot available. */
|
||||||
if (filehandles[fh_i] == NULL) {
|
if (filehandles[fh_i] == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fh_i >= OPEN_MAX) {
|
if (fh_i >= RETARGET_OPEN_MAX) {
|
||||||
/* Too many file handles have been opened */
|
/* Too many file handles have been opened */
|
||||||
errno = EMFILE;
|
errno = EMFILE;
|
||||||
filehandle_mutex->unlock();
|
filehandle_mutex->unlock();
|
||||||
|
@ -392,6 +443,7 @@ static int reserve_filehandle()
|
||||||
return fh_i;
|
return fh_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mbed::bind_to_fd(FileHandle *fh)
|
int mbed::bind_to_fd(FileHandle *fh)
|
||||||
{
|
{
|
||||||
int fildes = reserve_filehandle();
|
int fildes = reserve_filehandle();
|
||||||
|
@ -455,6 +507,8 @@ std::FILE *fdopen(FileHandle *fh, const char *mode)
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
|
|
||||||
/* @brief standard c library fopen() retargeting function.
|
/* @brief standard c library fopen() retargeting function.
|
||||||
*
|
*
|
||||||
|
@ -508,16 +562,23 @@ extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef __IAR_SYSTEMS_ICC__
|
#ifndef __IAR_SYSTEMS_ICC__
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
/* FILENAME: "@(integer)" gives an already-allocated descriptor */
|
/* FILENAME: "@(integer)" gives an already-allocated descriptor */
|
||||||
if (name[0] == '@') {
|
if (name[0] == '@') {
|
||||||
int fd;
|
int fd;
|
||||||
memcpy(&fd, name + 1, sizeof fd);
|
memcpy(&fd, name + 1, sizeof fd);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
#endif
|
#endif
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
return open(name, openflags_to_posix(openflags));
|
return open(name, openflags_to_posix(openflags));
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
extern "C" int open(const char *name, int oflag, ...)
|
extern "C" int open(const char *name, int oflag, ...)
|
||||||
{
|
{
|
||||||
int fildes = reserve_filehandle();
|
int fildes = reserve_filehandle();
|
||||||
|
@ -554,12 +615,18 @@ extern "C" int open(const char *name, int oflag, ...)
|
||||||
|
|
||||||
return fildes;
|
return fildes;
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
extern "C" int PREFIX(_close)(FILEHANDLE fh)
|
extern "C" int PREFIX(_close)(FILEHANDLE fh)
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
return close(fh);
|
return close(fh);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
extern "C" int close(int fildes)
|
extern "C" int close(int fildes)
|
||||||
{
|
{
|
||||||
FileHandle *fhc = mbed_file_handle(fildes);
|
FileHandle *fhc = mbed_file_handle(fildes);
|
||||||
|
@ -577,6 +644,7 @@ extern "C" int close(int fildes)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
static bool convert_crlf(int fd)
|
static bool convert_crlf(int fd)
|
||||||
{
|
{
|
||||||
|
@ -673,7 +741,20 @@ finish:
|
||||||
|
|
||||||
extern "C" ssize_t write(int fildes, const void *buf, size_t length)
|
extern "C" ssize_t write(int fildes, const void *buf, size_t length)
|
||||||
{
|
{
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
if (fildes != STDOUT_FILENO && fildes != STDERR_FILENO) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char *buffer = static_cast<const unsigned char *>(buf);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
mbed::minimal_console_putc(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t ret = length;
|
||||||
|
#else
|
||||||
FileHandle *fhc = mbed_file_handle(fildes);
|
FileHandle *fhc = mbed_file_handle(fildes);
|
||||||
if (fhc == NULL) {
|
if (fhc == NULL) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
|
@ -681,6 +762,7 @@ extern "C" ssize_t write(int fildes, const void *buf, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ret = fhc->write(buf, length);
|
ssize_t ret = fhc->write(buf, length);
|
||||||
|
#endif // MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
errno = -ret;
|
errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -689,6 +771,18 @@ extern "C" ssize_t write(int fildes, const void *buf, size_t length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
/* Write one character to a serial interface */
|
||||||
|
MBED_WEAK int mbed::minimal_console_putc(int c)
|
||||||
|
{
|
||||||
|
#if MBED_CONF_TARGET_CONSOLE_UART && DEVICE_SERIAL
|
||||||
|
do_serial_init_once();
|
||||||
|
serial_putc(&stdio_uart, c);
|
||||||
|
#endif // MBED_CONF_TARGET_CONSOLE_UART && DEVICE_SERIAL
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
#endif // MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
extern "C" void PREFIX(_exit)(int return_code)
|
extern "C" void PREFIX(_exit)(int return_code)
|
||||||
{
|
{
|
||||||
|
@ -768,6 +862,23 @@ extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int
|
||||||
|
|
||||||
extern "C" ssize_t read(int fildes, void *buf, size_t length)
|
extern "C" ssize_t read(int fildes, void *buf, size_t length)
|
||||||
{
|
{
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
if (fildes != STDIN_FILENO && fildes != STDERR_FILENO) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *buffer = static_cast<unsigned char *>(buf);
|
||||||
|
|
||||||
|
buf[0] = minimal_console_getc();
|
||||||
|
|
||||||
|
ssize_t ret = 1;
|
||||||
|
|
||||||
|
#else
|
||||||
FileHandle *fhc = mbed_file_handle(fildes);
|
FileHandle *fhc = mbed_file_handle(fildes);
|
||||||
if (fhc == NULL) {
|
if (fhc == NULL) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
|
@ -775,6 +886,7 @@ extern "C" ssize_t read(int fildes, void *buf, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ret = fhc->read(buf, length);
|
ssize_t ret = fhc->read(buf, length);
|
||||||
|
#endif // MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
errno = -ret;
|
errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -783,6 +895,19 @@ extern "C" ssize_t read(int fildes, void *buf, size_t length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
/* Read a character from the serial interface */
|
||||||
|
MBED_WEAK int mbed::minimal_console_getc()
|
||||||
|
{
|
||||||
|
#if MBED_CONF_TARGET_CONSOLE_UART && DEVICE_SERIAL
|
||||||
|
do_serial_init_once();
|
||||||
|
return serial_getc(&stdio_uart);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif // MBED_CONF_TARGET_CONSOLE_UART && DEVICE_SERIAL
|
||||||
|
}
|
||||||
|
#endif // MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ARMCC_VERSION
|
#ifdef __ARMCC_VERSION
|
||||||
extern "C" int PREFIX(_istty)(FILEHANDLE fh)
|
extern "C" int PREFIX(_istty)(FILEHANDLE fh)
|
||||||
|
@ -790,9 +915,15 @@ extern "C" int PREFIX(_istty)(FILEHANDLE fh)
|
||||||
extern "C" int _isatty(FILEHANDLE fh)
|
extern "C" int _isatty(FILEHANDLE fh)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
return isatty(fh);
|
return isatty(fh);
|
||||||
|
#else
|
||||||
|
// Is attached to an interactive device
|
||||||
|
return 1;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
extern "C" int isatty(int fildes)
|
extern "C" int isatty(int fildes)
|
||||||
{
|
{
|
||||||
FileHandle *fhc = mbed_file_handle(fildes);
|
FileHandle *fhc = mbed_file_handle(fildes);
|
||||||
|
@ -809,6 +940,7 @@ extern "C" int isatty(int fildes)
|
||||||
return tty;
|
return tty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
#if defined(__ARMCC_VERSION)
|
#if defined(__ARMCC_VERSION)
|
||||||
|
@ -819,6 +951,7 @@ long __lseek(int fh, long offset, int whence)
|
||||||
int _lseek(FILEHANDLE fh, int offset, int whence)
|
int _lseek(FILEHANDLE fh, int offset, int whence)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
#if defined(__ARMCC_VERSION)
|
#if defined(__ARMCC_VERSION)
|
||||||
int whence = SEEK_SET;
|
int whence = SEEK_SET;
|
||||||
#endif
|
#endif
|
||||||
|
@ -832,8 +965,13 @@ int _lseek(FILEHANDLE fh, int offset, int whence)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return off;
|
return off;
|
||||||
|
#else
|
||||||
|
// Not supported
|
||||||
|
return -1;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
extern "C" off_t lseek(int fildes, off_t offset, int whence)
|
extern "C" off_t lseek(int fildes, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
FileHandle *fhc = mbed_file_handle(fildes);
|
FileHandle *fhc = mbed_file_handle(fildes);
|
||||||
|
@ -873,9 +1011,11 @@ extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
|
||||||
return fsync(fh);
|
return fsync(fh);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
extern "C" int fsync(int fildes)
|
extern "C" int fsync(int fildes)
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
FileHandle *fhc = mbed_file_handle(fildes);
|
FileHandle *fhc = mbed_file_handle(fildes);
|
||||||
if (fhc == NULL) {
|
if (fhc == NULL) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
|
@ -889,11 +1029,16 @@ extern "C" int fsync(int fildes)
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ARMCC_VERSION
|
#ifdef __ARMCC_VERSION
|
||||||
extern "C" long PREFIX(_flen)(FILEHANDLE fh)
|
extern "C" long PREFIX(_flen)(FILEHANDLE fh)
|
||||||
{
|
{
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
FileHandle *fhc = mbed_file_handle(fh);
|
FileHandle *fhc = mbed_file_handle(fh);
|
||||||
if (fhc == NULL) {
|
if (fhc == NULL) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
|
@ -910,6 +1055,10 @@ extern "C" long PREFIX(_flen)(FILEHANDLE fh)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
|
#else
|
||||||
|
// Not supported
|
||||||
|
return -1;
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not compile this code for TFM secure target
|
// Do not compile this code for TFM secure target
|
||||||
|
@ -983,7 +1132,7 @@ extern "C" __value_in_regs struct __initial_stackheap __user_setup_stackheap(uin
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
#if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
|
#if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
|
||||||
extern "C" int _fstat(int fh, struct stat *st)
|
extern "C" int _fstat(int fh, struct stat *st)
|
||||||
{
|
{
|
||||||
|
@ -1042,12 +1191,12 @@ extern "C" int fcntl(int fildes, int cmd, ...)
|
||||||
|
|
||||||
extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||||
{
|
{
|
||||||
if (nfds > OPEN_MAX) {
|
if (nfds > RETARGET_OPEN_MAX) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mbed::pollfh fhs[OPEN_MAX];
|
struct mbed::pollfh fhs[RETARGET_OPEN_MAX];
|
||||||
for (nfds_t n = 0; n < nfds; n++) {
|
for (nfds_t n = 0; n < nfds; n++) {
|
||||||
// Underlying FileHandle poll returns POLLNVAL if given NULL, so
|
// Underlying FileHandle poll returns POLLNVAL if given NULL, so
|
||||||
// we don't need to take special action.
|
// we don't need to take special action.
|
||||||
|
@ -1060,6 +1209,7 @@ extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
extern "C" int remove(const char *path)
|
extern "C" int remove(const char *path)
|
||||||
|
@ -1127,6 +1277,7 @@ extern "C" char *_sys_command_string(char *cmd, int len)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
extern "C" DIR *opendir(const char *path)
|
extern "C" DIR *opendir(const char *path)
|
||||||
{
|
{
|
||||||
FilePath fp(path);
|
FilePath fp(path);
|
||||||
|
@ -1239,6 +1390,7 @@ extern "C" int statvfs(const char *path, struct statvfs *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY
|
||||||
|
|
||||||
#if defined(TOOLCHAIN_GCC)
|
#if defined(TOOLCHAIN_GCC)
|
||||||
/* prevents the exception handling name demangling code getting pulled in */
|
/* prevents the exception handling name demangling code getting pulled in */
|
||||||
|
|
|
@ -110,4 +110,5 @@ pppd
|
||||||
pppdebug
|
pppdebug
|
||||||
ppp
|
ppp
|
||||||
api
|
api
|
||||||
|
uart
|
||||||
_doxy_
|
_doxy_
|
||||||
|
|
Loading…
Reference in New Issue