risc-v/esp32-c3: Fixes gargabe UART issue, refactors serial driver, changes default pins of UART 1 and fixes low baud rate issue.
This commit is contained in:
parent
3c30c8b90b
commit
0926e7c578
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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
|
||||
****************************************************************************/
|
||||
|
@ -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 <chips>_lowsetup performs almost the same of this func and it's
|
||||
* called earlier than this one in <chip>_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
|
||||
*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user