From 6132c08a902954ab62b8f524e6b9ba75088e723b Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Thu, 21 Mar 2019 15:13:35 +0100 Subject: [PATCH 1/4] cpu/esp32: add config members for uart_mode Add data members to the UART device configuration data structure that are needed by uart_mode API function. --- cpu/esp32/periph/uart.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cpu/esp32/periph/uart.c b/cpu/esp32/periph/uart.c index e2b61f0297..50504c41e6 100644 --- a/cpu/esp32/periph/uart.c +++ b/cpu/esp32/periph/uart.c @@ -52,12 +52,15 @@ struct uart_hw_t { uart_dev_t* regs; /* pointer to register data struct of the UART device */ uint8_t pin_txd; /* TxD pin */ uint8_t pin_rxd; /* RxD pin */ + bool used; /* indicates whether UART is used */ + uint32_t baudrate; /* used baudrate */ + uart_data_bits_t data; /* used data bits */ + uart_stop_bits_t stop; /* used stop bits */ + uart_parity_t parity; /* used parity bits */ + uart_isr_ctx_t isr_ctx; /* callback functions */ uint8_t signal_txd; /* TxD signal from the controller */ uint8_t signal_rxd; /* RxD signal to the controller */ - uint32_t baudrate; /* used baudrate */ - bool used; /* indicates whether UART is used */ uint8_t int_src; /* peripheral interrupt source used by the UART device */ - uart_isr_ctx_t isr_ctx; /* callback functions */ }; /* hardware ressources */ From b9a8b98a9bb4dc79a60ba3169f4c2614d343f61d Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Thu, 21 Mar 2019 15:15:58 +0100 Subject: [PATCH 2/4] cpu/esp32: add config member values for uart_mode Set default values for additional data members of UART device configuration data structure that are needed by uart_mode API function. --- cpu/esp32/periph/uart.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cpu/esp32/periph/uart.c b/cpu/esp32/periph/uart.c index 50504c41e6..0b3f44287c 100644 --- a/cpu/esp32/periph/uart.c +++ b/cpu/esp32/periph/uart.c @@ -69,20 +69,26 @@ static struct uart_hw_t _uarts[] = { .regs = &UART0, .pin_txd = GPIO1, .pin_rxd = GPIO3, + .used = false, + .baudrate = STDIO_UART_BAUDRATE, + .data = UART_DATA_BITS_8, + .stop = UART_STOP_BITS_1, + .parity = UART_PARITY_NONE, .signal_txd = U0TXD_OUT_IDX, .signal_rxd = U0RXD_IN_IDX, - .baudrate = STDIO_UART_BAUDRATE, - .used = false, .int_src = ETS_UART0_INTR_SOURCE }, #if defined(UART1_TXD) && defined(UART1_RXD) { .regs = &UART1, .pin_txd = UART1_TXD, .pin_rxd = UART1_RXD, + .used = false, + .baudrate = STDIO_UART_BAUDRATE, + .data = UART_DATA_BITS_8, + .stop = UART_STOP_BITS_1, + .parity = UART_PARITY_NONE, .signal_txd = U1TXD_OUT_IDX, .signal_rxd = U1RXD_IN_IDX, - .baudrate = STDIO_UART_BAUDRATE, - .used = false, .int_src = ETS_UART1_INTR_SOURCE }, #endif @@ -90,10 +96,13 @@ static struct uart_hw_t _uarts[] = { { .regs = &UART2, .pin_txd = UART2_TXD, .pin_rxd = UART2_RXD, + .used = false, + .baudrate = STDIO_UART_BAUDRATE, + .data = UART_DATA_BITS_8, + .stop = UART_STOP_BITS_1, + .parity = UART_PARITY_NONE, .signal_txd = U2TXD_OUT_IDX, .signal_rxd = U2RXD_IN_IDX, - .baudrate = STDIO_UART_BAUDRATE, - .used = false, .int_src = ETS_UART2_INTR_SOURCE } #endif From ec013f74a708ff1a4700d0ad00918488ff0adbf1 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 26 Mar 2019 10:19:42 +0100 Subject: [PATCH 3/4] cpu/esp32: add internal _uart_set_mode function Configuration of UART mode is realized by an internal function which is also used by UART initialization function. --- cpu/esp32/periph/uart.c | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/cpu/esp32/periph/uart.c b/cpu/esp32/periph/uart.c index 0b3f44287c..3d3e3eaf28 100644 --- a/cpu/esp32/periph/uart.c +++ b/cpu/esp32/periph/uart.c @@ -113,6 +113,8 @@ extern void uart_div_modify(uint8_t uart_no, uint32_t div); /* forward declaration of internal functions */ static int _uart_set_baudrate(uart_t uart, uint32_t baudrate); +static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits, + uart_parity_t parity, uart_stop_bits_t stop_bits); static uint8_t IRAM _uart_rx_one_char (uart_t uart); static void _uart_tx_one_char(uart_t uart, uint8_t data); static void _uart_intr_enable (uart_t uart); @@ -308,6 +310,12 @@ static void _uart_config (uart_t uart) return; } + /* set number of data bits, stop bits and parity mode */ + if (_uart_set_mode(uart, _uarts[uart].data, _uarts[uart].stop, + _uarts[uart].parity) != UART_OK) { + return; + } + /* reset the FIFOs */ _uarts[uart].regs->conf0.rxfifo_rst = 1; _uarts[uart].regs->conf0.rxfifo_rst = 0; @@ -354,3 +362,74 @@ static int _uart_set_baudrate(uart_t uart, uint32_t baudrate) critical_exit(); return UART_OK; } + +static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits, + uart_parity_t parity, uart_stop_bits_t stop_bits) +{ + DEBUG("%s uart=%d, data_bits=%d parity=%d stop_bits=%d\n", __func__, + uart, data_bits, parity, stop_bits); + + CHECK_PARAM_RET (uart < UART_NUMOF, UART_NODEV); + + critical_enter(); + + /* set number of data bits */ + switch (data_bits) { + case UART_DATA_BITS_5: _uarts[uart].regs->conf0.bit_num = 0; break; + case UART_DATA_BITS_6: _uarts[uart].regs->conf0.bit_num = 1; break; + case UART_DATA_BITS_7: _uarts[uart].regs->conf0.bit_num = 2; break; + case UART_DATA_BITS_8: _uarts[uart].regs->conf0.bit_num = 3; break; + default: LOG_TAG_ERROR("uart", "invalid number of data bits\n"); + critical_exit(); + return UART_NOMODE; + } + /* store changed number of data bits in configuration */ + _uarts[uart].data = data_bits; + + /* set number of stop bits */ + #ifdef MCU_ESP32 + /* workaround for hardware bug when stop bits are set to 2-bit mode. */ + switch (stop_bits) { + case UART_STOP_BITS_1: _uarts[uart].regs->conf0.stop_bit_num = 1; + _uarts[uart].regs->rs485_conf.dl1_en = 0; + break; + case UART_STOP_BITS_2: _uarts[uart].regs->conf0.stop_bit_num = 1; + _uarts[uart].regs->rs485_conf.dl1_en = 1; + break; + default: LOG_TAG_ERROR("uart", "invalid number of stop bits\n"); + critical_exit(); + return UART_NOMODE; + } + #else + switch (stop_bits) { + case UART_STOP_BITS_1: _uarts[uart].regs->conf0.stop_bit_num = 1; break; + case UART_STOP_BITS_2: _uarts[uart].regs->conf0.stop_bit_num = 3; break; + default: LOG_TAG_ERROR("uart", "invalid number of stop bits\n"); + critical_exit(); + return UART_NOMODE; + } + #endif + + /* store changed number of stop bits in configuration */ + _uarts[uart].stop = stop_bits; + + /* set parity mode */ + switch (parity) { + case UART_PARITY_NONE: _uarts[uart].regs->conf0.parity_en = 0; + break; + case UART_PARITY_EVEN: _uarts[uart].regs->conf0.parity = 0; + _uarts[uart].regs->conf0.parity_en = 1; + break; + case UART_PARITY_ODD: _uarts[uart].regs->conf0.parity = 1; + _uarts[uart].regs->conf0.parity_en = 1; + break; + default: LOG_TAG_ERROR("uart", "invalid or unsupported parity mode\n"); + critical_exit(); + return UART_NOMODE; + } + /* store changed parity in configuration */ + _uarts[uart].parity = parity; + + critical_exit(); + return UART_OK; +} From 217ccbe1c4d7e2b81cd9d0dfcf7c6f6dae9b4a5b Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 26 Mar 2019 10:20:55 +0100 Subject: [PATCH 4/4] cpu/esp32: add new uart_mode API function The internal _uart_set_mode function is exposed if module periph_uart_modecfg is enabled. --- boards/common/esp32/Makefile.features | 1 + cpu/esp32/periph/uart.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/boards/common/esp32/Makefile.features b/boards/common/esp32/Makefile.features index 5557a521bb..963790ff90 100644 --- a/boards/common/esp32/Makefile.features +++ b/boards/common/esp32/Makefile.features @@ -5,6 +5,7 @@ include $(RIOTCPU)/esp32/Makefile.features FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_gpio_irq FEATURES_PROVIDED += periph_uart +FEATURES_PROVIDED += periph_uart_modecfg # other features provided by all boards FEATURES_PROVIDED += esp_spiffs diff --git a/cpu/esp32/periph/uart.c b/cpu/esp32/periph/uart.c index 3d3e3eaf28..366dc5d6f4 100644 --- a/cpu/esp32/periph/uart.c +++ b/cpu/esp32/periph/uart.c @@ -168,6 +168,14 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) return UART_OK; } +#if MODULE_PERIPH_UART_MODECFG +int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, + uart_stop_bits_t stop_bits) +{ + return _uart_set_mode(uart, data_bits, parity, stop_bits); +} +#endif + void uart_write(uart_t uart, const uint8_t *data, size_t len) { CHECK_PARAM (uart < UART_NUMOF);