diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig index 346c5bc786..b1c9ec3ee5 100644 --- a/arch/risc-v/src/esp32c3/Kconfig +++ b/arch/risc-v/src/esp32c3/Kconfig @@ -307,11 +307,11 @@ if ESP32C3_UART1 config ESP32C3_UART1_TXPIN int "UART1 TX Pin" - default 18 + default 6 config ESP32C3_UART1_RXPIN int "UART1 RX Pin" - default 19 + default 7 endif # ESP32C3_UART1 diff --git a/arch/risc-v/src/esp32c3/esp32c3_lowputc.c b/arch/risc-v/src/esp32c3/esp32c3_lowputc.c index 7860d4afb6..1aa4fdd02d 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_lowputc.c +++ b/arch/risc-v/src/esp32c3/esp32c3_lowputc.c @@ -55,14 +55,15 @@ * Private Data ****************************************************************************/ -#ifdef HAVE_SERIAL_CONSOLE -# if defined(CONFIG_UART0_SERIAL_CONSOLE) +#ifdef HAVE_UART_DEVICE -static const struct esp32c3_uart_s g_console_config = +#ifdef CONFIG_ESP32C3_UART0 + +struct esp32c3_uart_s g_uart0_config = { .periph = ESP32C3_PERIPH_UART0, - .cpuint = -ENOMEM, .id = 0, + .cpuint = -ENOMEM, .irq = ESP32C3_IRQ_UART0, .baud = CONFIG_UART0_BAUD, .bits = CONFIG_UART0_BITS, @@ -75,13 +76,15 @@ static const struct esp32c3_uart_s g_console_config = .rxsig = U0RXD_IN_IDX, }; -# elif defined(CONFIG_UART1_SERIAL_CONSOLE) +#endif /* CONFIG_ESP32C3_UART0 */ -static const struct esp32c3_uart_s g_console_config = +#ifdef CONFIG_ESP32C3_UART1 + +struct esp32c3_uart_s g_uart1_config = { .periph = ESP32C3_PERIPH_UART1, - .cpuint = -ENOMEM, .id = 1, + .cpuint = -ENOMEM, .irq = ESP32C3_IRQ_UART1, .baud = CONFIG_UART1_BAUD, .bits = CONFIG_UART1_BITS, @@ -93,8 +96,9 @@ static const struct esp32c3_uart_s g_console_config = .rxpin = CONFIG_ESP32C3_UART1_RXPIN, .rxsig = U1RXD_IN_IDX, }; -#endif /* CONFIG_UART0_SERIAL_CONSOLE */ -#endif /* HAVE_SERIAL_CONSOLE */ + +#endif /* CONFIG_ESP32C3_UART1 */ +#endif /* HAVE_UART_DEVICE */ /**************************************************************************** * Public Functions @@ -267,21 +271,53 @@ uint32_t esp32c3_lowputc_get_sclk(const struct esp32c3_uart_s * priv) void esp32c3_lowputc_baud(const struct esp32c3_uart_s * priv) { - const int sclk_div = 1; - uint32_t sclk_freq = esp32c3_lowputc_get_sclk(priv); - uint32_t clk_div = ((sclk_freq) << 4) / priv->baud; - uint32_t int_part = clk_div >> 4; - uint32_t frag_part = clk_div & 0xf; + int sclk_div; + uint32_t sclk_freq; + uint32_t clk_div; + uint32_t int_part; + uint32_t frag_part; - /* The baud rate configuration register is divided into - * an integer part and a fractional part. + /* Get serial clock */ + + sclk_freq = esp32c3_lowputc_get_sclk(priv); + + /* Calculate integral part of the frequency divider factor. + * For low baud rates, the sclk must be less than half. + * For high baud rates, the sclk must be the higher. */ + sclk_div = DIV_UP(sclk_freq, MAX_UART_CLKDIV * priv->baud); + + /* Calculate the clock divisor to achieve the baud rate. + * baud = f/clk_div + * f = sclk_freq/sclk_div + * clk_div = 16*int_part + frag_part + * 16*int_part + frag_part = 16*(sclk_freq/sclk_div)/baud + */ + + clk_div = ((sclk_freq) << 4) / (priv->baud * sclk_div); + + /* Get the integer part of it. */ + + int_part = clk_div >> 4; + + /* Get the frag part of it. */ + + frag_part = clk_div & 0xf; + + /* Set integer part of the clock divisor for baud rate. */ + modifyreg32(UART_CLKDIV_REG(priv->id), UART_CLKDIV_M, int_part); + + /* Set decimal part of the clock divisor for baud rate. */ + modifyreg32(UART_CLKDIV_REG(priv->id), UART_CLKDIV_FRAG_M, - frag_part << UART_CLKDIV_FRAG_S); + (frag_part & UART_CLKDIV_FRAG_V) << UART_CLKDIV_FRAG_S); + + /* Set the the integral part of the frequency divider factor. */ + modifyreg32(UART_CLK_CONF_REG(priv->id), UART_SCLK_DIV_NUM_M, - (sclk_div - 1) << UART_SCLK_DIV_NUM_S); + (sclk_div - 1) << UART_SCLK_DIV_NUM_S); } /**************************************************************************** @@ -601,8 +637,8 @@ void esp32c3_lowputc_config_pins(const struct esp32c3_uart_s *priv) { /* Configure the pins */ - esp32c3_configgpio(priv->txpin, OUTPUT_FUNCTION_1); esp32c3_gpio_matrix_out(priv->txpin, priv->txsig, 0, 0); + esp32c3_configgpio(priv->txpin, OUTPUT_FUNCTION_1); esp32c3_configgpio(priv->rxpin, INPUT_FUNCTION_1); esp32c3_gpio_matrix_in(priv->rxpin, priv->rxsig, 0); @@ -646,13 +682,19 @@ void riscv_lowputc(char ch) { #ifdef HAVE_SERIAL_CONSOLE +# if defined(CONFIG_UART0_SERIAL_CONSOLE) + struct esp32c3_uart_s *priv = &g_uart0_config; +#elif defined (CONFIG_UART1_SERIAL_CONSOLE) + struct esp32c3_uart_s *priv = &g_uart1_config; +#endif + /* Wait until the TX FIFO has space to insert new char */ - while (esp32c3_lowputc_is_tx_fifo_full(&g_console_config)); + while (esp32c3_lowputc_is_tx_fifo_full(priv)); /* Then send the character */ - esp32c3_lowputc_send_byte(&g_console_config, ch); + esp32c3_lowputc_send_byte(priv, ch); #endif /* HAVE_CONSOLE */ } @@ -661,51 +703,25 @@ void riscv_lowputc(char ch) * Name: esp32c3_lowsetup * * Description: - * This performs basic initialization of the UART used for the serial - * console. Its purpose is to get the console output available as soon - * as possible. + * This performs only the basic configuration for UART pins. * ****************************************************************************/ void esp32c3_lowsetup(void) { - /* Enable and configure the selected console device */ +#ifndef CONFIG_SUPPRESS_UART_CONFIG -#if defined(HAVE_SERIAL_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) +#ifdef CONFIG_ESP32C3_UART0 - /* Initialize UART module */ + esp32c3_lowputc_config_pins(&g_uart0_config); - /* Configure the UART Baud Rate */ +#endif - esp32c3_lowputc_baud(&g_console_config); +#ifdef CONFIG_ESP32C3_UART1 - /* Set a mode */ + esp32c3_lowputc_config_pins(&g_uart1_config); - esp32c3_lowputc_normal_mode(&g_console_config); +#endif - /* Parity */ - - esp32c3_lowputc_parity(&g_console_config); - - /* Data Frame size */ - - esp32c3_lowputc_data_length(&g_console_config); - - /* Stop bit */ - - esp32c3_lowputc_stop_length(&g_console_config); - - /* No Tx idle interval */ - - esp32c3_lowputc_set_tx_idle_time(&g_console_config, 0); - - /* Set pins */ - - esp32c3_lowputc_config_pins(&g_console_config); - - /* Enable cores */ - - esp32c3_lowputc_enable_sclk(&g_console_config); - -#endif /* HAVE_SERIAL_CONSOLE && !CONFIG_SUPPRESS_UART_CONFIG */ +#endif /* !CONFIG_SUPPRESS_UART_CONFIG */ } diff --git a/arch/risc-v/src/esp32c3/esp32c3_lowputc.h b/arch/risc-v/src/esp32c3/esp32c3_lowputc.h index b7ee21a711..d429571906 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_lowputc.h +++ b/arch/risc-v/src/esp32c3/esp32c3_lowputc.h @@ -81,6 +81,11 @@ enum uart_stop_length #define UART_TX_FIFO_SIZE 128 #define UART_RX_FIFO_SIZE 128 +/* Maximum serial clock divisor for integer part */ + +#define MAX_UART_CLKDIV (BIT(12) - 1) +#define DIV_UP(a, b) (((a) + (b) - 1) / (b)) + /* Struct used to store uart driver information and to * manipulate uart driver */ @@ -102,6 +107,9 @@ struct esp32c3_uart_s uint8_t rxsig; /* RX signal */ }; +extern struct esp32c3_uart_s g_uart0_config; +extern struct esp32c3_uart_s g_uart1_config; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/arch/risc-v/src/esp32c3/esp32c3_serial.c b/arch/risc-v/src/esp32c3/esp32c3_serial.c index c55dbab12f..196a8b0ff8 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_serial.c +++ b/arch/risc-v/src/esp32c3/esp32c3_serial.c @@ -155,23 +155,6 @@ static struct uart_ops_s g_uart_ops = static char g_uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE]; static char g_uart0_txbuffer[CONFIG_UART0_TXBUFSIZE]; -static struct esp32c3_uart_s g_uart0_config = -{ - .periph = ESP32C3_PERIPH_UART0, - .id = 0, - .cpuint = -ENOMEM, - .irq = ESP32C3_IRQ_UART0, - .baud = CONFIG_UART0_BAUD, - .bits = CONFIG_UART0_BITS, - .parity = CONFIG_UART0_PARITY, - .stop_b2 = CONFIG_UART0_2STOP, - .int_pri = ESP32C3_INT_PRIO_DEF, - .txpin = CONFIG_ESP32C3_UART0_TXPIN, - .txsig = U0TXD_OUT_IDX, - .rxpin = CONFIG_ESP32C3_UART0_RXPIN, - .rxsig = U0RXD_IN_IDX, -}; - /* Fill only the requested fields */ static uart_dev_t g_uart0_dev = @@ -205,23 +188,6 @@ static uart_dev_t g_uart0_dev = static char g_uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE]; static char g_uart1_txbuffer[CONFIG_UART1_TXBUFSIZE]; -static struct esp32c3_uart_s g_uart1_config = -{ - .periph = ESP32C3_PERIPH_UART1, - .id = 1, - .cpuint = -ENOMEM, - .irq = ESP32C3_IRQ_UART1, - .baud = CONFIG_UART1_BAUD, - .bits = CONFIG_UART1_BITS, - .parity = CONFIG_UART1_PARITY, - .stop_b2 = CONFIG_UART1_2STOP, - .int_pri = ESP32C3_INT_PRIO_DEF, - .txpin = CONFIG_ESP32C3_UART1_TXPIN, - .txsig = U1TXD_OUT_IDX, - .rxpin = CONFIG_ESP32C3_UART1_RXPIN, - .rxsig = U1RXD_IN_IDX, -}; - /* Fill only the requested fields */ static uart_dev_t g_uart1_dev = @@ -319,6 +285,33 @@ static int esp32c3_setup(struct uart_dev_s *dev) /* Initialize UART module */ + /* Discard corrupt RX data and + * disable UART memory clock gate enable signal. + */ + + modifyreg32(UART_CONF0_REG(priv->id), UART_ERR_WR_MASK_M | + UART_MEM_CLK_EN_M, UART_ERR_WR_MASK_M); + + /* Define 0 as the threshold that means TX FIFO buffer is empty. */ + + modifyreg32(UART_CONF1_REG(priv->id), UART_TXFIFO_EMPTY_THRHD_M, 0); + + /* Define a threshold to trigger an RX FIFO FULL interrupt. + * Define just one byte to read data immediately. + */ + + modifyreg32(UART_CONF1_REG(priv->id), UART_RXFIFO_FULL_THRHD_M, + 1 << UART_RXFIFO_FULL_THRHD_S); + + /* Define the maximum FIFO size for RX and TX FIFO. + * That means, 1 block = 128 bytes. + * As a consequence, software serial FIFO can unload the bytes and + * not wait too much on polling activity. + */ + + modifyreg32(UART_MEM_CONF_REG(priv->id), UART_TX_SIZE_M | UART_RX_SIZE_M, + (1 << UART_TX_SIZE_S) | (1 << UART_RX_SIZE_S)); + /* Configure the UART Baud Rate */ esp32c3_lowputc_baud(priv); @@ -343,14 +336,15 @@ static int esp32c3_setup(struct uart_dev_s *dev) esp32c3_lowputc_set_tx_idle_time(priv, 0); - /* Set pins */ - - esp32c3_lowputc_config_pins(priv); - /* Enable cores */ esp32c3_lowputc_enable_sclk(priv); + /* Clear FIFOs */ + + esp32c3_lowputc_rst_txfifo(priv); + esp32c3_lowputc_rst_rxfifo(priv); + return OK; } @@ -371,18 +365,9 @@ static void esp32c3_shutdown(struct uart_dev_s *dev) { struct esp32c3_uart_s *priv = dev->priv; - /* Clear FIFOs */ - - esp32c3_lowputc_rst_txfifo(priv); - esp32c3_lowputc_rst_rxfifo(priv); - /* Disable ints */ esp32c3_lowputc_disable_all_uart_int(priv, NULL); - - /* Back pins to normal */ - - esp32c3_lowputc_restore_pins(priv); } /**************************************************************************** @@ -486,6 +471,7 @@ static void esp32c3_txint(struct uart_dev_s *dev, bool enable) /* Set to receive an interrupt when the TX holding register register * is empty */ + #ifndef CONFIG_SUPPRESS_SERIAL_INTS modifyreg32(UART_INT_ENA_REG(priv->id), ints_mask, ints_mask); #endif @@ -518,8 +504,9 @@ static void esp32c3_rxint(struct uart_dev_s *dev, bool enable) if (enable) { - /* Receive an interrupt when there is anything in the Rx data register - * (or an Rx timeout occurs). + /* Receive an interrupt when there is anything in the RX data register + * (or an RX timeout occurs). + * NOTE: RX timeout feature needs to be enabled. */ #ifndef CONFIG_SUPPRESS_SERIAL_INTS modifyreg32(UART_CONF1_REG(priv->id), UART_RX_TOUT_EN_M, @@ -883,15 +870,27 @@ static int esp32c3_ioctl(struct file *filep, int cmd, unsigned long arg) * ****************************************************************************/ -/* TODO */ - void riscv_earlyserialinit(void) { - /* I've been looking at others chips/arches and I noticed - * that _lowsetup performs almost the same of this func and it's - * called earlier than this one in _start - * So, I am not sure what to do here + /* NOTE: All GPIO configuration for the UARTs was performed in + * esp32c3_lowsetup */ + + /* Disable all UARTS interrupts */ + + esp32c3_lowputc_disable_all_uart_int(TTYS0_DEV.priv, NULL); +#ifdef TTYS1_DEV + esp32c3_lowputc_disable_all_uart_int(TTYS1_DEV.priv, NULL); +#endif + + /* Configure console in early step. + * Setup for other serials will be perfomed when the serial driver is + * open. + */ + +#ifdef HAVE_SERIAL_CONSOLE + esp32c3_setup(&CONSOLE_DEV); +#endif } #endif /* USE_EARLYSERIALINIT */ @@ -956,7 +955,7 @@ int up_putc(int ch) * Name: riscv_earlyserialinit, riscv_serialinit, and up_putc * * Description: - * stubs that may be needed. These stubs will be used if all UARTs are + * Stubs that may be needed. These stubs will be used if all UARTs are * disabled. In that case, the logic in common/up_initialize() is not * smart enough to know that there are not UARTs and will still expect * these interfaces to be provided. @@ -979,12 +978,6 @@ int up_putc(int ch) #endif /* HAVE_UART_DEVICE */ #else /* USE_SERIALDRIVER */ -/* Common initialization logic will not not know that the all of the UARTs - * have been disabled. So, as a result, we may still have to provide - * stub implementations of riscv_earlyserialinit(), riscv_serialinit(), and - * up_putc(). - */ - /**************************************************************************** * Name: up_putc * diff --git a/arch/risc-v/src/esp32c3/esp32c3_start.c b/arch/risc-v/src/esp32c3/esp32c3_start.c index 8bd2d3ac95..a10c2a5a93 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_start.c +++ b/arch/risc-v/src/esp32c3/esp32c3_start.c @@ -75,6 +75,12 @@ void __esp32c3_start(void) esp32c3_lowsetup(); +#ifdef USE_EARLYSERIALINIT + /* Perform early serial initialization */ + + riscv_earlyserialinit(); +#endif + showprogress('A'); /* Clear .bss. We'll do this inline (vs. calling memset) just to be