Skip to content

Commit 1ad3b49

Browse files
author
Marcus Chang
committed
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.
1 parent b18c819 commit 1ad3b49

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ const PinMapI2C PinMap_UART[] = {
137137

138138
The table must be placed in a C compilation file.
139139

140+
#### Flow Control (RTS/CTS)
141+
142+
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).
140143

141144
#### RTC2
142145

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,20 @@ static void nordic_nrf5_uart_event_handler_endrx(int instance)
593593

594594
if (available > 0) {
595595

596+
/* Check if hardware flow control is set and signal sender to stop.
597+
*
598+
* This signal is set manually because the flow control logic in the UARTE module
599+
* only works when the module is receiving and not after an ENDRX event.
600+
*
601+
* The RTS signal is kept high until the atomic FIFO is empty. This allow systems
602+
* with flow control to reduce their FIFO and DMA buffers.
603+
*/
604+
if ((nordic_nrf5_uart_state[instance].owner->hwfc == NRF_UART_HWFC_ENABLED) &&
605+
(nordic_nrf5_uart_state[instance].owner->rts != NRF_UART_PSEL_DISCONNECTED)) {
606+
607+
nrf_gpio_pin_set(nordic_nrf5_uart_state[instance].owner->rts);
608+
}
609+
596610
/* Copy data from DMA buffer to FIFO buffer. */
597611
for (size_t index = 0; index < available; index++) {
598612

@@ -810,6 +824,7 @@ static void nordic_nrf5_uart_configure_object(serial_t *obj)
810824
/* Check if pin is set before configuring it. */
811825
if (uart_object->rts != NRF_UART_PSEL_DISCONNECTED) {
812826

827+
nrf_gpio_pin_clear(uart_object->rts);
813828
nrf_gpio_cfg_output(uart_object->rts);
814829
}
815830

@@ -819,8 +834,9 @@ static void nordic_nrf5_uart_configure_object(serial_t *obj)
819834
nrf_gpio_cfg_input(uart_object->cts, NRF_GPIO_PIN_NOPULL);
820835
}
821836

837+
/* Only let UARTE module handle CTS, RTS is handled manually due to buggy UARTE logic. */
822838
nrf_uarte_hwfc_pins_set(nordic_nrf5_uart_register[uart_object->instance],
823-
uart_object->rts,
839+
NRF_UART_PSEL_DISCONNECTED,
824840
uart_object->cts);
825841
}
826842

@@ -1429,6 +1445,20 @@ int serial_getc(serial_t *obj)
14291445
uint8_t *byte = (uint8_t *) nrf_atfifo_item_get(fifo, &context);
14301446
nrf_atfifo_item_free(fifo, &context);
14311447

1448+
/* Check if hardware flow control is set and the atomic FIFO buffer is empty.
1449+
*
1450+
* Receive is halted until the buffer has been completely handled to reduce RAM usage.
1451+
*
1452+
* This signal is set manually because the flow control logic in the UARTE module
1453+
* only works when the module is receiving and not after an ENDRX event.
1454+
*/
1455+
if ((nordic_nrf5_uart_state[instance].owner->hwfc == NRF_UART_HWFC_ENABLED) &&
1456+
(nordic_nrf5_uart_state[instance].owner->rts != NRF_UART_PSEL_DISCONNECTED) &&
1457+
(*head == *tail)) {
1458+
1459+
nrf_gpio_pin_clear(nordic_nrf5_uart_state[instance].owner->rts);
1460+
}
1461+
14321462
return *byte;
14331463
}
14341464

0 commit comments

Comments
 (0)