| /**************************************************************************** |
| * arch/xtensa/src/esp32s3/esp32s3_lowputc.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| #include <nuttx/arch.h> |
| #include <nuttx/irq.h> |
| |
| #include <sys/types.h> |
| #include <stdint.h> |
| #include <stdbool.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <assert.h> |
| #include <errno.h> |
| #include <debug.h> |
| |
| #include <arch/irq.h> |
| |
| #include "chip.h" |
| #include "xtensa.h" |
| |
| #include "hardware/esp32s3_pinmap.h" |
| #include "hardware/esp32s3_system.h" |
| #include "hardware/esp32s3_uart.h" |
| #include "hardware/esp32s3_soc.h" |
| |
| #include "esp32s3_clockconfig.h" |
| #include "esp32s3_gpio.h" |
| |
| #include "esp32s3_lowputc.h" |
| |
| #include "esp32s3_periph.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Private Types |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| #ifdef HAVE_UART_DEVICE |
| |
| #ifdef CONFIG_ESP32S3_UART0 |
| |
| struct esp32s3_uart_s g_uart0_config = |
| { |
| .periph = ESP32S3_PERIPH_UART0, |
| .id = 0, |
| .cpuint = -ENOMEM, |
| .irq = ESP32S3_IRQ_UART0, |
| .baud = CONFIG_UART0_BAUD, |
| .bits = CONFIG_UART0_BITS, |
| .parity = CONFIG_UART0_PARITY, |
| .stop_b2 = CONFIG_UART0_2STOP, |
| .int_pri = ESP32S3_INT_PRIO_DEF, |
| .txpin = CONFIG_ESP32S3_UART0_TXPIN, |
| .txsig = U0TXD_OUT_IDX, |
| .rxpin = CONFIG_ESP32S3_UART0_RXPIN, |
| .rxsig = U0RXD_IN_IDX, |
| #ifdef CONFIG_SERIAL_IFLOWCONTROL |
| .rtspin = CONFIG_ESP32S3_UART0_RTSPIN, |
| .rtssig = U0RTS_OUT_IDX, |
| #ifdef CONFIG_UART0_IFLOWCONTROL |
| .iflow = true, /* input flow control (RTS) enabled */ |
| #else |
| .iflow = false, /* input flow control (RTS) disabled */ |
| #endif |
| #endif |
| #ifdef CONFIG_SERIAL_OFLOWCONTROL |
| .ctspin = CONFIG_ESP32S3_UART0_CTSPIN, |
| .ctssig = U0CTS_IN_IDX, |
| #ifdef CONFIG_UART0_OFLOWCONTROL |
| .oflow = true, /* output flow control (CTS) enabled */ |
| #else |
| .oflow = false, /* output flow control (CTS) disabled */ |
| #endif |
| #endif |
| #ifdef CONFIG_ESP32S3_UART0_RS485 |
| .rs485_dir_gpio = CONFIG_ESP32S3_UART0_RS485_DIR_PIN, |
| #if (CONFIG_ESP32S3_UART0_RS485_DIR_POLARITY == 0) |
| .rs485_dir_polarity = false, |
| #else |
| .rs485_dir_polarity = true, |
| #endif |
| #endif |
| }; |
| |
| #endif /* CONFIG_ESP32S3_UART0 */ |
| |
| #ifdef CONFIG_ESP32S3_UART1 |
| |
| struct esp32s3_uart_s g_uart1_config = |
| { |
| .periph = ESP32S3_PERIPH_UART1, |
| .id = 1, |
| .cpuint = -ENOMEM, |
| .irq = ESP32S3_IRQ_UART1, |
| .baud = CONFIG_UART1_BAUD, |
| .bits = CONFIG_UART1_BITS, |
| .parity = CONFIG_UART1_PARITY, |
| .stop_b2 = CONFIG_UART1_2STOP, |
| .int_pri = ESP32S3_INT_PRIO_DEF, |
| .txpin = CONFIG_ESP32S3_UART1_TXPIN, |
| .txsig = U1TXD_OUT_IDX, |
| .rxpin = CONFIG_ESP32S3_UART1_RXPIN, |
| .rxsig = U1RXD_IN_IDX, |
| #ifdef CONFIG_SERIAL_IFLOWCONTROL |
| .rtspin = CONFIG_ESP32S3_UART1_RTSPIN, |
| .rtssig = U1RTS_OUT_IDX, |
| #ifdef CONFIG_UART1_IFLOWCONTROL |
| .iflow = true, /* input flow control (RTS) enabled */ |
| #else |
| .iflow = false, /* input flow control (RTS) disabled */ |
| #endif |
| #endif |
| #ifdef CONFIG_SERIAL_OFLOWCONTROL |
| .ctspin = CONFIG_ESP32S3_UART1_CTSPIN, |
| .ctssig = U1CTS_IN_IDX, |
| #ifdef CONFIG_UART1_OFLOWCONTROL |
| .oflow = true, /* output flow control (CTS) enabled */ |
| #else |
| .oflow = false, /* output flow control (CTS) disabled */ |
| #endif |
| #endif |
| #ifdef CONFIG_ESP32S3_UART1_RS485 |
| .rs485_dir_gpio = CONFIG_ESP32S3_UART1_RS485_DIR_PIN, |
| #if (CONFIG_ESP32S3_UART1_RS485_DIR_POLARITY == 0) |
| .rs485_dir_polarity = false, |
| #else |
| .rs485_dir_polarity = true, |
| #endif |
| #endif |
| }; |
| |
| #endif /* CONFIG_ESP32S3_UART1 */ |
| |
| #ifdef CONFIG_ESP32S3_UART2 |
| |
| struct esp32s3_uart_s g_uart2_config = |
| { |
| .periph = ESP32S3_PERIPH_UART2, |
| .id = 2, |
| .cpuint = -ENOMEM, |
| .irq = ESP32S3_IRQ_UART2, |
| .baud = CONFIG_UART2_BAUD, |
| .bits = CONFIG_UART2_BITS, |
| .parity = CONFIG_UART2_PARITY, |
| .stop_b2 = CONFIG_UART2_2STOP, |
| .int_pri = ESP32S3_INT_PRIO_DEF, |
| .txpin = CONFIG_ESP32S3_UART2_TXPIN, |
| .txsig = U2TXD_OUT_IDX, |
| .rxpin = CONFIG_ESP32S3_UART2_RXPIN, |
| .rxsig = U2RXD_IN_IDX, |
| #ifdef CONFIG_SERIAL_IFLOWCONTROL |
| .rtspin = CONFIG_ESP32S3_UART2_RTSPIN, |
| .rtssig = U2RTS_OUT_IDX, |
| #ifdef CONFIG_UART2_IFLOWCONTROL |
| .iflow = true, /* input flow control (RTS) enabled */ |
| #else |
| .iflow = false, /* input flow control (RTS) disabled */ |
| #endif |
| #endif |
| #ifdef CONFIG_SERIAL_OFLOWCONTROL |
| .ctspin = CONFIG_ESP32S3_UART2_CTSPIN, |
| .ctssig = U2CTS_IN_IDX, |
| #ifdef CONFIG_UART1_OFLOWCONTROL |
| .oflow = true, /* output flow control (CTS) enabled */ |
| #else |
| .oflow = false, /* output flow control (CTS) disabled */ |
| #endif |
| #endif |
| #ifdef CONFIG_ESP32S3_UART2_RS485 |
| .rs485_dir_gpio = CONFIG_ESP32S3_UART2_RS485_DIR_PIN, |
| #if (CONFIG_ESP32S3_UART2_RS485_DIR_POLARITY == 0) |
| .rs485_dir_polarity = false, |
| #else |
| .rs485_dir_polarity = true, |
| #endif |
| #endif |
| }; |
| |
| #endif /* CONFIG_ESP32S3_UART2 */ |
| #endif /* HAVE_UART_DEVICE */ |
| |
| /**************************************************************************** |
| * Name: uart_is_iomux |
| * |
| * Description: |
| * Check if the selected UART pins can use IOMUX directly. Otherwise, UART |
| * signals will be routed via GPIO Matrix. |
| * |
| * Input Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| * Returned Value: |
| * True if can use IOMUX or false if can't. |
| * |
| ****************************************************************************/ |
| |
| static inline bool uart_is_iomux(const struct esp32s3_uart_s *priv) |
| { |
| bool mapped = false; |
| |
| if (priv->id == 0) |
| { |
| if (priv->txpin == UART0_IOMUX_TXPIN |
| && priv->rxpin == UART0_IOMUX_RXPIN |
| #ifdef CONFIG_UART0_IFLOWCONTROL |
| && priv->rtspin == UART0_IOMUX_RTSPIN |
| #endif |
| #ifdef CONFIG_UART0_OFLOWCONTROL |
| && priv->ctspin == UART0_IOMUX_CTSPIN |
| #endif |
| ) |
| { |
| mapped = true; |
| } |
| } |
| else if (priv->id == 1) |
| { |
| if (priv->txpin == UART1_IOMUX_TXPIN |
| && priv->rxpin == UART1_IOMUX_RXPIN |
| #ifdef CONFIG_UART1_IFLOWCONTROL |
| && priv->rtspin == UART1_IOMUX_RTSPIN |
| #endif |
| #ifdef CONFIG_UART1_OFLOWCONTROL |
| && priv->ctspin == UART1_IOMUX_CTSPIN |
| #endif |
| ) |
| { |
| mapped = true; |
| } |
| } |
| |
| return mapped; |
| } |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_set_iflow |
| * |
| * Description: |
| * Configure the input hardware flow control. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * threshold - RX FIFO value from which RST will automatically be |
| * asserted. |
| * enable - true = enable, false = disable |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_set_iflow(const struct esp32s3_uart_s *priv, |
| uint8_t threshold, bool enable) |
| { |
| uint32_t mask; |
| if (enable) |
| { |
| /* Enable RX flow control */ |
| |
| modifyreg32(UART_CONF1_REG(priv->id), 0, UART_RX_FLOW_EN); |
| |
| /* Configure the threshold */ |
| |
| mask = VALUE_TO_FIELD(threshold, UART_RX_FLOW_THRHD); |
| modifyreg32(UART_MEM_CONF_REG(priv->id), UART_RX_FLOW_THRHD_M, mask); |
| } |
| else |
| { |
| /* Disable RX flow control */ |
| |
| modifyreg32(UART_CONF1_REG(priv->id), UART_RX_FLOW_EN, 0); |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_set_oflow |
| * |
| * Description: |
| * Configure the output hardware flow control. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * enable - true = enable, false = disable |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_set_oflow(const struct esp32s3_uart_s *priv, |
| bool enable) |
| { |
| if (enable) |
| { |
| /* Enable TX flow control */ |
| |
| modifyreg32(UART_CONF0_REG(priv->id), 0, UART_TX_FLOW_EN); |
| } |
| else |
| { |
| /* Disable TX flow control */ |
| |
| modifyreg32(UART_CONF0_REG(priv->id), UART_TX_FLOW_EN, 0); |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_reset_core |
| * |
| * Description: |
| * Reset both TX and RX cores. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_reset_cores(const struct esp32s3_uart_s *priv) |
| { |
| uint32_t set_bit = 1 << UART_RST_CORE_S; |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_RST_CORE_M, set_bit); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_RST_CORE_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_rst_tx |
| * |
| * Description: |
| * Reset TX core. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_rst_tx(const struct esp32s3_uart_s *priv) |
| { |
| uint32_t set_bit = 1 << UART_TX_RST_CORE_S; |
| |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_TX_RST_CORE_M, set_bit); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_TX_RST_CORE_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_rst_rx |
| * |
| * Description: |
| * Reset RX core. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_rst_rx(const struct esp32s3_uart_s *priv) |
| { |
| uint32_t set_bit = 1 << UART_RX_RST_CORE_S; |
| |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_RX_RST_CORE_M, set_bit); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_RX_RST_CORE_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_enable_sclk |
| * |
| * Description: |
| * Enable clock for whole core. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_enable_sclk(const struct esp32s3_uart_s *priv) |
| { |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_SCLK_EN_M, |
| 1 << UART_SCLK_EN_S); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_RX_SCLK_EN_M, |
| 1 << UART_RX_SCLK_EN_S); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_TX_SCLK_EN_M, |
| 1 << UART_TX_SCLK_EN_S); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_disable_sclk |
| * |
| * Description: |
| * Disable clock for whole core. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_disable_sclk(const struct esp32s3_uart_s *priv) |
| { |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_SCLK_EN_M, 0); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_RX_SCLK_EN_M, 0); |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_TX_SCLK_EN_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_set_sclk |
| * |
| * Description: |
| * Set a source clock for UART. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * source - APB_CLK = 1 80 MHz |
| * CLK_8 = 2 8 MHz |
| * XTAL_CLK = 3 |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_set_sclk(const struct esp32s3_uart_s *priv, |
| enum uart_sclk source) |
| { |
| uint32_t clk = (uint32_t)source << UART_SCLK_SEL_S; |
| modifyreg32(UART_CLK_CONF_REG(priv->id), UART_SCLK_SEL_M, clk); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_get_sclk |
| * |
| * Description: |
| * Get the source clock for UART. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| * Returned Value: |
| * The frequency of the clock in Hz. |
| * |
| ****************************************************************************/ |
| |
| uint32_t esp32s3_lowputc_get_sclk(const struct esp32s3_uart_s * priv) |
| { |
| uint32_t clk_conf; |
| uint32_t ret = -ENODATA; |
| |
| clk_conf = REG_MASK(getreg32(UART_CLK_CONF_REG(priv->id)), UART_SCLK_SEL); |
| switch (clk_conf) |
| { |
| case 1: |
| ret = esp_clk_apb_freq(); |
| break; |
| case 2: |
| ret = RTC_CLK_FREQ; |
| break; |
| case 3: |
| ret = XTAL_CLK_FREQ; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_baud |
| * |
| * Description: |
| * Set the baud rate according to the value in the private driver |
| * struct. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_baud(const struct esp32s3_uart_s *priv) |
| { |
| int sclk_div; |
| uint32_t sclk_freq; |
| uint32_t clk_div; |
| uint32_t int_part; |
| uint32_t frag_part; |
| |
| /* Get serial clock */ |
| |
| sclk_freq = esp32s3_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_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); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_normal_mode |
| * |
| * Description: |
| * Set the UART to operate in normal mode, i.e., disable the RS485 mode and |
| * IRDA mode. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_normal_mode(const struct esp32s3_uart_s *priv) |
| { |
| /* Disable RS485 mode */ |
| |
| modifyreg32(UART_RS485_CONF_REG(priv->id), UART_RS485_EN_M, 0); |
| modifyreg32(UART_RS485_CONF_REG(priv->id), UART_RS485TX_RX_EN_M, 0); |
| modifyreg32(UART_RS485_CONF_REG(priv->id), UART_RS485RXBY_TX_EN_M, 0); |
| |
| /* Disable IRDA mode */ |
| |
| modifyreg32(UART_CONF0_REG(priv->id), UART_IRDA_EN_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_parity |
| * |
| * Description: |
| * Set the parity, according to the value in the private driver |
| * struct. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_parity(const struct esp32s3_uart_s *priv) |
| { |
| if (priv->parity == UART_PARITY_DISABLE) |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_PARITY_EN_M, 0); |
| } |
| else |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_PARITY_M, |
| (priv->parity & 0x1) << UART_PARITY_S); |
| modifyreg32(UART_CONF0_REG(priv->id), UART_PARITY_EN_M, |
| 1 << UART_PARITY_EN_S); |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_data_length |
| * |
| * Description: |
| * Set the data bits length, according to the value in the private driver |
| * struct. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| int esp32s3_lowputc_data_length(const struct esp32s3_uart_s *priv) |
| { |
| int ret = OK; |
| uint32_t length = priv->bits - 5; |
| |
| /* If it is the allowed range */ |
| |
| if (length >= UART_DATA_5_BITS && length <= UART_DATA_8_BITS) |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_BIT_NUM_M, |
| length << UART_BIT_NUM_S); |
| } |
| else |
| { |
| ret = -EINVAL; |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_stop_length |
| * |
| * Description: |
| * Set the stop bits length, according to the value in the private driver |
| * struct. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_stop_length(const struct esp32s3_uart_s *priv) |
| { |
| if (priv->stop_b2 == 0) |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_STOP_BIT_NUM_M, |
| UART_STOP_BITS_1 << UART_STOP_BIT_NUM_S); |
| } |
| else |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_STOP_BIT_NUM_M, |
| UART_STOP_BITS_2 << UART_STOP_BIT_NUM_S); |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_set_tx_idle_time |
| * |
| * Description: |
| * Set the idle time between transfers. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * time - Desired time interval between the transfers. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_set_tx_idle_time(const struct esp32s3_uart_s *priv, |
| uint32_t time) |
| { |
| modifyreg32(UART_IDLE_CONF_REG(priv->id), UART_TX_IDLE_NUM_M, |
| VALUE_TO_FIELD(time, UART_TX_IDLE_NUM)); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_send_byte |
| * |
| * Description: |
| * Send one byte. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * byte - Byte to be sent. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_send_byte(const struct esp32s3_uart_s *priv, |
| char byte) |
| { |
| putreg32((uint32_t)byte, UART_FIFO_REG(priv->id)); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_enable_sysclk |
| * |
| * Description: |
| * Enable clock for the UART using the System register. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_enable_sysclk(const struct esp32s3_uart_s *priv) |
| { |
| esp32s3_periph_module_enable(PERIPH_UART0_MODULE + priv->id); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_is_tx_fifo_full |
| * |
| * Description: |
| * Verify if TX FIFO is full. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| * Returned Value: |
| * True if it is full, otherwise false. |
| * |
| ****************************************************************************/ |
| |
| bool esp32s3_lowputc_is_tx_fifo_full(const struct esp32s3_uart_s *priv) |
| { |
| uint32_t val; |
| val = REG_MASK(getreg32(UART_STATUS_REG(priv->id)), UART_TXFIFO_CNT); |
| return val >= (UART_TX_FIFO_SIZE - 1); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_rst_peripheral |
| * |
| * Description: |
| * Reset the UART peripheral by using System reg. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_rst_peripheral(const struct esp32s3_uart_s *priv) |
| { |
| if (priv->id == 0) |
| { |
| modifyreg32(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST_M, |
| SYSTEM_UART_RST_M); |
| modifyreg32(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST_M, 0); |
| } |
| else |
| { |
| modifyreg32(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST_M, |
| SYSTEM_UART1_RST_M); |
| modifyreg32(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST_M, 0); |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_rst_txfifo |
| * |
| * Description: |
| * Reset TX FIFO. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_rst_txfifo(const struct esp32s3_uart_s *priv) |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_TXFIFO_RST_M, |
| UART_TXFIFO_RST_M); |
| modifyreg32(UART_CONF0_REG(priv->id), UART_TXFIFO_RST_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_rst_rxfifo |
| * |
| * Description: |
| * Reset RX FIFO. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_rst_rxfifo(const struct esp32s3_uart_s *priv) |
| { |
| modifyreg32(UART_CONF0_REG(priv->id), UART_RXFIFO_RST_M, |
| UART_RXFIFO_RST_M); |
| modifyreg32(UART_CONF0_REG(priv->id), UART_RXFIFO_RST_M, 0); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_disable_all_uart_int |
| * |
| * Description: |
| * Disable all UART interrupts. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * current_status - Pointer to a variable to store the current status of |
| * the interrupt enable register before disabling |
| * UART interrupts. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_disable_all_uart_int(struct esp32s3_uart_s *priv, |
| uint32_t *current_status) |
| { |
| irqstate_t flags; |
| |
| flags = spin_lock_irqsave(&priv->lock); |
| |
| if (current_status != NULL) |
| { |
| /* Save current status */ |
| |
| *current_status = getreg32(UART_INT_ENA_REG(priv->id)); |
| } |
| |
| /* Disable all UART int */ |
| |
| putreg32(0, UART_INT_ENA_REG(priv->id)); |
| |
| /* Clear all ints */ |
| |
| putreg32(0xffffffff, UART_INT_CLR_REG(priv->id)); |
| |
| spin_unlock_irqrestore(&priv->lock, flags); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_restore_all_uart_int |
| * |
| * Description: |
| * Restore all UART interrupts. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * last_status - Pointer to a variable that stored the last state of the |
| * interrupt enable register. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_restore_all_uart_int(const struct esp32s3_uart_s *priv, |
| uint32_t *last_status) |
| { |
| /* Restore the previous behaviour */ |
| |
| putreg32(*last_status, UART_INT_ENA_REG(priv->id)); |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_config_pins |
| * |
| * Description: |
| * Configure TX and RX UART pins. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_config_pins(const struct esp32s3_uart_s *priv) |
| { |
| /* Configure the pins */ |
| |
| /* Keep TX pin in high level to avoid "?" trash character |
| * This "?" is the Unicode replacement character (U+FFFD) |
| */ |
| |
| esp32s3_gpiowrite(priv->txpin, true); |
| |
| if (uart_is_iomux(priv)) |
| { |
| esp32s3_gpio_matrix_out(priv->txpin, SIG_GPIO_OUT_IDX, 0, 0); |
| esp32s3_configgpio(priv->txpin, priv->id == 1 ? OUTPUT_FUNCTION_3 : |
| OUTPUT_FUNCTION_1); |
| |
| esp32s3_configgpio(priv->rxpin, priv->id == 1 ? INPUT_FUNCTION_3 : |
| INPUT_FUNCTION_1); |
| esp32s3_gpio_matrix_out(priv->rxpin, SIG_GPIO_OUT_IDX, 0, 0); |
| |
| #ifdef CONFIG_SERIAL_IFLOWCONTROL |
| if (priv->iflow) |
| { |
| esp32s3_configgpio(priv->rtspin, OUTPUT_FUNCTION_3); |
| esp32s3_gpio_matrix_out(priv->rtspin, SIG_GPIO_OUT_IDX, 0, 0); |
| } |
| |
| #endif |
| #ifdef CONFIG_SERIAL_OFLOWCONTROL |
| if (priv->oflow) |
| { |
| esp32s3_configgpio(priv->ctspin, INPUT_FUNCTION_3); |
| esp32s3_gpio_matrix_out(priv->ctspin, SIG_GPIO_OUT_IDX, 0, 0); |
| } |
| #endif |
| } |
| else |
| { |
| esp32s3_gpio_matrix_out(priv->txpin, priv->txsig, 0, 0); |
| esp32s3_configgpio(priv->txpin, OUTPUT_FUNCTION_2); |
| |
| esp32s3_configgpio(priv->rxpin, INPUT_FUNCTION_2); |
| esp32s3_gpio_matrix_in(priv->rxpin, priv->rxsig, 0); |
| |
| #ifdef CONFIG_SERIAL_IFLOWCONTROL |
| if (priv->iflow) |
| { |
| esp32s3_configgpio(priv->rtspin, OUTPUT_FUNCTION_2); |
| esp32s3_gpio_matrix_out(priv->rtspin, priv->rtssig, 0, 0); |
| } |
| |
| #endif |
| #ifdef CONFIG_SERIAL_OFLOWCONTROL |
| if (priv->oflow) |
| { |
| esp32s3_configgpio(priv->ctspin, INPUT_FUNCTION_2); |
| esp32s3_gpio_matrix_in(priv->ctspin, priv->ctssig, 0); |
| } |
| #endif |
| } |
| |
| #ifdef HAVE_RS485 |
| if (priv->rs485_dir_gpio != 0) |
| { |
| esp32s3_configgpio(priv->rs485_dir_gpio, OUTPUT); |
| esp32s3_gpio_matrix_out(priv->rs485_dir_gpio, SIG_GPIO_OUT_IDX, 0, 0); |
| esp32s3_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); |
| } |
| #endif |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowputc_restore_pins |
| * |
| * Description: |
| * Configure both pins back to INPUT mode and detach the TX pin from the |
| * output signal and the RX pin from the input signal. |
| * |
| * Parameters: |
| * priv - Pointer to the private driver struct. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowputc_restore_pins(const struct esp32s3_uart_s *priv) |
| { |
| /* Configure the pins */ |
| |
| esp32s3_configgpio(priv->txpin, INPUT); |
| esp32s3_gpio_matrix_out(priv->txpin, MATRIX_DETACH_OUT_SIG, false, false); |
| |
| esp32s3_configgpio(priv->rxpin, INPUT); |
| esp32s3_gpio_matrix_in(priv->rxpin, MATRIX_DETACH_IN_LOW_PIN, false); |
| } |
| |
| /**************************************************************************** |
| * Name: xtensa_lowputc |
| * |
| * Description: |
| * Output one byte on the serial console. |
| * |
| * Parameters: |
| * ch - Byte to be sent. |
| * |
| ****************************************************************************/ |
| |
| void xtensa_lowputc(char ch) |
| { |
| #ifdef CONSOLE_UART |
| |
| # if defined(CONFIG_UART0_SERIAL_CONSOLE) |
| struct esp32s3_uart_s *priv = &g_uart0_config; |
| #elif defined (CONFIG_UART1_SERIAL_CONSOLE) |
| struct esp32s3_uart_s *priv = &g_uart1_config; |
| #elif defined (CONFIG_UART2_SERIAL_CONSOLE) |
| struct esp32s3_uart_s *priv = &g_uart2_config; |
| #endif |
| |
| /* Wait until the TX FIFO has space to insert new char */ |
| |
| while (esp32s3_lowputc_is_tx_fifo_full(priv)); |
| |
| /* Then send the character */ |
| |
| esp32s3_lowputc_send_byte(priv, ch); |
| #endif /* CONSOLE_UART */ |
| } |
| |
| /**************************************************************************** |
| * Name: esp32s3_lowsetup |
| * |
| * Description: |
| * This performs only the basic configuration for UART pins. |
| * |
| ****************************************************************************/ |
| |
| void esp32s3_lowsetup(void) |
| { |
| #ifndef CONFIG_SUPPRESS_UART_CONFIG |
| |
| #ifdef CONFIG_ESP32S3_UART0 |
| esp32s3_lowputc_enable_sysclk(&g_uart0_config); |
| esp32s3_lowputc_config_pins(&g_uart0_config); |
| #endif |
| |
| #ifdef CONFIG_ESP32S3_UART1 |
| esp32s3_lowputc_enable_sysclk(&g_uart1_config); |
| esp32s3_lowputc_config_pins(&g_uart1_config); |
| #endif |
| |
| #ifdef CONFIG_ESP32S3_UART2 |
| esp32s3_lowputc_enable_sysclk(&g_uart2_config); |
| esp32s3_lowputc_config_pins(&g_uart2_config); |
| #endif |
| |
| #endif /* !CONFIG_SUPPRESS_UART_CONFIG */ |
| } |