Skip to content

Fix hardware flow control on NRF52 series #8292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions targets/TARGET_NORDIC/TARGET_NRF5x/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 2 additions & 4 deletions targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/mbed_lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@
"NRF52_PAN_62",
"NRF52_PAN_63",
"NRF52_PAN_64"
],
"target.console-uart-flow-control": "RTSCTS"
]
},
"RBLAB_BLENANO2": {
"target.macros_add": [
Expand Down Expand Up @@ -186,8 +185,7 @@
"target.macros_add": [
"CONFIG_GPIO_AS_PINRESET",
"NRF52_ERRATA_20"
],
"target.console-uart-flow-control": "RTSCTS"
]
},
"MTB_LAIRD_BL654": {
"target.macros_add": [
Expand Down
32 changes: 31 additions & 1 deletion targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {

Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down Expand Up @@ -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;
}

Expand Down