Fix hardware flow control on NRF52 series

Due to buggy flow control logic in the UARTE, the stop signal
is not being set as it is supposed to when the the module is
not ready to receive data.

This commit signals the sender to halt transmitting when a DMA
buffer is full and only continue again when the atomic FIFO
buffer has been emptied. This allows platforms with hardware
flow control to minimize all buffers and rely on flow control
instead.
pull/8292/head
Marcus Chang 2018-10-01 16:49:40 -07:00
parent b18c819837
commit 1ad3b49599
2 changed files with 34 additions and 1 deletions

View File

@ -137,6 +137,9 @@ const PinMapI2C PinMap_UART[] = {
The table must be placed in a C compilation file.
#### Flow Control (RTS/CTS)
When hardware flow control is enabled the DMA and FIFO buffers can be reduced to save RAM. CTS will be disabled when a DMA buffer is copied to the FIFO and enabled again when the FIFO has been emptied. Because of the dual buffering the FIFO buffer must be twice the size of the DMA buffer (less than half and data mmight be lost and more than half will be a waste of RAM).
#### RTC2

View File

@ -593,6 +593,20 @@ static void nordic_nrf5_uart_event_handler_endrx(int instance)
if (available > 0) {
/* Check if hardware flow control is set and signal sender to stop.
*
* This signal is set manually because the flow control logic in the UARTE module
* only works when the module is receiving and not after an ENDRX event.
*
* The RTS signal is kept high until the atomic FIFO is empty. This allow systems
* with flow control to reduce their FIFO and DMA buffers.
*/
if ((nordic_nrf5_uart_state[instance].owner->hwfc == NRF_UART_HWFC_ENABLED) &&
(nordic_nrf5_uart_state[instance].owner->rts != NRF_UART_PSEL_DISCONNECTED)) {
nrf_gpio_pin_set(nordic_nrf5_uart_state[instance].owner->rts);
}
/* Copy data from DMA buffer to FIFO buffer. */
for (size_t index = 0; index < available; index++) {
@ -810,6 +824,7 @@ static void nordic_nrf5_uart_configure_object(serial_t *obj)
/* Check if pin is set before configuring it. */
if (uart_object->rts != NRF_UART_PSEL_DISCONNECTED) {
nrf_gpio_pin_clear(uart_object->rts);
nrf_gpio_cfg_output(uart_object->rts);
}
@ -819,8 +834,9 @@ static void nordic_nrf5_uart_configure_object(serial_t *obj)
nrf_gpio_cfg_input(uart_object->cts, NRF_GPIO_PIN_NOPULL);
}
/* Only let UARTE module handle CTS, RTS is handled manually due to buggy UARTE logic. */
nrf_uarte_hwfc_pins_set(nordic_nrf5_uart_register[uart_object->instance],
uart_object->rts,
NRF_UART_PSEL_DISCONNECTED,
uart_object->cts);
}
@ -1429,6 +1445,20 @@ int serial_getc(serial_t *obj)
uint8_t *byte = (uint8_t *) nrf_atfifo_item_get(fifo, &context);
nrf_atfifo_item_free(fifo, &context);
/* Check if hardware flow control is set and the atomic FIFO buffer is empty.
*
* Receive is halted until the buffer has been completely handled to reduce RAM usage.
*
* This signal is set manually because the flow control logic in the UARTE module
* only works when the module is receiving and not after an ENDRX event.
*/
if ((nordic_nrf5_uart_state[instance].owner->hwfc == NRF_UART_HWFC_ENABLED) &&
(nordic_nrf5_uart_state[instance].owner->rts != NRF_UART_PSEL_DISCONNECTED) &&
(*head == *tail)) {
nrf_gpio_pin_clear(nordic_nrf5_uart_state[instance].owner->rts);
}
return *byte;
}