-
Notifications
You must be signed in to change notification settings - Fork 2.1k
cpu/esp32: add the new API function uart_mode to periph/uart #11231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6132c08
b9a8b98
ec013f7
217ccbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 */ | ||
|
|
@@ -66,31 +69,40 @@ 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 | ||
| #if defined(UART2_TXD) && defined(UART2_RXD) | ||
| { .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 | ||
|
|
@@ -101,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); | ||
|
|
@@ -154,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); | ||
|
|
@@ -296,6 +318,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; | ||
|
|
@@ -342,3 +370,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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the ifdef needed here since they are all MCU_ESP32 that use this file?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, at the moment. But, the UART source code is already compatible with that of the complete ESP8266 reimplemenation in PR #11108 (https://github.com/RIOT-OS/RIOT/blob/2f008018200c180a96f6457e7d0ec655b2209510/cpu/esp8266/periph/uart.c). To make planned deduplication easier, I'm already adapting the ESP32 code if I make changes. |
||
| 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; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be 2? Either that or say not implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it is a known hardware bug.
_uarts[uart].regs->conf0.stop_bit_numhas to be set to1if there is any stop bit. With_uarts[uart].regs->rs485_conf.dl1_enit is decided whether there are 1 or 2 stop bits.