Skip to content

Commit 6d64809

Browse files
committed
Asynchronous Serial API fixes and refactoring, part 1
1. As RX and TX flows are separate on Serial device, read and write functionalities should be completely separate, including any deep sleep locking etc. 2. User may want to use asynchronous API without a callback (especially for write operations), for example in a command-response scheme end of write operation is usually meaningless. The intuitive method is to submit NULL pointer for a callback. For this reason depending on the _callback field in determining whether the operation is in progress seems to be uncertain, so introduced additional flags for this purpose.
1 parent 51b8d6e commit 6d64809

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

drivers/SerialBase.cpp

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
2727
#if DEVICE_SERIAL_ASYNCH
2828
_thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
2929
_rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL),
30-
_rx_callback(NULL),
30+
_rx_callback(NULL), _tx_asynch_set(false),
31+
_rx_asynch_set(false),
3132
#endif
3233
_serial(), _baud(baud)
3334
{
@@ -218,6 +219,7 @@ int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t
218219

219220
void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event)
220221
{
222+
_tx_asynch_set = true;
221223
_tx_callback = callback;
222224

223225
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
@@ -227,22 +229,22 @@ void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_wi
227229

228230
void SerialBase::abort_write(void)
229231
{
230-
// rx might still be active
231-
if (_rx_callback) {
232+
if (_tx_asynch_set) {
233+
_tx_callback = NULL;
234+
_tx_asynch_set = false;
235+
serial_tx_abort_asynch(&_serial);
232236
sleep_manager_unlock_deep_sleep();
233237
}
234-
_tx_callback = NULL;
235-
serial_tx_abort_asynch(&_serial);
236238
}
237239

238240
void SerialBase::abort_read(void)
239241
{
240-
// tx might still be active
241-
if (_tx_callback) {
242+
if (_rx_asynch_set) {
243+
_rx_callback = NULL;
244+
_rx_asynch_set = false;
245+
serial_rx_abort_asynch(&_serial);
242246
sleep_manager_unlock_deep_sleep();
243247
}
244-
_rx_callback = NULL;
245-
serial_rx_abort_asynch(&_serial);
246248
}
247249

248250
int SerialBase::set_dma_usage_tx(DMAUsage usage)
@@ -285,6 +287,7 @@ int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callb
285287

286288
void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match)
287289
{
290+
_rx_asynch_set = true;
288291
_rx_callback = callback;
289292
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
290293
sleep_manager_lock_deep_sleep();
@@ -295,20 +298,25 @@ void SerialBase::interrupt_handler_asynch(void)
295298
{
296299
int event = serial_irq_handler_asynch(&_serial);
297300
int rx_event = event & SERIAL_EVENT_RX_MASK;
298-
bool unlock_deepsleep = false;
299301

300-
if (_rx_callback && rx_event) {
301-
unlock_deepsleep = true;
302-
_rx_callback.call(rx_event);
302+
if (_rx_asynch_set && rx_event) {
303+
event_callback_t cb = _rx_callback;
304+
_rx_asynch_set = false;
305+
_rx_callback = NULL;
306+
if (cb) {
307+
cb.call(rx_event);
308+
}
309+
sleep_manager_unlock_deep_sleep();
303310
}
304311

305312
int tx_event = event & SERIAL_EVENT_TX_MASK;
306-
if (_tx_callback && tx_event) {
307-
unlock_deepsleep = true;
308-
_tx_callback.call(tx_event);
309-
}
310-
// unlock if tx or rx events are generated
311-
if (unlock_deepsleep) {
313+
if (_tx_asynch_set && tx_event) {
314+
event_callback_t cb = _tx_callback;
315+
_tx_asynch_set = false;
316+
_tx_callback = NULL;
317+
if (cb) {
318+
cb.call(tx_event);
319+
}
312320
sleep_manager_unlock_deep_sleep();
313321
}
314322
}

drivers/SerialBase.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ class SerialBase : private NonCopyable<SerialBase> {
269269
DMAUsage _rx_usage;
270270
event_callback_t _tx_callback;
271271
event_callback_t _rx_callback;
272+
bool _tx_asynch_set;
273+
bool _rx_asynch_set;
272274
#endif
273275

274276
serial_t _serial;

0 commit comments

Comments
 (0)