Skip to content

Commit a8a7df0

Browse files
committed
Corrected serial_api - added waiting for TX completion in 'serial_putc' and before TX_COMPLETE callback, corrected pins configuration routines.
1 parent 32afc59 commit a8a7df0

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/serial_api.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,19 @@ void UART_IRQ_HANDLER(void)
178178

179179
#if DEVICE_SERIAL_ASYNCH
180180
if (UART_CB.tx_active) {
181-
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
182-
183-
nrf_uart_txd_set(UART_INSTANCE, UART_CB.tx_buffer[UART_CB.tx_pos]);
184-
if (++UART_CB.tx_pos >= UART_CB.tx_length) {
181+
if (++UART_CB.tx_pos <= UART_CB.tx_length) {
182+
// When there is still something to send, clear the TXDRDY event
183+
// and put next byte to transmitter.
184+
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
185+
nrf_uart_txd_set(UART_INSTANCE,
186+
UART_CB.tx_buffer[UART_CB.tx_pos]);
187+
}
188+
else {
189+
// When the TXDRDY event is set after the last byte to be sent
190+
// has been passed to the transmitter, the job is done and TX
191+
// complete can be indicated.
192+
// Don't clear the TXDRDY event, it needs to remain set for the
193+
// 'serial_writable' function to work properly.
185194
end_asynch_tx();
186195

187196
UART_CB.events_occured |= SERIAL_EVENT_TX_COMPLETE;
@@ -229,27 +238,29 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
229238
(tx == NC) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t)tx;
230239
UART_CB.pselrxd =
231240
(rx == NC) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t)rx;
241+
if (UART_CB.pseltxd != NRF_UART_PSEL_DISCONNECTED) {
242+
nrf_gpio_pin_set(UART_CB.pseltxd);
243+
nrf_gpio_cfg_output(UART_CB.pseltxd);
244+
}
245+
if (UART_CB.pselrxd != NRF_UART_PSEL_DISCONNECTED) {
246+
nrf_gpio_cfg_input(UART_CB.pselrxd, NRF_GPIO_PIN_NOPULL);
247+
}
248+
249+
// UART pins must only be configured when the peripheral is disabled.
250+
nrf_uart_disable(UART_INSTANCE);
251+
232252
if (UART_CB.initialized) {
233253
// Reconfigure RX/TX pins only.
234-
nrf_uart_txrx_pins_set(UART_INSTANCE,
235-
UART_CB.pseltxd, UART_CB.pselrxd);
254+
nrf_uart_txrx_pins_set(UART_INSTANCE, UART_CB.pseltxd, UART_CB.pselrxd);
255+
nrf_uart_enable(UART_INSTANCE);
236256
}
237257
else {
238-
if (UART_CB.pseltxd != NRF_UART_PSEL_DISCONNECTED) {
239-
nrf_gpio_pin_set(UART_CB.pseltxd);
240-
nrf_gpio_cfg_output(UART_CB.pseltxd);
241-
}
242-
if (UART_CB.pselrxd != NRF_UART_PSEL_DISCONNECTED) {
243-
nrf_gpio_cfg_input(UART_CB.pselrxd, NRF_GPIO_PIN_NOPULL);
244-
}
245-
246258
UART_CB.baudrate = UART_DEFAULT_BAUDRATE;
247259
UART_CB.parity = UART_DEFAULT_PARITY;
248260
UART_CB.hwfc = UART_DEFAULT_HWFC;
249261
UART_CB.pselcts = UART_DEFAULT_CTS;
250262
UART_CB.pselrts = UART_DEFAULT_RTS;
251263

252-
nrf_uart_enable(UART_INSTANCE);
253264
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
254265
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
255266
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTRX);
@@ -273,19 +284,23 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
273284
// Perform it with disconnected TX pin, so nothing actually comes out
274285
// of the device.
275286
nrf_uart_txrx_pins_disconnect(UART_INSTANCE);
287+
nrf_uart_hwfc_pins_disconnect(UART_INSTANCE);
288+
nrf_uart_enable(UART_INSTANCE);
276289
nrf_uart_txd_set(UART_INSTANCE, 0);
277290
while (!nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY)) {
278291
}
292+
nrf_uart_disable(UART_INSTANCE);
279293

280294
// Now everything is prepared to set the default configuration and
281295
// connect the peripheral to actual pins.
296+
nrf_uart_txrx_pins_set(UART_INSTANCE, UART_CB.pseltxd, UART_CB.pselrxd);
282297
nrf_uart_baudrate_set(UART_INSTANCE, UART_CB.baudrate);
283298
nrf_uart_configure(UART_INSTANCE, UART_CB.parity, UART_CB.hwfc);
284299
if (UART_CB.hwfc == NRF_UART_HWFC_ENABLED) {
285300
serial_set_flow_control(obj, FlowControlRTSCTS,
286301
UART_CB.pselrts, UART_CB.pselcts);
287302
}
288-
nrf_uart_txrx_pins_set(UART_INSTANCE, UART_CB.pseltxd, UART_CB.pselrxd);
303+
nrf_uart_enable(UART_INSTANCE);
289304

290305
UART_CB.initialized = true;
291306
}
@@ -469,6 +484,9 @@ void serial_putc(serial_t *obj, int c)
469484

470485
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
471486
nrf_uart_txd_set(UART_INSTANCE, (uint8_t)c);
487+
// Wait until sending is completed.
488+
while (!nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY)) {
489+
}
472490
}
473491

474492
int serial_readable(serial_t *obj)
@@ -527,7 +545,9 @@ void serial_set_flow_control(serial_t *obj, FlowControl type,
527545
if (UART_CB.pselcts != NRF_UART_PSEL_DISCONNECTED) {
528546
nrf_gpio_cfg_input(UART_CB.pselcts, NRF_GPIO_PIN_NOPULL);
529547
}
548+
nrf_uart_disable(UART_INSTANCE);
530549
nrf_uart_hwfc_pins_set(UART_INSTANCE, UART_CB.pselrts, UART_CB.pselcts);
550+
nrf_uart_enable(UART_INSTANCE);
531551
}
532552

533553
void serial_clear(serial_t *obj) {

0 commit comments

Comments
 (0)