mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #9797 from ARMmbed/fh_enable
API to temporarily enable/disable FileHandlespull/9965/head
commit
596b9f740e
|
@ -120,6 +120,16 @@ void UARTSerial::tx_irq(void)
|
|||
{
|
||||
}
|
||||
|
||||
int UARTSerial::enable_input(bool enabled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UARTSerial::enable_output(bool enabled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UARTSerial::wait_ms(uint32_t millisec)
|
||||
{
|
||||
|
||||
|
|
|
@ -32,11 +32,13 @@ UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) :
|
|||
SerialBase(tx, rx, baud),
|
||||
_blocking(true),
|
||||
_tx_irq_enabled(false),
|
||||
_rx_irq_enabled(true),
|
||||
_rx_irq_enabled(false),
|
||||
_tx_enabled(true),
|
||||
_rx_enabled(true),
|
||||
_dcd_irq(NULL)
|
||||
{
|
||||
/* Attatch IRQ routines to the serial device. */
|
||||
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
|
||||
enable_rx_irq();
|
||||
}
|
||||
|
||||
UARTSerial::~UARTSerial()
|
||||
|
@ -188,11 +190,10 @@ ssize_t UARTSerial::write(const void *buffer, size_t length)
|
|||
}
|
||||
|
||||
core_util_critical_section_enter();
|
||||
if (!_tx_irq_enabled) {
|
||||
if (_tx_enabled && !_tx_irq_enabled) {
|
||||
UARTSerial::tx_irq(); // only write to hardware in one place
|
||||
if (!_txbuf.empty()) {
|
||||
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
|
||||
_tx_irq_enabled = true;
|
||||
enable_tx_irq();
|
||||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
@ -231,11 +232,10 @@ ssize_t UARTSerial::read(void *buffer, size_t length)
|
|||
}
|
||||
|
||||
core_util_critical_section_enter();
|
||||
if (!_rx_irq_enabled) {
|
||||
if (_rx_enabled && !_rx_irq_enabled) {
|
||||
UARTSerial::rx_irq(); // only read from hardware in one place
|
||||
if (!_rxbuf.full()) {
|
||||
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
|
||||
_rx_irq_enabled = true;
|
||||
enable_rx_irq();
|
||||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
@ -314,8 +314,7 @@ void UARTSerial::rx_irq(void)
|
|||
}
|
||||
|
||||
if (_rx_irq_enabled && _rxbuf.full()) {
|
||||
SerialBase::attach(NULL, RxIrq);
|
||||
_rx_irq_enabled = false;
|
||||
disable_rx_irq();
|
||||
}
|
||||
|
||||
/* Report the File handler that data is ready to be read from the buffer. */
|
||||
|
@ -337,8 +336,7 @@ void UARTSerial::tx_irq(void)
|
|||
}
|
||||
|
||||
if (_tx_irq_enabled && _txbuf.empty()) {
|
||||
SerialBase::attach(NULL, TxIrq);
|
||||
_tx_irq_enabled = false;
|
||||
disable_tx_irq();
|
||||
}
|
||||
|
||||
/* Report the File handler that data can be written to peripheral. */
|
||||
|
@ -347,6 +345,69 @@ void UARTSerial::tx_irq(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* These are all called from critical section */
|
||||
void UARTSerial::enable_rx_irq()
|
||||
{
|
||||
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
|
||||
_rx_irq_enabled = true;
|
||||
}
|
||||
|
||||
void UARTSerial::disable_rx_irq()
|
||||
{
|
||||
SerialBase::attach(NULL, RxIrq);
|
||||
_rx_irq_enabled = false;
|
||||
}
|
||||
|
||||
void UARTSerial::enable_tx_irq()
|
||||
{
|
||||
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
|
||||
_tx_irq_enabled = true;
|
||||
}
|
||||
|
||||
void UARTSerial::disable_tx_irq()
|
||||
{
|
||||
SerialBase::attach(NULL, TxIrq);
|
||||
_tx_irq_enabled = false;
|
||||
}
|
||||
|
||||
int UARTSerial::enable_input(bool enabled)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (_rx_enabled != enabled) {
|
||||
if (enabled) {
|
||||
UARTSerial::rx_irq();
|
||||
if (!_rxbuf.full()) {
|
||||
enable_rx_irq();
|
||||
}
|
||||
} else {
|
||||
disable_rx_irq();
|
||||
}
|
||||
_rx_enabled = enabled;
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UARTSerial::enable_output(bool enabled)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (_tx_enabled != enabled) {
|
||||
if (enabled) {
|
||||
UARTSerial::tx_irq();
|
||||
if (!_txbuf.empty()) {
|
||||
enable_tx_irq();
|
||||
}
|
||||
} else {
|
||||
disable_tx_irq();
|
||||
}
|
||||
_tx_enabled = enabled;
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UARTSerial::wait_ms(uint32_t millisec)
|
||||
{
|
||||
/* wait_ms implementation for RTOS spins until exact microseconds - we
|
||||
|
|
|
@ -152,6 +152,36 @@ public:
|
|||
return _blocking;
|
||||
}
|
||||
|
||||
/** Enable or disable input
|
||||
*
|
||||
* Control enabling of device for input. This is primarily intended
|
||||
* for temporary power-saving; the overall ability of the device to operate for
|
||||
* input and/or output may be fixed at creation time, but this call can
|
||||
* allow input to be temporarily disabled to permit power saving without
|
||||
* losing device state.
|
||||
*
|
||||
* @param enabled true to enable input, false to disable.
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return Negative error code on failure
|
||||
*/
|
||||
virtual int enable_input(bool enabled);
|
||||
|
||||
/** Enable or disable output
|
||||
*
|
||||
* Control enabling of device for output. This is primarily intended
|
||||
* for temporary power-saving; the overall ability of the device to operate for
|
||||
* input and/or output may be fixed at creation time, but this call can
|
||||
* allow output to be temporarily disabled to permit power saving without
|
||||
* losing device state.
|
||||
*
|
||||
* @param enabled true to enable output, false to disable.
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return Negative error code on failure
|
||||
*/
|
||||
virtual int enable_output(bool enabled);
|
||||
|
||||
/** Register a callback on state change of the file.
|
||||
*
|
||||
* The specified callback will be called on state changes such as when
|
||||
|
@ -242,6 +272,11 @@ private:
|
|||
/** Unbuffered write - invoked when write called from critical section */
|
||||
ssize_t write_unbuffered(const char *buf_ptr, size_t length);
|
||||
|
||||
void enable_rx_irq();
|
||||
void disable_rx_irq();
|
||||
void enable_tx_irq();
|
||||
void disable_tx_irq();
|
||||
|
||||
/** Software serial buffers
|
||||
* By default buffer size is 256 for TX and 256 for RX. Configurable through mbed_app.json
|
||||
*/
|
||||
|
@ -255,6 +290,8 @@ private:
|
|||
bool _blocking;
|
||||
bool _tx_irq_enabled;
|
||||
bool _rx_irq_enabled;
|
||||
bool _tx_enabled;
|
||||
bool _rx_enabled;
|
||||
InterruptIn *_dcd_irq;
|
||||
|
||||
/** Device Hanged up
|
||||
|
|
|
@ -220,6 +220,42 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Enable or disable input
|
||||
*
|
||||
* Control enabling of device for input. This is primarily intended
|
||||
* for temporary power-saving; the overall ability of the device to operate for
|
||||
* input and/or output may be fixed at creation time, but this call can
|
||||
* allow input to be temporarily disabled to permit power saving without
|
||||
* losing device state.
|
||||
*
|
||||
* @param enabled true to enable input, false to disable.
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return Negative error code on failure
|
||||
*/
|
||||
virtual int enable_input(bool enabled)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/** Enable or disable output
|
||||
*
|
||||
* Control enabling of device for output. This is primarily intended
|
||||
* for temporary power-saving; the overall ability of the device to operate for
|
||||
* input and/or output may be fixed at creation time, but this call can
|
||||
* allow output to be temporarily disabled to permit power saving without
|
||||
* losing device state.
|
||||
*
|
||||
* @param enabled true to enable output, false to disable.
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return Negative error code on failure
|
||||
*/
|
||||
virtual int enable_output(bool enabled)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/** Check for poll event flags
|
||||
* You can use or ignore the input parameter. You can return all events
|
||||
* or check just the events listed in events.
|
||||
|
|
|
@ -291,7 +291,7 @@ static FileHandle *get_console(int fd)
|
|||
}
|
||||
|
||||
/* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
|
||||
static FileHandle *get_fhc(int fd)
|
||||
FileHandle *mbed::mbed_file_handle(int fd)
|
||||
{
|
||||
if (fd >= OPEN_MAX) {
|
||||
return NULL;
|
||||
|
@ -491,13 +491,13 @@ extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
|
|||
/* Use the posix convention that stdin,out,err are filehandles 0,1,2.
|
||||
*/
|
||||
if (std::strcmp(name, __stdin_name) == 0) {
|
||||
get_fhc(STDIN_FILENO);
|
||||
mbed_file_handle(STDIN_FILENO);
|
||||
return STDIN_FILENO;
|
||||
} else if (std::strcmp(name, __stdout_name) == 0) {
|
||||
get_fhc(STDOUT_FILENO);
|
||||
mbed_file_handle(STDOUT_FILENO);
|
||||
return STDOUT_FILENO;
|
||||
} else if (std::strcmp(name, __stderr_name) == 0) {
|
||||
get_fhc(STDERR_FILENO);
|
||||
mbed_file_handle(STDERR_FILENO);
|
||||
return STDERR_FILENO;
|
||||
}
|
||||
#endif
|
||||
|
@ -556,7 +556,7 @@ extern "C" int PREFIX(_close)(FILEHANDLE fh)
|
|||
|
||||
extern "C" int close(int fildes)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
filehandles[fildes] = NULL;
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
|
@ -668,7 +668,7 @@ finish:
|
|||
extern "C" ssize_t write(int fildes, const void *buf, size_t length)
|
||||
{
|
||||
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -762,8 +762,7 @@ extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int
|
|||
|
||||
extern "C" ssize_t read(int fildes, void *buf, size_t length)
|
||||
{
|
||||
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -790,7 +789,7 @@ extern "C" int _isatty(FILEHANDLE fh)
|
|||
|
||||
extern "C" int isatty(int fildes)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return 0;
|
||||
|
@ -829,7 +828,7 @@ int _lseek(FILEHANDLE fh, int offset, int whence)
|
|||
|
||||
extern "C" off_t lseek(int fildes, off_t offset, int whence)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -845,7 +844,7 @@ extern "C" off_t lseek(int fildes, off_t offset, int whence)
|
|||
|
||||
extern "C" int ftruncate(int fildes, off_t length)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -869,7 +868,7 @@ extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
|
|||
|
||||
extern "C" int fsync(int fildes)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -887,7 +886,7 @@ extern "C" int fsync(int fildes)
|
|||
#ifdef __ARMCC_VERSION
|
||||
extern "C" long PREFIX(_flen)(FILEHANDLE fh)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fh);
|
||||
FileHandle *fhc = mbed_file_handle(fh);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -965,7 +964,7 @@ extern "C" int _fstat(int fh, struct stat *st)
|
|||
|
||||
extern "C" int fstat(int fildes, struct stat *st)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -978,7 +977,7 @@ extern "C" int fstat(int fildes, struct stat *st)
|
|||
|
||||
extern "C" int fcntl(int fildes, int cmd, ...)
|
||||
{
|
||||
FileHandle *fhc = get_fhc(fildes);
|
||||
FileHandle *fhc = mbed_file_handle(fildes);
|
||||
if (fhc == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
@ -1023,7 +1022,7 @@ extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
|||
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.
|
||||
fhs[n].fh = get_fhc(fds[n].fd);
|
||||
fhs[n].fh = mbed_file_handle(fds[n].fd);
|
||||
fhs[n].events = fds[n].events;
|
||||
}
|
||||
int ret = poll(fhs, nfds, timeout);
|
||||
|
|
|
@ -133,6 +133,27 @@ FileHandle *mbed_target_override_console(int fd);
|
|||
*/
|
||||
FileHandle *mbed_override_console(int fd);
|
||||
|
||||
/** Look up the Mbed file handle corresponding to a file descriptor
|
||||
*
|
||||
* This conversion function permits an application to find the underlying
|
||||
* FileHandle object corresponding to a POSIX file descriptor.
|
||||
*
|
||||
* This allows access to specialized behavior only available via the
|
||||
* FileHandle API.
|
||||
*
|
||||
* Example of saving power by disabling console input - for buffered serial,
|
||||
* this would release the RX interrupt handler, which would release the
|
||||
* deep sleep lock.
|
||||
* @code
|
||||
* mbed_file_handle(STDIN_FILENO)->enable_input(false);
|
||||
* @endcode
|
||||
*
|
||||
* @param fd file descriptor
|
||||
* @return FileHandle pointer
|
||||
* NULL if descriptor does not correspond to a FileHandle (only
|
||||
* possible if it's not open with current implementation).
|
||||
*/
|
||||
FileHandle *mbed_file_handle(int fd);
|
||||
}
|
||||
|
||||
typedef mbed::DirHandle DIR;
|
||||
|
|
Loading…
Reference in New Issue