Skip to content

API to temporarily enable/disable FileHandles #9797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions UNITTESTS/stubs/UARTSerial_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{

Expand Down
85 changes: 73 additions & 12 deletions drivers/UARTSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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. */
Expand All @@ -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. */
Expand All @@ -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
Expand Down
37 changes: 37 additions & 0 deletions drivers/UARTSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,36 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
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
Expand Down Expand Up @@ -242,6 +272,11 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
/** 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
*/
Expand All @@ -255,6 +290,8 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
bool _blocking;
bool _tx_irq_enabled;
bool _rx_irq_enabled;
bool _tx_enabled;
bool _rx_enabled;
InterruptIn *_dcd_irq;

/** Device Hanged up
Expand Down
36 changes: 36 additions & 0 deletions platform/FileHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,42 @@ class FileHandle : private NonCopyable<FileHandle> {
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.
Expand Down
31 changes: 15 additions & 16 deletions platform/mbed_retarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,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;
Expand Down Expand Up @@ -490,13 +490,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
Expand Down Expand Up @@ -555,7 +555,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;
Expand Down Expand Up @@ -667,7 +667,7 @@ extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsign
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;
Expand Down Expand Up @@ -761,8 +761,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;
Expand All @@ -789,7 +788,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;
Expand Down Expand Up @@ -828,7 +827,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;
Expand All @@ -844,7 +843,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;
Expand All @@ -868,7 +867,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;
Expand All @@ -886,7 +885,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;
Expand Down Expand Up @@ -936,7 +935,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;
Expand All @@ -949,7 +948,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;
Expand Down Expand Up @@ -994,7 +993,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);
Expand Down
Loading