uart: Support LP_UART port with UART driver on esp32c6

This commit is contained in:
Song Ruo Jing
2023-03-24 11:42:01 +08:00
parent b77540c285
commit 921713fff4
68 changed files with 1127 additions and 401 deletions

View File

@@ -11,7 +11,6 @@
#include "soc/periph_defs.h"
#include "soc/pcr_reg.h"
#include "soc/soc.h"
#include "soc/lpperi_reg.h"
#include "esp_attr.h"
#ifdef __cplusplus
@@ -79,9 +78,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return PCR_SDIO_SLAVE_CLK_EN;
case PERIPH_REGDMA_MODULE:
return PCR_REGDMA_CLK_EN;
//TODO: LP_PERIPH modules are added temporarily and will be moved to a separate API (IDF-7374).
case PERIPH_LP_I2C0_MODULE:
return LPPERI_LP_EXT_I2C_CK_EN;
// case PERIPH_RNG_MODULE:
// return PCR_WIFI_CLK_RNG_EN;
// case PERIPH_WIFI_MODULE:
@@ -175,9 +171,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return PCR_SDIO_SLAVE_RST_EN;
case PERIPH_REGDMA_MODULE:
return PCR_REGDMA_RST_EN;
//TODO: LP_PERIPH modules are added temporarily and will be moved to a separate API (IDF-7374).
case PERIPH_LP_I2C0_MODULE:
return LPPERI_LP_EXT_I2C_RESET_EN;
// case PERIPH_RNG_MODULE:
// return PCR_WIFI_CLK_RNG_EN;
// case PERIPH_WIFI_MODULE:
@@ -264,9 +257,6 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
return PCR_SDIO_SLAVE_CONF_REG;
case PERIPH_REGDMA_MODULE:
return PCR_REGDMA_CONF_REG;
//TODO: LP_PERIPH modules are added temporarily and will be moved to a separate API (IDF-7374).
case PERIPH_LP_I2C0_MODULE:
return LPPERI_CLK_EN_REG;
default:
return 0;
}
@@ -333,9 +323,6 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
return PCR_SDIO_SLAVE_CONF_REG;
case PERIPH_REGDMA_MODULE:
return PCR_REGDMA_CONF_REG;
//TODO: LP_PERIPH modules are added temporarily and will be moved to a separate API (IDF-7374).
case PERIPH_LP_I2C0_MODULE:
return LPPERI_RESET_EN_REG;
default:
return 0;
}

View File

