Skip to content

Commit 9ce3965

Browse files
committed
Add flow control for RX FIFO filling
When the RX FIFO is nearly full use flow control to stop receiving data.
1 parent 59bb79b commit 9ce3965

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
#define UART1_FIFO_BUFFER_SIZE MBED_CONF_NORDIC_UART_1_FIFO_SIZE
8989
#define DMA_BUFFER_SIZE 1
9090
#define NUMBER_OF_BANKS 2
91+
#define FIFO_MIN 3
9192

9293
/***
9394
* _______ _ __
@@ -144,8 +145,10 @@ typedef struct {
144145
bool callback_posted;
145146
uint8_t active_bank;
146147
nrf_atfifo_t *fifo;
148+
uint32_t fifo_free_count;
147149
nrf_ppi_channel_t ppi_rts;
148150
nrf_drv_gpiote_pin_t rts;
151+
bool rx_suspended;
149152
} nordic_uart_state_t;
150153

151154
/**
@@ -434,6 +437,7 @@ static void nordic_nrf5_uart_event_handler_endrx(int instance)
434437
/* Copy 1 byte from DMA buffer and commit to FIFO buffer. */
435438
*byte = nordic_nrf5_uart_state[instance].buffer[active_bank][index];
436439
nrf_atfifo_item_put(nordic_nrf5_uart_state[instance].fifo, &fifo_context);
440+
core_util_atomic_decr_u32(&nordic_nrf5_uart_state[instance].fifo_free_count, 1);
437441

438442
} else {
439443

@@ -463,9 +467,15 @@ static void nordic_nrf5_uart_event_handler_rxstarted(int instance)
463467
uint8_t next_bank = nordic_nrf5_uart_state[instance].active_bank ^ 0x01;
464468

465469
nrf_uarte_rx_buffer_set(nordic_nrf5_uart_register[instance], nordic_nrf5_uart_state[instance].buffer[next_bank], DMA_BUFFER_SIZE);
466-
/* Clear rts if flow control is enabled since we are ready to recieve the next byte */
467-
if (nordic_nrf5_uart_state[instance].owner->rts != NRF_UART_PSEL_DISCONNECTED) {
468-
nrf_drv_gpiote_clr_task_trigger((nrf_drv_gpiote_pin_t)nordic_nrf5_uart_state[instance].owner->rts);
470+
if (nordic_nrf5_uart_state[instance].rts != NRF_UART_PSEL_DISCONNECTED) {
471+
if (nordic_nrf5_uart_state[instance].fifo_free_count > FIFO_MIN) {
472+
/* Clear rts since we are ready to receive the next byte */
473+
nrf_drv_gpiote_clr_task_trigger(nordic_nrf5_uart_state[instance].rts);
474+
} else {
475+
/* Suspend reception since there isn't enough buffer space.
476+
* The function serial_getc will restart reception. */
477+
nordic_nrf5_uart_state[instance].rx_suspended = true;
478+
}
469479
}
470480
}
471481

@@ -697,6 +707,7 @@ static void nordic_nrf5_uart_configure_rx(int instance)
697707

698708
/* Clear FIFO buffer. */
699709
nrf_atfifo_clear(nordic_nrf5_uart_state[instance].fifo);
710+
nordic_nrf5_uart_state[instance].fifo_free_count = UART0_FIFO_BUFFER_SIZE;
700711

701712
/* Clear Rx related events. */
702713
nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXSTARTED);
@@ -716,6 +727,9 @@ static void nordic_nrf5_uart_configure_rx(int instance)
716727
/* Set non-asynchronous mode. */
717728
nordic_nrf5_uart_state[instance].rx_asynch = false;
718729

730+
/* Clear suspend condition */
731+
nordic_nrf5_uart_state[instance].rx_suspended = false;
732+
719733
/* Enable interrupts again. */
720734
nrf_uarte_int_enable(nordic_nrf5_uart_register[instance], NRF_UARTE_INT_RXSTARTED_MASK |
721735
NRF_UARTE_INT_ENDRX_MASK);
@@ -743,6 +757,9 @@ static void nordic_nrf5_uart_configure_rx_asynch(int instance)
743757
/* Set asynchronous mode. */
744758
nordic_nrf5_uart_state[instance].rx_asynch = true;
745759

760+
/* Clear suspend condition */
761+
nordic_nrf5_uart_state[instance].rx_suspended = false;
762+
746763
/* Enable Rx interrupt. */
747764
nrf_uarte_int_enable(nordic_nrf5_uart_register[instance], NRF_UARTE_INT_ENDRX_MASK);
748765
}
@@ -1304,6 +1321,11 @@ int serial_getc(serial_t *obj)
13041321
nrf_atfifo_item_get_t context;
13051322
uint8_t *byte = (uint8_t *) nrf_atfifo_item_get(fifo, &context);
13061323
nrf_atfifo_item_free(fifo, &context);
1324+
core_util_atomic_incr_u32(&nordic_nrf5_uart_state[instance].fifo_free_count, 1);
1325+
if (nordic_nrf5_uart_state[instance].rx_suspended) {
1326+
nordic_nrf5_uart_state[instance].rx_suspended = false;
1327+
nrf_drv_gpiote_clr_task_trigger(nordic_nrf5_uart_state[instance].rts);
1328+
}
13071329

13081330
return *byte;
13091331
}

0 commit comments

Comments
 (0)