mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #9476 from lrusinowicz/asynch_serial_api
Asynchronous Serial API fixes and refactoringpull/10267/head
commit
d3db0a8c2d
|
@ -27,7 +27,8 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
_thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
|
_thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
|
||||||
_rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL),
|
_rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL),
|
||||||
_rx_callback(NULL),
|
_rx_callback(NULL), _tx_asynch_set(false),
|
||||||
|
_rx_asynch_set(false),
|
||||||
#endif
|
#endif
|
||||||
_serial(), _baud(baud)
|
_serial(), _baud(baud)
|
||||||
{
|
{
|
||||||
|
@ -200,24 +201,33 @@ void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2)
|
||||||
|
|
||||||
int SerialBase::write(const uint8_t *buffer, int length, const event_callback_t &callback, int event)
|
int SerialBase::write(const uint8_t *buffer, int length, const event_callback_t &callback, int event)
|
||||||
{
|
{
|
||||||
if (serial_tx_active(&_serial)) {
|
int result = 0;
|
||||||
return -1; // transaction ongoing
|
lock();
|
||||||
}
|
if (!serial_tx_active(&_serial) && !_tx_asynch_set) {
|
||||||
start_write((void *)buffer, length, 8, callback, event);
|
start_write((void *)buffer, length, 8, callback, event);
|
||||||
return 0;
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t &callback, int event)
|
int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t &callback, int event)
|
||||||
{
|
{
|
||||||
if (serial_tx_active(&_serial)) {
|
int result = 0;
|
||||||
return -1; // transaction ongoing
|
lock();
|
||||||
}
|
if (!serial_tx_active(&_serial) && !_tx_asynch_set) {
|
||||||
start_write((void *)buffer, length, 16, callback, event);
|
start_write((void *)buffer, length, 16, callback, event);
|
||||||
return 0;
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event)
|
void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event)
|
||||||
{
|
{
|
||||||
|
_tx_asynch_set = true;
|
||||||
_tx_callback = callback;
|
_tx_callback = callback;
|
||||||
|
|
||||||
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
|
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
|
||||||
|
@ -227,22 +237,30 @@ void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_wi
|
||||||
|
|
||||||
void SerialBase::abort_write(void)
|
void SerialBase::abort_write(void)
|
||||||
{
|
{
|
||||||
// rx might still be active
|
lock();
|
||||||
if (_rx_callback) {
|
core_util_critical_section_enter();
|
||||||
|
if (_tx_asynch_set) {
|
||||||
|
_tx_callback = NULL;
|
||||||
|
_tx_asynch_set = false;
|
||||||
|
serial_tx_abort_asynch(&_serial);
|
||||||
sleep_manager_unlock_deep_sleep();
|
sleep_manager_unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
_tx_callback = NULL;
|
core_util_critical_section_exit();
|
||||||
serial_tx_abort_asynch(&_serial);
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialBase::abort_read(void)
|
void SerialBase::abort_read(void)
|
||||||
{
|
{
|
||||||
// tx might still be active
|
lock();
|
||||||
if (_tx_callback) {
|
core_util_critical_section_enter();
|
||||||
|
if (_rx_asynch_set) {
|
||||||
|
_rx_callback = NULL;
|
||||||
|
_rx_asynch_set = false;
|
||||||
|
serial_rx_abort_asynch(&_serial);
|
||||||
sleep_manager_unlock_deep_sleep();
|
sleep_manager_unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
_rx_callback = NULL;
|
core_util_critical_section_exit();
|
||||||
serial_rx_abort_asynch(&_serial);
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SerialBase::set_dma_usage_tx(DMAUsage usage)
|
int SerialBase::set_dma_usage_tx(DMAUsage usage)
|
||||||
|
@ -265,26 +283,35 @@ int SerialBase::set_dma_usage_rx(DMAUsage usage)
|
||||||
|
|
||||||
int SerialBase::read(uint8_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match)
|
int SerialBase::read(uint8_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match)
|
||||||
{
|
{
|
||||||
if (serial_rx_active(&_serial)) {
|
int result = 0;
|
||||||
return -1; // transaction ongoing
|
lock();
|
||||||
}
|
if (!serial_rx_active(&_serial) && !_rx_asynch_set) {
|
||||||
start_read((void *)buffer, length, 8, callback, event, char_match);
|
start_read((void *)buffer, length, 8, callback, event, char_match);
|
||||||
return 0;
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match)
|
int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match)
|
||||||
{
|
{
|
||||||
if (serial_rx_active(&_serial)) {
|
int result = 0;
|
||||||
return -1; // transaction ongoing
|
lock();
|
||||||
}
|
if (!serial_rx_active(&_serial) && !_rx_asynch_set) {
|
||||||
start_read((void *)buffer, length, 16, callback, event, char_match);
|
start_read((void *)buffer, length, 16, callback, event, char_match);
|
||||||
return 0;
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match)
|
void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match)
|
||||||
{
|
{
|
||||||
|
_rx_asynch_set = true;
|
||||||
_rx_callback = callback;
|
_rx_callback = callback;
|
||||||
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
|
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
|
||||||
sleep_manager_lock_deep_sleep();
|
sleep_manager_lock_deep_sleep();
|
||||||
|
@ -295,20 +322,25 @@ void SerialBase::interrupt_handler_asynch(void)
|
||||||
{
|
{
|
||||||
int event = serial_irq_handler_asynch(&_serial);
|
int event = serial_irq_handler_asynch(&_serial);
|
||||||
int rx_event = event & SERIAL_EVENT_RX_MASK;
|
int rx_event = event & SERIAL_EVENT_RX_MASK;
|
||||||
bool unlock_deepsleep = false;
|
|
||||||
|
|
||||||
if (_rx_callback && rx_event) {
|
if (_rx_asynch_set && rx_event) {
|
||||||
unlock_deepsleep = true;
|
event_callback_t cb = _rx_callback;
|
||||||
_rx_callback.call(rx_event);
|
_rx_asynch_set = false;
|
||||||
|
_rx_callback = NULL;
|
||||||
|
if (cb) {
|
||||||
|
cb.call(rx_event);
|
||||||
|
}
|
||||||
|
sleep_manager_unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
int tx_event = event & SERIAL_EVENT_TX_MASK;
|
int tx_event = event & SERIAL_EVENT_TX_MASK;
|
||||||
if (_tx_callback && tx_event) {
|
if (_tx_asynch_set && tx_event) {
|
||||||
unlock_deepsleep = true;
|
event_callback_t cb = _tx_callback;
|
||||||
_tx_callback.call(tx_event);
|
_tx_asynch_set = false;
|
||||||
|
_tx_callback = NULL;
|
||||||
|
if (cb) {
|
||||||
|
cb.call(tx_event);
|
||||||
}
|
}
|
||||||
// unlock if tx or rx events are generated
|
|
||||||
if (unlock_deepsleep) {
|
|
||||||
sleep_manager_unlock_deep_sleep();
|
sleep_manager_unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,57 +179,85 @@ public:
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
|
|
||||||
/** Begin asynchronous write using 8bit buffer. The completion invokes registered TX event callback
|
/** Begin asynchronous write using 8bit buffer.
|
||||||
*
|
*
|
||||||
* This function locks the deep sleep until any event has occurred
|
* The write operation ends with any of the enabled events and invokes
|
||||||
|
* registered callback function (which can be NULL to not receive callback at all).
|
||||||
|
* Events that are not enabled by event argument are simply ignored.
|
||||||
|
* Operation has to be ended explicitly by calling abort_write() when
|
||||||
|
* no events are enabled.
|
||||||
|
* This function locks the deep sleep until any event has occurred.
|
||||||
*
|
*
|
||||||
* @param buffer The buffer where received data will be stored
|
* @param buffer The buffer where received data will be stored
|
||||||
* @param length The buffer length in bytes
|
* @param length The buffer length in bytes
|
||||||
* @param callback The event callback function
|
* @param callback The event callback function
|
||||||
* @param event The logical OR of TX events
|
* @param event The logical OR of TX events that should end operation
|
||||||
|
* @return Zero if new transaction was started, -1 if transaction is already on-going
|
||||||
*/
|
*/
|
||||||
int write(const uint8_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_TX_COMPLETE);
|
int write(const uint8_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_TX_COMPLETE);
|
||||||
|
|
||||||
/** Begin asynchronous write using 16bit buffer. The completion invokes registered TX event callback
|
/** Begin asynchronous write using 16bit buffer.
|
||||||
*
|
*
|
||||||
* This function locks the deep sleep until any event has occurred
|
* The write operation ends with any of the enabled events and invokes
|
||||||
|
* registered callback function (which can be NULL to not receive callback at all).
|
||||||
|
* Events that are not enabled by event argument are simply ignored.
|
||||||
|
* Operation has to be ended explicitly by calling abort_write() when
|
||||||
|
* no events are enabled.
|
||||||
|
* This function locks the deep sleep until any event has occurred.
|
||||||
*
|
*
|
||||||
* @param buffer The buffer where received data will be stored
|
* @param buffer The buffer where received data will be stored
|
||||||
* @param length The buffer length in bytes
|
* @param length The buffer length in bytes
|
||||||
* @param callback The event callback function
|
* @param callback The event callback function
|
||||||
* @param event The logical OR of TX events
|
* @param event The logical OR of TX events that should end operation
|
||||||
|
* @return Zero if new transaction was started, -1 if transaction is already on-going
|
||||||
*/
|
*/
|
||||||
int write(const uint16_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_TX_COMPLETE);
|
int write(const uint16_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_TX_COMPLETE);
|
||||||
|
|
||||||
/** Abort the on-going write transfer
|
/** Abort the on-going write transfer
|
||||||
|
*
|
||||||
|
* It is safe to call abort_write() when there is no on-going transaction.
|
||||||
*/
|
*/
|
||||||
void abort_write();
|
void abort_write();
|
||||||
|
|
||||||
/** Begin asynchronous reading using 8bit buffer. The completion invokes registered RX event callback.
|
/** Begin asynchronous reading using 8bit buffer.
|
||||||
*
|
*
|
||||||
* This function locks the deep sleep until any event has occurred
|
* The read operation ends with any of the enabled events and invokes registered
|
||||||
|
* callback function (which can be NULL to not receive callback at all).
|
||||||
|
* Events that are not enabled by event argument are simply ignored.
|
||||||
|
* Operation has to be ended explicitly by calling abort_read() when
|
||||||
|
* no events are enabled.
|
||||||
|
* This function locks the deep sleep until any event has occurred.
|
||||||
*
|
*
|
||||||
* @param buffer The buffer where received data will be stored
|
* @param buffer The buffer where received data will be stored
|
||||||
* @param length The buffer length in bytes
|
* @param length The buffer length in bytes
|
||||||
* @param callback The event callback function
|
* @param callback The event callback function
|
||||||
* @param event The logical OR of RX events
|
* @param event The logical OR of RX events that should end operation
|
||||||
* @param char_match The matching character
|
* @param char_match The matching character
|
||||||
|
* @return Zero if new transaction was started, -1 if transaction is already on-going
|
||||||
*/
|
*/
|
||||||
int read(uint8_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_RX_COMPLETE, unsigned char char_match = SERIAL_RESERVED_CHAR_MATCH);
|
int read(uint8_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_RX_COMPLETE, unsigned char char_match = SERIAL_RESERVED_CHAR_MATCH);
|
||||||
|
|
||||||
/** Begin asynchronous reading using 16bit buffer. The completion invokes registered RX event callback.
|
/** Begin asynchronous reading using 16bit buffer.
|
||||||
*
|
*
|
||||||
* This function locks the deep sleep until any event has occurred
|
* The read operation ends with any of the enabled events and invokes registered
|
||||||
|
* callback function (which can be NULL to not receive callback at all).
|
||||||
|
* Events that are not enabled by event argument are simply ignored.
|
||||||
|
* Operation has to be ended explicitly by calling abort_read() when
|
||||||
|
* no events are enabled.
|
||||||
|
* This function locks the deep sleep until any event has occurred.
|
||||||
*
|
*
|
||||||
* @param buffer The buffer where received data will be stored
|
* @param buffer The buffer where received data will be stored
|
||||||
* @param length The buffer length in bytes
|
* @param length The buffer length in bytes
|
||||||
* @param callback The event callback function
|
* @param callback The event callback function
|
||||||
* @param event The logical OR of RX events
|
* @param event The logical OR of RX events that should end operation
|
||||||
* @param char_match The matching character
|
* @param char_match The matching character
|
||||||
|
* @return Zero if new transaction was started, -1 if transaction is already on-going
|
||||||
*/
|
*/
|
||||||
int read(uint16_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_RX_COMPLETE, unsigned char char_match = SERIAL_RESERVED_CHAR_MATCH);
|
int read(uint16_t *buffer, int length, const event_callback_t &callback, int event = SERIAL_EVENT_RX_COMPLETE, unsigned char char_match = SERIAL_RESERVED_CHAR_MATCH);
|
||||||
|
|
||||||
/** Abort the on-going read transfer
|
/** Abort the on-going read transfer
|
||||||
|
*
|
||||||
|
* It is safe to call abort_read() when there is no on-going transaction.
|
||||||
*/
|
*/
|
||||||
void abort_read();
|
void abort_read();
|
||||||
|
|
||||||
|
@ -269,6 +297,8 @@ protected:
|
||||||
DMAUsage _rx_usage;
|
DMAUsage _rx_usage;
|
||||||
event_callback_t _tx_callback;
|
event_callback_t _tx_callback;
|
||||||
event_callback_t _rx_callback;
|
event_callback_t _rx_callback;
|
||||||
|
bool _tx_asynch_set;
|
||||||
|
bool _rx_asynch_set;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
serial_t _serial;
|
serial_t _serial;
|
||||||
|
|
Loading…
Reference in New Issue