mirror of https://github.com/ARMmbed/mbed-os.git
Asynchronous Serial API fixes and refactoring, part 2
Aborting of asynchronous operation is necessarily hazardous, as operation can end in interrupt anywhere from the point of decision until it is actually aborted down the abort_...() method. Proper deep sleep unlocking requires then use of the critical section and should be contained completely within API implementation.pull/9476/head
parent
6d648092e1
commit
cbb84d8ad3
|
@ -201,20 +201,28 @@ 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);
|
||||||
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
}
|
}
|
||||||
start_write((void *)buffer, length, 8, callback, event);
|
unlock();
|
||||||
return 0;
|
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);
|
||||||
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
}
|
}
|
||||||
start_write((void *)buffer, length, 16, callback, event);
|
unlock();
|
||||||
return 0;
|
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)
|
||||||
|
@ -229,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)
|
||||||
{
|
{
|
||||||
|
lock();
|
||||||
|
core_util_critical_section_enter();
|
||||||
if (_tx_asynch_set) {
|
if (_tx_asynch_set) {
|
||||||
_tx_callback = NULL;
|
_tx_callback = NULL;
|
||||||
_tx_asynch_set = false;
|
_tx_asynch_set = false;
|
||||||
serial_tx_abort_asynch(&_serial);
|
serial_tx_abort_asynch(&_serial);
|
||||||
sleep_manager_unlock_deep_sleep();
|
sleep_manager_unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialBase::abort_read(void)
|
void SerialBase::abort_read(void)
|
||||||
{
|
{
|
||||||
|
lock();
|
||||||
|
core_util_critical_section_enter();
|
||||||
if (_rx_asynch_set) {
|
if (_rx_asynch_set) {
|
||||||
_rx_callback = NULL;
|
_rx_callback = NULL;
|
||||||
_rx_asynch_set = false;
|
_rx_asynch_set = false;
|
||||||
serial_rx_abort_asynch(&_serial);
|
serial_rx_abort_asynch(&_serial);
|
||||||
sleep_manager_unlock_deep_sleep();
|
sleep_manager_unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SerialBase::set_dma_usage_tx(DMAUsage usage)
|
int SerialBase::set_dma_usage_tx(DMAUsage usage)
|
||||||
|
@ -267,21 +283,29 @@ 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);
|
||||||
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
}
|
}
|
||||||
start_read((void *)buffer, length, 8, callback, event, char_match);
|
unlock();
|
||||||
return 0;
|
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);
|
||||||
|
} else {
|
||||||
|
result = -1; // transaction ongoing
|
||||||
}
|
}
|
||||||
start_read((void *)buffer, length, 16, callback, event, char_match);
|
unlock();
|
||||||
return 0;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue