Skip to content

Commit 649856f

Browse files
committed
Implement enable calls in UARTSerial
Implement enable calls so that reception can be shut down to save power without closing the device.
1 parent e96d658 commit 649856f

File tree

2 files changed

+110
-12
lines changed

2 files changed

+110
-12
lines changed

drivers/UARTSerial.cpp

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) :
3232
SerialBase(tx, rx, baud),
3333
_blocking(true),
3434
_tx_irq_enabled(false),
35-
_rx_irq_enabled(true),
35+
_rx_irq_enabled(false),
36+
_tx_enabled(true),
37+
_rx_enabled(true),
3638
_dcd_irq(NULL)
3739
{
3840
/* Attatch IRQ routines to the serial device. */
39-
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
41+
enable_rx_irq();
4042
}
4143

4244
UARTSerial::~UARTSerial()
@@ -188,11 +190,10 @@ ssize_t UARTSerial::write(const void *buffer, size_t length)
188190
}
189191

190192
core_util_critical_section_enter();
191-
if (!_tx_irq_enabled) {
193+
if (_tx_enabled && !_tx_irq_enabled) {
192194
UARTSerial::tx_irq(); // only write to hardware in one place
193195
if (!_txbuf.empty()) {
194-
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
195-
_tx_irq_enabled = true;
196+
enable_tx_irq();
196197
}
197198
}
198199
core_util_critical_section_exit();
@@ -231,11 +232,10 @@ ssize_t UARTSerial::read(void *buffer, size_t length)
231232
}
232233

233234
core_util_critical_section_enter();
234-
if (!_rx_irq_enabled) {
235+
if (_rx_enabled && !_rx_irq_enabled) {
235236
UARTSerial::rx_irq(); // only read from hardware in one place
236237
if (!_rxbuf.full()) {
237-
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
238-
_rx_irq_enabled = true;
238+
enable_rx_irq();
239239
}
240240
}
241241
core_util_critical_section_exit();
@@ -314,8 +314,7 @@ void UARTSerial::rx_irq(void)
314314
}
315315

316316
if (_rx_irq_enabled && _rxbuf.full()) {
317-
SerialBase::attach(NULL, RxIrq);
318-
_rx_irq_enabled = false;
317+
disable_rx_irq();
319318
}
320319

321320
/* Report the File handler that data is ready to be read from the buffer. */
@@ -337,8 +336,7 @@ void UARTSerial::tx_irq(void)
337336
}
338337

339338
if (_tx_irq_enabled && _txbuf.empty()) {
340-
SerialBase::attach(NULL, TxIrq);
341-
_tx_irq_enabled = false;
339+
disable_tx_irq();
342340
}
343341

344342
/* Report the File handler that data can be written to peripheral. */
@@ -347,6 +345,69 @@ void UARTSerial::tx_irq(void)
347345
}
348346
}
349347

348+
/* These are all called from critical section */
349+
void UARTSerial::enable_rx_irq()
350+
{
351+
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
352+
_rx_irq_enabled = true;
353+
}
354+
355+
void UARTSerial::disable_rx_irq()
356+
{
357+
SerialBase::attach(NULL, RxIrq);
358+
_rx_irq_enabled = false;
359+
}
360+
361+
void UARTSerial::enable_tx_irq()
362+
{
363+
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
364+
_tx_irq_enabled = true;
365+
}
366+
367+
void UARTSerial::disable_tx_irq()
368+
{
369+
SerialBase::attach(NULL, TxIrq);
370+
_tx_irq_enabled = false;
371+
}
372+
373+
int UARTSerial::enable_input(bool enabled)
374+
{
375+
core_util_critical_section_enter();
376+
if (_rx_enabled != enabled) {
377+
if (enabled) {
378+
UARTSerial::rx_irq();
379+
if (!_rxbuf.full()) {
380+
enable_rx_irq();
381+
}
382+
} else {
383+
disable_rx_irq();
384+
}
385+
_rx_enabled = enabled;
386+
}
387+
core_util_critical_section_exit();
388+
389+
return 0;
390+
}
391+
392+
int UARTSerial::enable_output(bool enabled)
393+
{
394+
core_util_critical_section_enter();
395+
if (_tx_enabled != enabled) {
396+
if (enabled) {
397+
UARTSerial::tx_irq();
398+
if (!_txbuf.empty()) {
399+
enable_tx_irq();
400+
}
401+
} else {
402+
disable_tx_irq();
403+
}
404+
_tx_enabled = enabled;
405+
}
406+
core_util_critical_section_exit();
407+
408+
return 0;
409+
}
410+
350411
void UARTSerial::wait_ms(uint32_t millisec)
351412
{
352413
/* wait_ms implementation for RTOS spins until exact microseconds - we

drivers/UARTSerial.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,36 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
152152
return _blocking;
153153
}
154154

155+
/** Enable or disable input
156+
*
157+
* Control enabling of device for input. This is primarily intended
158+
* for temporary power-saving; the overall ability of the device to operate for
159+
* input and/or output may be fixed at creation time, but this call can
160+
* allow input to be temporarily disabled to permit power saving without
161+
* losing device state.
162+
*
163+
* @param enabled true to enable input, false to disable.
164+
*
165+
* @return 0 on success
166+
* @return Negative error code on failure
167+
*/
168+
virtual int enable_input(bool enabled);
169+
170+
/** Enable or disable output
171+
*
172+
* Control enabling of device for output. This is primarily intended
173+
* for temporary power-saving; the overall ability of the device to operate for
174+
* input and/or output may be fixed at creation time, but this call can
175+
* allow output to be temporarily disabled to permit power saving without
176+
* losing device state.
177+
*
178+
* @param enabled true to enable output, false to disable.
179+
*
180+
* @return 0 on success
181+
* @return Negative error code on failure
182+
*/
183+
virtual int enable_output(bool enabled);
184+
155185
/** Register a callback on state change of the file.
156186
*
157187
* The specified callback will be called on state changes such as when
@@ -242,6 +272,11 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
242272
/** Unbuffered write - invoked when write called from critical section */
243273
ssize_t write_unbuffered(const char *buf_ptr, size_t length);
244274

275+
void enable_rx_irq();
276+
void disable_rx_irq();
277+
void enable_tx_irq();
278+
void disable_tx_irq();
279+
245280
/** Software serial buffers
246281
* By default buffer size is 256 for TX and 256 for RX. Configurable through mbed_app.json
247282
*/
@@ -255,6 +290,8 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
255290
bool _blocking;
256291
bool _tx_irq_enabled;
257292
bool _rx_irq_enabled;
293+
bool _tx_enabled;
294+
bool _rx_enabled;
258295
InterruptIn *_dcd_irq;
259296

260297
/** Device Hanged up

0 commit comments

Comments
 (0)