Skip to content

Commit 3bdbccb

Browse files
committed
Corrected serial_api implementation, so 'serial_putc' no longer requires enabled interrupts.
1 parent 8249a7f commit 3bdbccb

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

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

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "app_util_platform.h"
2222
#include "nrf_gpio.h"
2323

24+
#if DEVICE_SERIAL
25+
2426
#if DEVICE_SERIAL_ASYNCH
2527
#define SERIAL_S(obj) (&obj->serial)
2628
#else
@@ -211,8 +213,10 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
211213
UART_CB.initialized = true;
212214
nrf_drv_uart_rx_enable();
213215

214-
stdio_uart_inited = 1;
215-
memcpy(&stdio_uart, obj, sizeof(serial_t));
216+
if (tx == STDIO_UART_TX && rx == STDIO_UART_RX) {
217+
stdio_uart_inited = 1;
218+
memcpy(&stdio_uart, obj, sizeof(serial_t));
219+
}
216220
}
217221
else {
218222
error("UART init failure.");
@@ -225,6 +229,8 @@ void serial_free(serial_t *obj)
225229
if (UART_CB.initialized) {
226230
nrf_drv_uart_uninit();
227231
UART_CB.initialized = false;
232+
233+
stdio_uart_inited = 0;
228234
}
229235
}
230236

@@ -240,32 +246,40 @@ int serial_writable(serial_t *obj)
240246
int serial_readable(serial_t *obj)
241247
{
242248
(void)obj;
243-
return nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
249+
return (!UART_CB.rx_active &&
250+
nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY));
244251
}
245252

246253
void serial_putc(serial_t *obj, int c)
247254
{
248255
(void)obj;
249-
UART_CB.async_mode = false;
250-
UART_CB.tx_active = true;
251-
uint8_t data = c;
252-
nrf_drv_uart_tx(&data, 1);
253256

254-
while (UART_CB.tx_active) {
257+
// Interrupt on the TXDRDY event must be temporarily disabled, otherwise
258+
// the driver would try to handle (and clear) this event in the interrupt
259+
// handler.
260+
nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
261+
262+
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTTX);
263+
nrf_uart_txd_set(UART_INSTANCE, (uint8_t)c);
264+
while (!nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY)) {
255265
}
266+
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STOPTX);
267+
268+
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
269+
nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
256270
}
257271

258272
int serial_getc(serial_t *obj)
259273
{
260274
(void)obj;
261-
UART_CB.async_mode = false;
262-
UART_CB.rx_active = true;
263-
uint8_t data;
264-
nrf_drv_uart_rx(&data, 1);
265275

266-
while (UART_CB.rx_active) {
276+
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTRX);
277+
while (!nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY)) {
267278
}
268-
return (int)data;
279+
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STOPRX);
280+
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
281+
282+
return nrf_uart_rxd_get(UART_INSTANCE);
269283
}
270284

271285
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
@@ -467,3 +481,5 @@ void serial_clear(serial_t *obj)
467481
{
468482
(void)obj;
469483
}
484+
485+
#endif // DEVICE_SERIAL

0 commit comments

Comments
 (0)