Skip to content

Commit 2a7f5e2

Browse files
kjbraceyCruz Monrreal II
authored andcommitted
nRF52 serial: Tighten/simplify atomics
Use new atomics (exchange, load, store and bool types) to simplify and improve the atomics in the nRF52 serial HAL. * Ensure mutexes are released last and atomically when done done inside a critical section. * Compare-and-swap is not required for the spinlock - exchange is sufficient. (Not clear a spinlock is needed anyway, but left in). * Remove unneeded volatile, and make mutexes bool.
1 parent c0a6e95 commit 2a7f5e2

File tree

1 file changed

+18
-22
lines changed

1 file changed

+18
-22
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ typedef struct {
138138
uint8_t buffer[NUMBER_OF_BANKS][DMA_BUFFER_SIZE];
139139
uint32_t usage_counter;
140140
uint8_t tx_data;
141-
volatile uint8_t tx_in_progress;
142-
volatile uint8_t rx_in_progress;
141+
bool tx_in_progress;
142+
bool rx_in_progress;
143143
bool tx_asynch;
144144
bool rx_asynch;
145145
bool callback_posted;
@@ -252,7 +252,7 @@ static void nordic_nrf5_uart_callback_handler(uint32_t instance)
252252
static void nordic_nrf5_uart_event_handler_endtx(int instance)
253253
{
254254
/* Release mutex. As the owner this call is safe. */
255-
nordic_nrf5_uart_state[instance].tx_in_progress = 0;
255+
core_util_atomic_store_bool(&nordic_nrf5_uart_state[instance].tx_in_progress, false);
256256

257257
/* Check if callback handler and Tx event mask is set. */
258258
uart_irq_handler callback = (uart_irq_handler) nordic_nrf5_uart_state[instance].owner->handler;
@@ -275,8 +275,8 @@ static void nordic_nrf5_uart_event_handler_endtx(int instance)
275275
static void nordic_nrf5_uart_event_handler_endtx_asynch(int instance)
276276
{
277277
/* Set Tx done and reset Tx mode to be not asynchronous. */
278-
nordic_nrf5_uart_state[instance].tx_in_progress = 0;
279278
nordic_nrf5_uart_state[instance].tx_asynch = false;
279+
core_util_atomic_store_bool(&nordic_nrf5_uart_state[instance].tx_in_progress, false);
280280

281281
/* Cast handler to callback function pointer. */
282282
void (*callback)(void) = (void (*)(void)) nordic_nrf5_uart_state[instance].owner->tx_handler;
@@ -482,8 +482,8 @@ static void nordic_nrf5_uart_event_handler_rxstarted(int instance)
482482
static void nordic_nrf5_uart_event_handler_endrx_asynch(int instance)
483483
{
484484
/* Set Rx done and reset Rx mode to be not asynchronous. */
485-
nordic_nrf5_uart_state[instance].rx_in_progress = 0;
486485
nordic_nrf5_uart_state[instance].rx_asynch = false;
486+
core_util_atomic_store_bool(&nordic_nrf5_uart_state[instance].rx_in_progress, false);
487487

488488
/* Cast handler to callback function pointer. */
489489
void (*callback)(void) = (void (*)(void)) nordic_nrf5_uart_state[instance].owner->rx_handler;
@@ -1410,7 +1410,7 @@ int serial_writable(serial_t *obj)
14101410

14111411
int instance = uart_object->instance;
14121412

1413-
return ((nordic_nrf5_uart_state[instance].tx_in_progress == 0) &&
1413+
return (!core_util_atomic_load_bool(&nordic_nrf5_uart_state[instance].tx_in_progress) &&
14141414
(nrf_uarte_event_extra_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_TXDRDY)));
14151415
}
14161416

@@ -1449,16 +1449,14 @@ int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx
14491449

14501450
/**
14511451
* tx_in_progress acts like a mutex to ensure only one transmission can be active at a time.
1452-
* The flag is modified using the atomic compare-and-set function.
1452+
* The flag is modified using the atomic exchange function - only proceed when we see the
1453+
* flag clear and we set it to true.
14531454
*/
1454-
bool mutex = false;
1455+
bool old_mutex;
14551456

14561457
do {
1457-
uint8_t expected = 0;
1458-
uint8_t desired = 1;
1459-
1460-
mutex = core_util_atomic_cas_u8((uint8_t *) &nordic_nrf5_uart_state[instance].tx_in_progress, &expected, desired);
1461-
} while (mutex == false);
1458+
old_mutex = core_util_atomic_exchange_bool(&nordic_nrf5_uart_state[instance].tx_in_progress, true);
1459+
} while (old_mutex == true);
14621460

14631461
/* State variables. */
14641462
int result = 0;
@@ -1575,16 +1573,14 @@ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_widt
15751573

15761574
/**
15771575
* rx_in_progress acts like a mutex to ensure only one asynchronous reception can be active at a time.
1578-
* The flag is modified using the atomic compare-and-set function.
1576+
* The flag is modified using the atomic exchange function - only proceed when we see the
1577+
* flag clear and we set it to true.
15791578
*/
1580-
bool mutex = false;
1579+
bool old_mutex;
15811580

15821581
do {
1583-
uint8_t expected = 0;
1584-
uint8_t desired = 1;
1585-
1586-
mutex = core_util_atomic_cas_u8((uint8_t *) &nordic_nrf5_uart_state[instance].rx_in_progress, &expected, desired);
1587-
} while (mutex == false);
1582+
old_mutex = core_util_atomic_exchange_bool(&nordic_nrf5_uart_state[instance].rx_in_progress, true);
1583+
} while (old_mutex == true);
15881584

15891585
/* Store callback handler, mask and reset event value. */
15901586
obj->serial.rx_handler = handler;
@@ -1663,8 +1659,8 @@ void serial_tx_abort_asynch(serial_t *obj)
16631659
nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX);
16641660

16651661
/* Reset Tx flags. */
1666-
nordic_nrf5_uart_state[instance].tx_in_progress = 0;
16671662
nordic_nrf5_uart_state[instance].tx_asynch = false;
1663+
nordic_nrf5_uart_state[instance].tx_in_progress = false;
16681664

16691665
/* Force reconfiguration. */
16701666
obj->serial.update = true;
@@ -1691,8 +1687,8 @@ void serial_rx_abort_asynch(serial_t *obj)
16911687
core_util_critical_section_enter();
16921688

16931689
/* Reset Rx flags. */
1694-
nordic_nrf5_uart_state[obj->serial.instance].rx_in_progress = 0;
16951690
nordic_nrf5_uart_state[obj->serial.instance].rx_asynch = false;
1691+
nordic_nrf5_uart_state[obj->serial.instance].rx_in_progress = false;
16961692
obj->serial.rx_asynch = false;
16971693

16981694
/* Force reconfiguration. */

0 commit comments

Comments
 (0)