diff --git a/drivers/include/periph/uart.h b/drivers/include/periph/uart.h index 87bbc965c1..b57e4ea558 100644 --- a/drivers/include/periph/uart.h +++ b/drivers/include/periph/uart.h @@ -177,7 +177,7 @@ typedef enum { #endif /** - * @brief Initialize a given UART device + * @brief Initialize and acquire a given UART device * * The UART device will be initialized with the following configuration: * - 8 data bits @@ -188,6 +188,14 @@ typedef enum { * If no callback parameter is given (rx_cb := NULL), the UART will be * initialized in TX only mode. * + * @pre The caller is not calling `uart_init()` twice without a call of + * to @ref uart_poweroff in between. + * + * @note This may block if the UART is already acquired until it is released. + * This allows sharing the underlying peripheral to provide other + * serial interfaces (e.g. if the peripheral can also provide SPI, I2C, + * etc.) + * * @param[in] uart UART device to initialize * @param[in] baud desired symbol rate in baud * @param[in] rx_cb receive callback, executed in interrupt context once @@ -401,14 +409,17 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, void uart_write(uart_t uart, const uint8_t *data, size_t len); /** - * @brief Power on the given UART device + * @brief Power on and acquire the given UART device + * + * The UART will resume with the configuration it was most recently configured + * with. * * @param[in] uart the UART device to power on */ void uart_poweron(uart_t uart); /** - * @brief Power off the given UART device + * @brief Power off and release the given UART device * * @param[in] uart the UART device to power off */ diff --git a/tests/periph/uart/Makefile b/tests/periph/uart/Makefile index b60500e81f..c8ec516c0f 100644 --- a/tests/periph/uart/Makefile +++ b/tests/periph/uart/Makefile @@ -6,6 +6,7 @@ FEATURES_OPTIONAL += periph_uart_collision FEATURES_OPTIONAL += periph_uart_modecfg FEATURES_OPTIONAL += periph_uart_rxstart_irq +USEMODULE += bitfield USEMODULE += shell USEMODULE += ztimer_msec diff --git a/tests/periph/uart/main.c b/tests/periph/uart/main.c index 6c5a17a6ea..b7b36f5976 100644 --- a/tests/periph/uart/main.c +++ b/tests/periph/uart/main.c @@ -22,11 +22,12 @@ #include #include +#include "bitfield.h" +#include "msg.h" +#include "periph/uart.h" +#include "ringbuffer.h" #include "shell.h" #include "thread.h" -#include "msg.h" -#include "ringbuffer.h" -#include "periph/uart.h" #include "ztimer.h" #ifdef MODULE_STDIO_UART @@ -86,6 +87,8 @@ static uart_stop_bits_t stop_bits_lut[] = { UART_STOP_BITS_1, UART_STOP_BITS_2 } static int stop_bits_lut_len = ARRAY_SIZE(stop_bits_lut); #endif +static BITFIELD(uarts_initialized_mask, UART_NUMOF); + static int parse_dev(char *arg) { unsigned dev = atoi(arg); @@ -180,6 +183,9 @@ static int _self_test(uart_t dev, unsigned baud) uart_collision_detect_disable(dev); #endif + uart_poweroff(UART_DEV(dev)); + + test_mode = false; return 0; failure: @@ -248,6 +254,11 @@ static int cmd_init(int argc, char **argv) } baud = strtol(argv[2], NULL, 0); + if (bf_isset(uarts_initialized_mask, dev)) { + uart_poweroff(UART_DEV(dev)); + bf_unset(uarts_initialized_mask, dev); + } + /* initialize UART */ res = uart_init(UART_DEV(dev), baud, rx_cb, (void *)(intptr_t)dev); if (res == UART_NOBAUD) { @@ -260,6 +271,8 @@ static int cmd_init(int argc, char **argv) } printf("Success: Initialized UART_DEV(%i) at BAUD %"PRIu32"\n", dev, baud); + bf_set(uarts_initialized_mask, dev); + /* also test if poweron() and poweroff() work (or at least don't break * anything) */ sleep_test(dev, UART_DEV(dev)); @@ -396,6 +409,11 @@ static int cmd_test(int argc, char **argv) puts("[START]"); + if (bf_isset(uarts_initialized_mask, dev)) { + uart_poweroff(UART_DEV(dev)); + bf_unset(uarts_initialized_mask, dev); + } + /* run self test with different baud rates */ test_mode = true; for (unsigned i = 1; i <= 12; ++i) {