Implement enable calls in UARTSerial

Implement enable calls so that reception can be shut down to save
power without closing the device.
pull/9797/head
Kevin Bracey 2019-02-21 16:44:54 +02:00
parent e96d6581db
commit 649856f3ff
2 changed files with 110 additions and 12 deletions

View File

@ -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

View File

@ -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