Skip to content

Commit 2c4cfe1

Browse files
committed
nrf52820_hic: Port #840 and #842 UART fixes to nrf52820
1 parent 92aa678 commit 2c4cfe1

File tree

1 file changed

+49
-11
lines changed
  • source/hic_hal/nordic/nrf52820

1 file changed

+49
-11
lines changed

source/hic_hal/nordic/nrf52820/uart.c

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ circ_buf_t read_buffer;
4545
uint8_t read_buffer_data[BUFFER_SIZE];
4646

4747
struct {
48+
// Number of bytes pending to be transferred. This is 0 if there is no
49+
// ongoing transfer and the uart_handler processed the last transfer.
50+
volatile uint32_t tx_size;
51+
4852
uint8_t rx;
49-
uint8_t tx;
50-
uint8_t tx_active;
5153
} cb_buf;
5254

5355
void uart_handler(uint32_t event);
@@ -61,6 +63,7 @@ void clear_buffers(void)
6163
int32_t uart_initialize(void)
6264
{
6365
clear_buffers();
66+
cb_buf.tx_size = 0;
6467
Driver_USART0.Initialize(uart_handler);
6568
Driver_USART0.PowerControl(ARM_POWER_FULL);
6669

@@ -70,8 +73,11 @@ int32_t uart_initialize(void)
7073
int32_t uart_uninitialize(void)
7174
{
7275
USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0);
76+
USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U);
77+
Driver_USART0.PowerControl(ARM_POWER_OFF);
7378
Driver_USART0.Uninitialize();
7479
clear_buffers();
80+
cb_buf.tx_size = 0;
7581

7682
return 1;
7783
}
@@ -153,6 +159,11 @@ int32_t uart_set_configuration(UART_Configuration *config)
153159

154160
NVIC_DisableIRQ(USART_IRQ);
155161
clear_buffers();
162+
163+
// If there was no Receive() call in progress aborting it is harmless.
164+
USART_INSTANCE.Control(ARM_USART_CONTROL_RX, 0U);
165+
USART_INSTANCE.Control(ARM_USART_ABORT_RECEIVE, 0U);
166+
156167
uint32_t r = USART_INSTANCE.Control(control, config->Baudrate);
157168
if (r != ARM_DRIVER_OK) {
158169
return 0;
@@ -177,10 +188,42 @@ int32_t uart_write_free(void)
177188
return circ_buf_count_free(&write_buffer);
178189
}
179190

191+
// Start a new TX transfer if there are bytes pending to be transferred on the
192+
// write_buffer buffer. The transferred bytes are not removed from the circular
193+
// by this function, only the event handler will remove them once the transfer
194+
// is done.
195+
static void uart_start_tx_transfer() {
196+
uint32_t tx_size = 0;
197+
const uint8_t* buf = circ_buf_peek(&write_buffer, &tx_size);
198+
if (tx_size > BUFFER_SIZE / 4) {
199+
// The bytes being transferred remain on the circular buffer memory
200+
// until the transfer is done. Limiting the UART transfer size
201+
// allows the uart_handler to clear those bytes earlier.
202+
tx_size = BUFFER_SIZE / 4;
203+
}
204+
cb_buf.tx_size = tx_size;
205+
if (tx_size) {
206+
USART_INSTANCE.Send(buf, tx_size);
207+
}
208+
}
209+
180210
int32_t uart_write_data(uint8_t *data, uint16_t size)
181211
{
212+
if (size == 0) {
213+
return 0;
214+
}
215+
182216
uint32_t cnt = circ_buf_write(&write_buffer, data, size);
183-
NVIC_SetPendingIRQ(USART_IRQ);
217+
if (cb_buf.tx_size == 0) {
218+
// There's no pending transfer and the value of cb_buf.tx_size will not
219+
// change to non-zero by the event handler once it is zero. Note that it
220+
// is entirely possible that we transferred all the bytes we added to
221+
// the circular buffer in this function by the time we are in this
222+
// branch, in that case uart_start_tx_transfer() would not schedule any
223+
// transfer.
224+
uart_start_tx_transfer();
225+
}
226+
184227
return cnt;
185228
}
186229

@@ -202,13 +245,8 @@ void uart_handler(uint32_t event) {
202245
USART_INSTANCE.Receive(&(cb_buf.rx), 1);
203246
}
204247

205-
if ((event & ARM_USART_EVENT_SEND_COMPLETE) || !cb_buf.tx_active) {
206-
if (circ_buf_count_used(&write_buffer) > 0) {
207-
cb_buf.tx_active = true;
208-
cb_buf.tx = circ_buf_pop(&write_buffer);
209-
USART_INSTANCE.Send(&(cb_buf.tx), 1);
210-
} else {
211-
cb_buf.tx_active = false;
212-
}
248+
if (event & ARM_USART_EVENT_SEND_COMPLETE) {
249+
circ_buf_pop_n(&write_buffer, cb_buf.tx_size);
250+
uart_start_tx_transfer();
213251
}
214252
}

0 commit comments

Comments
 (0)