I'm using the UARTE peripheral via the UART driver code in SDK v14.2. Due to transfer size and SoftDevice timing I have to use the double-buffered receive method (by calling nrf_drv_uart_rx() twice). My receive transfers have the possibility of timing out, in which case I abort the transfer via nrf_drv_uart_rx_abort(). I have found that if the first buffer is still active, and the second buffer hasn't been used, then when I call nrf_drv_uart_rx_abort() I never get the NRF_DRV_UART_EVT_RX_DONE callback in my event handler. When I subsequently try to initiate my next RX, the driver throws NRF_ERROR_BUSY.
Tracing it back, it looks like the UARTE never generates an RXTO event as long as the ENDRX->STARTRX shortcut is enabled. I made two small changes to the driver code which solved my problem, but I would like to know if there is a better/cleaner solution. If not, then these changes should probably become part of the UART driver.
In nrf_drv_uart_rx_abort(), change the CODE_FOR_UARTE block to look like this:
CODE_FOR_UARTE ( // When using double-buffered RX, we must disable the short before aborting. Otherwise, // we will never receive the RXTO event if (p_cb->rx_secondary_buffer_length)
nrf_uarte_shorts_disable(p_instance->reg.p_uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); nrf_uarte_task_trigger(p_instance->reg.p_uarte, NRF_UARTE_TASK_STOPRX); )
and in uarte_irq_handler(), change the RXTO handler section to look like this:
if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_RXTO)) { nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_RXTO); if (p_cb->rx_buffer_length) { p_cb->rx_buffer_length = 0; rx_done_event(p_cb, nrf_uarte_rx_amount_get(p_uarte), p_cb->p_rx_buffer); } // When using double-buffered RX, we must clear both receive counts. Otherwise, the next // time we try to do a double-buffered receive the driver will throw an error if (p_cb->rx_secondary_buffer_length != 0) { p_cb->rx_secondary_buffer_length = 0; } }