@@ -17,7 +17,6 @@
#include "soc/pcr_struct.h"
#include "hal/i2c_types.h"
#include "soc/clk_tree_defs.h"
#include "soc/lp_clkrst_struct.h"
#ifdef __cplusplus
extern "C" {
@@ -675,33 +674,6 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
PCR.i2c_sclk_conf.i2c_sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
}
#if SOC_LP_I2C_SUPPORTED
/**
* @brief Set LP I2C source clock
*
* @param hw Address offset of the LP I2C peripheral registers
* @param src_clk Source clock for the LP I2C peripheral
*
* @return None
*/
static inline void lp_i2c_ll_set_source_clk(i2c_dev_t *hw, soc_periph_lp_i2c_clk_src_t src_clk)
{
(void)hw;
// src_clk : (0) for LP_FAST_CLK (RTC Fast), (1) for XTAL_D2_CLK
switch (src_clk) {
case LP_I2C_SCLK_LP_FAST:
LP_CLKRST.lpperi.lp_i2c_clk_sel = 0;
break;
case LP_I2C_SCLK_XTAL_D2:
LP_CLKRST.lpperi.lp_i2c_clk_sel = 1;
break;
default:
// Invalid source clock selected
abort();
}
}
#endif /* SOC_LP_I2C_SUPPORTED */
/**
* @brief Enable I2C peripheral controller clock
*
@@ -771,6 +743,7 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
return &dev->int_status;
}
//////////////////////////////////////////Deprecated Functions//////////////////////////////////////////////////////////
/////////////////////////////The following functions are only used by the legacy driver/////////////////////////////////
/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)//////////////////////////////

View File

@@ -0,0 +1,105 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdlib.h>
#include "soc/periph_defs.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc.h"
#include "soc/lpperi_reg.h"
#include "soc/lp_clkrst_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
static uint32_t lp_periph_ll_get_clk_en_mask(lp_periph_module_t lp_periph)
{
switch (lp_periph) {
case LP_PERIPH_I2C0_MODULE:
return LPPERI_LP_EXT_I2C_CK_EN;
case LP_PERIPH_UART0_MODULE:
return LPPERI_LP_UART_CK_EN;
default:
// Unsupported LP peripherals
abort();
}
}
static uint32_t lp_periph_ll_get_rst_en_mask(lp_periph_module_t lp_periph)
{
switch (lp_periph) {
case LP_PERIPH_I2C0_MODULE:
return LPPERI_LP_EXT_I2C_RESET_EN;
case LP_PERIPH_UART0_MODULE:
return LPPERI_LP_UART_RESET_EN;
default:
// Unsupported LP peripherals
abort();
}
}
static inline void lp_periph_ll_enable_clk_clear_rst(lp_periph_module_t lp_periph)
{
SET_PERI_REG_MASK(LPPERI_CLK_EN_REG, lp_periph_ll_get_clk_en_mask(lp_periph));
CLEAR_PERI_REG_MASK(LPPERI_RESET_EN_REG, lp_periph_ll_get_rst_en_mask(lp_periph));
}
static inline void lp_periph_ll_disable_clk_set_rst(lp_periph_module_t lp_periph)
{
CLEAR_PERI_REG_MASK(LPPERI_CLK_EN_REG, lp_periph_ll_get_clk_en_mask(lp_periph));
SET_PERI_REG_MASK(LPPERI_RESET_EN_REG, lp_periph_ll_get_rst_en_mask(lp_periph));
}
static inline void lp_periph_ll_reset(lp_periph_module_t lp_periph)
{
uint32_t bit_mask = lp_periph_ll_get_rst_en_mask(lp_periph);
SET_PERI_REG_MASK(LPPERI_RESET_EN_REG, bit_mask);
CLEAR_PERI_REG_MASK(LPPERI_RESET_EN_REG, bit_mask);
}
static inline void lp_periph_ll_set_clk_src(lp_periph_module_t lp_periph, soc_module_clk_t clk_src)
{
uint32_t val;
switch (lp_periph) {
case LP_PERIPH_I2C0_MODULE:
switch (clk_src) {
case LP_I2C_SCLK_LP_FAST:
val = 0;
break;
case LP_I2C_SCLK_XTAL_D2:
val = 1;
break;
default:
// Invalid LP_I2C clock source
abort();
}
REG_SET_FIELD(LP_CLKRST_LPPERI_REG, LP_CLKRST_LP_I2C_CLK_SEL, val);
break;
case LP_PERIPH_UART0_MODULE:
switch (clk_src) {
case LP_UART_SCLK_LP_FAST:
val = 0;
break;
case LP_UART_SCLK_XTAL_D2:
val = 1;
break;
default:
// Invalid LP_UART clock source
abort();
}
REG_SET_FIELD(LP_CLKRST_LPPERI_REG, LP_CLKRST_LP_UART_CLK_SEL, val);
break;
default:
// Unsupported LP peripherals
abort();
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -46,6 +46,17 @@ typedef enum {
RTCIO_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */
} rtcio_ll_out_mode_t;
/**
* @brief Select a RTC IOMUX function for the RTC IO
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param func Function to assign to the pin
*/
static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func)
{
LP_IO.gpio[rtcio_num].mcu_sel = func;
}
/**
* @brief Select the rtcio function.
*
@@ -64,7 +75,7 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func)
sel_mask |= BIT(rtcio_num);
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel, sel_mask);
//0:RTC FUNCTION 1,2,3:Reserved
LP_IO.gpio[rtcio_num].mcu_sel = RTCIO_LL_PIN_FUNC;
rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC);
} else if (func == RTCIO_FUNC_DIGITAL) {
// Clear the bit to use digital GPIO module
uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel);

View File

@@ -12,9 +12,12 @@
#include "hal/misc.h"
#include "hal/uart_types.h"
#include "soc/uart_periph.h"
#include "soc/uart_reg.h"
#include "soc/uart_struct.h"
#include "soc/lp_uart_reg.h"
#include "soc/pcr_struct.h"
#include "soc/lp_clkrst_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -22,8 +25,11 @@ extern "C" {
// The default fifo depth
#define UART_LL_FIFO_DEF_LEN (SOC_UART_FIFO_LEN)
#define LP_UART_LL_FIFO_DEF_LEN (SOC_LP_UART_FIFO_LEN)
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == 0) ? (&UART0) : (&UART1))
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&LP_UART)))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
@@ -77,6 +83,30 @@ typedef enum {
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t;
/****************************************** LP_UART Specific ********************************************/
/**
* @brief Get the LP_UART source clock.
*
* @param hw Beginning address of the peripheral registers.
* @param source_clk Current LP_UART clock source, one in soc_periph_lp_uart_clk_src_t.
*/
static inline void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk)
{
(void)hw;
switch (LP_CLKRST.lpperi.lp_uart_clk_sel) {
default:
case 0:
*source_clk = LP_UART_SCLK_LP_FAST;
break;
case 1:
*source_clk = LP_UART_SCLK_XTAL_D2;
break;
}
}
// LP_UART clock control LL functions are located in lp_periph_clk_ctrl_ll.h
/*************************************** General LL functions ******************************************/
/**
* @brief Sync the update to UART core clock domain
*
@@ -100,7 +130,13 @@ static inline void uart_ll_update(uart_dev_t *hw)
*/
static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en)
{
UART_LL_PCR_REG_SET(hw, conf, rst_en, core_rst_en);
if ((hw) != &LP_UART) {
UART_LL_PCR_REG_SET(hw, conf, rst_en, core_rst_en);
} else {
// LP_UART reset shares the same register with other LP peripherals
// Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c
abort();
}
}
/**
@@ -112,7 +148,13 @@ static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en)
*/
static inline void uart_ll_sclk_enable(uart_dev_t *hw)
{
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_en, 1);
if ((hw) != &LP_UART) {
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_en, 1);
} else {
// LP_UART clk_en shares the same register with other LP peripherals
// Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c
abort();
}
}
/**
@@ -124,7 +166,13 @@ static inline void uart_ll_sclk_enable(uart_dev_t *hw)
*/
static inline void uart_ll_sclk_disable(uart_dev_t *hw)
{
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_en, 0);
if ((hw) != &LP_UART) {
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_en, 0);
} else {
// LP_UART clk_en shares the same register with other LP peripherals
// Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c
abort();
}
}
/**
@@ -136,19 +184,29 @@ static inline void uart_ll_sclk_disable(uart_dev_t *hw)
*
* @return None.
*/
static inline void uart_ll_set_sclk(uart_dev_t *hw, uart_sclk_t source_clk)
static inline void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_clk)
{
switch (source_clk) {
default:
if ((hw) != &LP_UART) {
uint32_t sel_value = 0;
switch (source_clk) {
case UART_SCLK_PLL_F80M:
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 1);
sel_value = 1;
break;
case UART_SCLK_RTC:
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 2);
sel_value = 2;
break;
case UART_SCLK_XTAL:
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, 3);
sel_value = 3;
break;
default:
// Invalid HP_UART clock source
abort();
}
UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_sel, sel_value);
} else {
// LP_UART clk_sel shares the same register with other LP peripherals
// Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c
abort();
}
}
@@ -160,9 +218,10 @@ static inline void uart_ll_set_sclk(uart_dev_t *hw, uart_sclk_t source_clk)
*
* @return None.
*/
static inline void uart_ll_get_sclk(uart_dev_t *hw, uart_sclk_t *source_clk)
static inline void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk)
{
switch (UART_LL_PCR_REG_GET(hw, sclk_conf, sclk_sel)) {
if ((hw) != &LP_UART) {
switch (UART_LL_PCR_REG_GET(hw, sclk_conf, sclk_sel)) {
default:
case 1:
*source_clk = UART_SCLK_PLL_F80M;
@@ -173,6 +232,9 @@ static inline void uart_ll_get_sclk(uart_dev_t *hw, uart_sclk_t *source_clk)
case 3:
*source_clk = UART_SCLK_XTAL;
break;
}
} else {
lp_uart_ll_get_sclk(hw, source_clk);
}
}
@@ -196,7 +258,11 @@ static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t
// an integer part and a fractional part.
hw->clkdiv_sync.clkdiv_int = clk_div >> 4;
hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf;
UART_LL_PCR_REG_U32_SET(hw, sclk_conf, sclk_div_num, sclk_div - 1);
if ((hw) == &LP_UART) {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1);
} else {
UART_LL_PCR_REG_U32_SET(hw, sclk_conf, sclk_div_num, sclk_div - 1);
}
#undef DIV_UP
uart_ll_update(hw);
}
@@ -213,7 +279,13 @@ static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq)
{
typeof(hw->clkdiv_sync) div_reg;
div_reg.val = hw->clkdiv_sync.val;
return ((sclk_freq << 4)) / (((div_reg.clkdiv_int << 4) | div_reg.clkdiv_frag) * (UART_LL_PCR_REG_U32_GET(hw, sclk_conf, sclk_div_num) + 1));
int sclk_div;
if ((hw) == &LP_UART) {
sclk_div = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1;
} else {
sclk_div = UART_LL_PCR_REG_U32_GET(hw, sclk_conf, sclk_div_num) + 1;
}
return ((sclk_freq << 4)) / (((div_reg.clkdiv_int << 4) | div_reg.clkdiv_frag) * sclk_div);
}
/**
@@ -362,7 +434,7 @@ static inline void uart_ll_txfifo_rst(uart_dev_t *hw)
*/
static inline uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw)
{
return hw->status.rxfifo_cnt;
return (hw->status.rxfifo_cnt) >> UART_LL_REG_FIELD_BIT_SHIFT(hw);
}
/**
@@ -374,7 +446,9 @@ static inline uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw)
*/
static inline uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw)
{
return UART_LL_FIFO_DEF_LEN - hw->status.txfifo_cnt;
uint32_t total_fifo_len = ((hw) == &LP_UART) ? LP_UART_LL_FIFO_DEF_LEN : UART_LL_FIFO_DEF_LEN;
uint32_t txfifo_len = (hw->status.txfifo_cnt) >> UART_LL_REG_FIELD_BIT_SHIFT(hw);
return (total_fifo_len - txfifo_len);
}
/**
@@ -443,13 +517,13 @@ static inline void uart_ll_get_parity(uart_dev_t *hw, uart_parity_t *parity_mode
* it will produce rxfifo_full_int_raw interrupt.
*
* @param hw Beginning address of the peripheral registers.
* @param full_thrhd The full threshold value of the rxfifo. `full_thrhd` should be less than `UART_LL_FIFO_DEF_LEN`.
* @param full_thrhd The full threshold value of the rxfifo. `full_thrhd` should be less than `(LP_)UART_LL_FIFO_DEF_LEN`.
*
* @return None.
*/
static inline void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thrhd)
{
hw->conf1.rxfifo_full_thrhd = full_thrhd;
hw->conf1.rxfifo_full_thrhd = full_thrhd << UART_LL_REG_FIELD_BIT_SHIFT(hw);
}
/**
@@ -463,7 +537,7 @@ static inline void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thr
*/
static inline void uart_ll_set_txfifo_empty_thr(uart_dev_t *hw, uint16_t empty_thrhd)
{
hw->conf1.txfifo_empty_thrhd = empty_thrhd;
hw->conf1.txfifo_empty_thrhd = empty_thrhd << UART_LL_REG_FIELD_BIT_SHIFT(hw);
}
/**
@@ -527,7 +601,7 @@ static inline void uart_ll_set_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_
{
//only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.
if (flow_ctrl & UART_HW_FLOWCTRL_RTS) {
hw->hwfc_conf_sync.rx_flow_thrhd = rx_thrs;
hw->hwfc_conf_sync.rx_flow_thrhd = rx_thrs << UART_LL_REG_FIELD_BIT_SHIFT(hw);
hw->hwfc_conf_sync.rx_flow_en = 1;
} else {
hw->hwfc_conf_sync.rx_flow_en = 0;
@@ -573,8 +647,8 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t *
if (sw_flow_ctrl_en) {
hw->swfc_conf0_sync.xonoff_del = 1;
hw->swfc_conf0_sync.sw_flow_con_en = 1;
hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd;
hw->swfc_conf1.xoff_threshold = flow_ctrl->xoff_thrd;
hw->swfc_conf1.xon_threshold = (flow_ctrl->xon_thrd) << UART_LL_REG_FIELD_BIT_SHIFT(hw);
hw->swfc_conf1.xoff_threshold = (flow_ctrl->xoff_thrd) << UART_LL_REG_FIELD_BIT_SHIFT(hw);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0_sync, xon_char, flow_ctrl->xon_char);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0_sync, xoff_char, flow_ctrl->xoff_char);
} else {
@@ -671,6 +745,10 @@ static inline void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
*/
static inline void uart_ll_set_mode_normal(uart_dev_t *hw)
{
// This function is only for HP_UART use
// LP_UART can only work in normal mode
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
hw->rs485_conf_sync.rs485_en = 0;
hw->rs485_conf_sync.rs485tx_rx_en = 0;
hw->rs485_conf_sync.rs485rxby_tx_en = 0;
@@ -687,6 +765,10 @@ static inline void uart_ll_set_mode_normal(uart_dev_t *hw)
*/
static inline void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw)
{
// This function is only for HP_UART use
// LP_UART can only work in normal mode
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
// Application software control, remove echo
hw->rs485_conf_sync.rs485rxby_tx_en = 1;
hw->conf0_sync.irda_en = 0;
@@ -707,6 +789,10 @@ static inline void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw)
*/
static inline void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw)
{
// This function is only for HP_UART use
// LP_UART can only work in normal mode
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
// Enable receiver, sw_rts = 1 generates low level on RTS pin
hw->conf0_sync.sw_rts = 1;
// Half duplex mode
@@ -730,6 +816,10 @@ static inline void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw)
*/
static inline void uart_ll_set_mode_collision_detect(uart_dev_t *hw)
{
// This function is only for HP_UART use
// LP_UART can only work in normal mode
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
hw->conf0_sync.irda_en = 0;
// Enable full-duplex mode
hw->rs485_conf_sync.rs485tx_rx_en = 1;
@@ -751,6 +841,10 @@ static inline void uart_ll_set_mode_collision_detect(uart_dev_t *hw)
*/
static inline void uart_ll_set_mode_irda(uart_dev_t *hw)
{
// This function is only for HP_UART use
// LP_UART can only work in normal mode
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
hw->rs485_conf_sync.rs485_en = 0;
hw->rs485_conf_sync.rs485tx_rx_en = 0;
hw->rs485_conf_sync.rs485rxby_tx_en = 0;
@@ -775,15 +869,19 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode)
uart_ll_set_mode_normal(hw);
break;
case UART_MODE_RS485_COLLISION_DETECT:
// Only HP_UART support this mode
uart_ll_set_mode_collision_detect(hw);
break;
case UART_MODE_RS485_APP_CTRL:
// Only HP_UART support this mode
uart_ll_set_mode_rs485_app_ctrl(hw);
break;
case UART_MODE_RS485_HALF_DUPLEX:
// Only HP_UART support this mode
uart_ll_set_mode_rs485_half_duplex(hw);
break;
case UART_MODE_IRDA:
// Only HP_UART support this mode
uart_ll_set_mode_irda(hw);
break;
}
@@ -838,7 +936,7 @@ static inline void uart_ll_get_data_bit_num(uart_dev_t *hw, uart_word_length_t *
*/
static inline bool uart_ll_is_tx_idle(uart_dev_t *hw)
{
return ((hw->status.txfifo_cnt == 0) && (hw->fsm_status.st_utx_out == 0));
return ((((hw->status.txfifo_cnt) >> UART_LL_REG_FIELD_BIT_SHIFT(hw)) == 0) && (hw->fsm_status.st_utx_out == 0));
}
/**
@@ -900,6 +998,9 @@ static inline void uart_ll_xon_force_on(uart_dev_t *hw, bool always_on)
*/
static inline void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask)
{
// LP_UART does not support UART_SIGNAL_IRDA_TX_INV and UART_SIGNAL_IRDA_RX_INV
// lp_uart_dev_t has no these fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
typeof(hw->conf0_sync) conf0_reg;
conf0_reg.val = hw->conf0_sync.val;
conf0_reg.irda_tx_inv = (inv_mask & UART_SIGNAL_IRDA_TX_INV) ? 1 : 0;
@@ -963,7 +1064,7 @@ static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
*/
static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
{
return UART_RX_TOUT_THRHD_V;
return ((hw) == &LP_UART) ? LP_UART_RX_TOUT_THRHD_V : UART_RX_TOUT_THRHD_V;
}
/**
@@ -974,6 +1075,9 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
*/
static inline void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable)
{
// LP_UART does not support autobaud
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
hw->conf0_sync.autobaud_en = enable ? 1 : 0;
uart_ll_update(hw);
}
@@ -985,6 +1089,9 @@ static inline void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable)
*/
static inline uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw)
{
// LP_UART does not support this feature
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
return hw->rxd_cnt.rxd_edge_cnt;
}
@@ -995,6 +1102,9 @@ static inline uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw)
*/
static inline uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw)
{
// LP_UART does not support this feature
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
return hw->pospulse.posedge_min_cnt;
}
@@ -1005,6 +1115,9 @@ static inline uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw)
*/
static inline uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw)
{
// LP_UART does not support this feature
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
return hw->negpulse.negedge_min_cnt;
}
@@ -1015,6 +1128,9 @@ static inline uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw)
*/
static inline uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw)
{
// LP_UART does not support this feature
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
return hw->highpulse.highpulse_min_cnt;
}
@@ -1025,6 +1141,9 @@ static inline uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw)
*/
static inline uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw)
{
// LP_UART does not support this feature
// lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct
return hw->lowpulse.lowpulse_min_cnt;
}
@@ -1037,9 +1156,11 @@ static inline uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw)
*/
static inline void uart_ll_force_xoff(uart_port_t uart_num)
{
REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XON);
REG_SET_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
uart_ll_update(UART_LL_GET_HW(uart_num));
uart_dev_t *hw = UART_LL_GET_HW(uart_num);
hw->swfc_conf0_sync.force_xon = 0;
hw->swfc_conf0_sync.sw_flow_con_en = 1;
hw->swfc_conf0_sync.force_xoff = 1;
uart_ll_update(hw);
}
/**
@@ -1051,10 +1172,12 @@ static inline void uart_ll_force_xoff(uart_port_t uart_num)
*/
static inline void uart_ll_force_xon(uart_port_t uart_num)
{
REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XOFF);
REG_SET_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XON);
REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
uart_ll_update(UART_LL_GET_HW(uart_num));
uart_dev_t *hw = UART_LL_GET_HW(uart_num);
hw->swfc_conf0_sync.force_xoff = 0;
hw->swfc_conf0_sync.force_xon = 1;
hw->swfc_conf0_sync.sw_flow_con_en = 0;
hw->swfc_conf0_sync.force_xon = 0;
uart_ll_update(hw);
}
/**
@@ -1066,7 +1189,8 @@ static inline void uart_ll_force_xon(uart_port_t uart_num)
*/
static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num)
{
return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT);
uart_dev_t *hw = UART_LL_GET_HW(uart_num);
return hw->fsm_status.st_utx_out;
}
/**