diff --git a/cpu/nrf5x_common/periph/uart.c b/cpu/nrf5x_common/periph/uart.c index 6c223c73b9bfc..28225358e995e 100644 --- a/cpu/nrf5x_common/periph/uart.c +++ b/cpu/nrf5x_common/periph/uart.c @@ -28,6 +28,7 @@ * @} */ +#include #include #include @@ -99,6 +100,39 @@ enum { UART_ISR_NUMOF, }; +static inline void set_power(uart_t uart, bool value) +{ +#ifdef UARTE_PRESENT + const uint32_t enable_mask = UARTE_ENABLE_ENABLE_Enabled; + const uint32_t disable_mask = UARTE_ENABLE_ENABLE_Disabled; +#else + const uint32_t enable_mask = UART_ENABLE_ENABLE_Enabled; + const uint32_t disable_mask = UART_ENABLE_ENABLE_Disabled; +#endif + UART_TYPE *dev = uart_config[uart].dev; + + if (value) { + dev->ENABLE = enable_mask; + } + else { + dev->ENABLE = disable_mask; + } +#ifndef UARTE_PRESENT + dev->POWER = value; +#endif +} + +static inline bool get_power(uart_t uart) +{ +#ifdef UARTE_PRESENT + const uint32_t disable_mask = UARTE_ENABLE_ENABLE_Disabled; +#else + const uint32_t disable_mask = UART_ENABLE_ENABLE_Disabled; +#endif + UART_TYPE *dev = uart_config[uart].dev; + return dev->ENABLE != disable_mask; +} + int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { /* ensure the ISR names have been defined as needed */ @@ -206,7 +240,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) } /* enable the UART device */ - dev->ENABLE = ENABLE_ON; + set_power(uart, true); #ifdef MODULE_PERIPH_UART_NONBLOCKING /* set up the TX buffer */ @@ -242,6 +276,7 @@ void uart_poweron(uart_t uart) if (isr_ctx[uart].rx_cb) { uart_config[uart].dev->TASKS_STARTRX = 1; + set_power(uart, false); } } @@ -250,6 +285,7 @@ void uart_poweroff(uart_t uart) assume((unsigned)uart < UART_NUMOF); uart_config[uart].dev->TASKS_STOPRX = 1; + set_power(uart, false); } /* Unify macro names across nRF51 (UART) and nRF52 and newer (UARTE) */ @@ -335,6 +371,10 @@ static void _write_buf(uart_t uart, const uint8_t *data, size_t len) void uart_write(uart_t uart, const uint8_t *data, size_t len) { assume((unsigned)uart < UART_NUMOF); + if (!get_power(uart)) { + /* Device is powered down. Writing anyway would deadlock */ + return; + } #ifdef MODULE_PERIPH_UART_NONBLOCKING for (size_t i = 0; i < len; i++) { /* in IRQ or interrupts disabled */