Merge branch 'refactor/rcc_critical_section_twai' into 'master'

refactor(twai): add reset and clock control to twai LL layer

See merge request espressif/esp-idf!25559
This commit is contained in:
morris 2023-08-30 15:56:27 +08:00
commit 1cbfe15cd6
13 changed files with 256 additions and 30 deletions

View File

@ -130,7 +130,6 @@ menu "Driver Configurations"
config TWAI_ISR_IN_IRAM
bool "Place TWAI ISR function into IRAM"
default n
select PERIPH_CTRL_FUNC_IN_IRAM if TWAI_ERRATA_FIX_RX_FRAME_INVALID || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT
help
Place the TWAI ISR in to IRAM. This will allow the ISR to avoid
cache misses, and also be able to run whilst the cache is disabled

View File

@ -56,12 +56,17 @@
#define ALERT_LOG_LEVEL_WARNING TWAI_ALERT_ARB_LOST //Alerts above and including this level use ESP_LOGW
#define ALERT_LOG_LEVEL_ERROR TWAI_ALERT_TX_FAILED //Alerts above and including this level use ESP_LOGE
#if !SOC_RCC_IS_INDEPENDENT
#define TWAI_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define TWAI_RCC_ATOMIC()
#endif
/* ------------------ Typedefs, structures, and variables ------------------- */
//Control structure for TWAI driver
typedef struct {
int controller_id;
periph_module_t module; // peripheral module
//Control and status members
twai_state_t state;
twai_mode_t mode;
@ -208,7 +213,9 @@ static void twai_intr_handler_main(void *arg)
#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) {
twai_hal_prepare_for_reset(&twai_context);
periph_module_reset(p_twai_obj->module);
TWAI_RCC_ATOMIC() {
twai_ll_reset_register(p_twai_obj->controller_id);
}
twai_hal_recover_from_reset(&twai_context);
p_twai_obj->rx_missed_count += twai_hal_get_reset_lost_rx_cnt(&twai_context);
twai_alert_handler(TWAI_ALERT_PERIPH_RESET, &alert_req);
@ -442,7 +449,6 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
p_twai_obj_dummy->state = TWAI_STATE_STOPPED;
p_twai_obj_dummy->mode = g_config->mode;
p_twai_obj_dummy->alerts_enabled = g_config->alerts_enabled;
p_twai_obj_dummy->module = twai_controller_periph_signals.controllers[controller_id].module;
//Assign the TWAI object
TWAI_ENTER_CRITICAL();
@ -455,8 +461,10 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
goto err;
}
//Enable TWAI peripheral register clock
periph_module_reset(p_twai_obj_dummy->module);
periph_module_enable(p_twai_obj_dummy->module);
TWAI_RCC_ATOMIC() {
twai_ll_enable_bus_clock(p_twai_obj->controller_id, true);
twai_ll_reset_register(p_twai_obj->controller_id);
}
//Initialize TWAI HAL layer
twai_hal_config_t hal_config = {
@ -496,7 +504,9 @@ esp_err_t twai_driver_uninstall(void)
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED || p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
//Clear registers by reading
twai_hal_deinit(&twai_context);
periph_module_disable(p_twai_obj->module); //Disable TWAI peripheral
TWAI_RCC_ATOMIC() {
twai_ll_enable_bus_clock(p_twai_obj->controller_id, false);
}
p_twai_obj_dummy = p_twai_obj; //Use dummy to shorten critical section
p_twai_obj = NULL;
TWAI_EXIT_CRITICAL();

View File

@ -19,12 +19,12 @@ static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0};
void periph_rcc_enter(void)
IRAM_ATTR void periph_rcc_enter(void)
{
portENTER_CRITICAL_SAFE(&periph_spinlock);
}
void periph_rcc_exit(void)
IRAM_ATTR void periph_rcc_exit(void)
{
portEXIT_CRITICAL_SAFE(&periph_spinlock);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -24,6 +24,7 @@
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/dport_reg.h"
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
@ -150,6 +151,44 @@ typedef enum {
} twai_ll_err_seg_t;
#endif
/* ---------------------------- Reset and Clock Control ------------------------------ */
/**
* @brief Enable the bus clock for twai module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
uint32_t reg_val = DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
reg_val &= ~DPORT_TWAI_CLK_EN;
reg_val |= enable << 19;
DPORT_WRITE_PERI_REG(DPORT_PERIP_CLK_EN_REG, reg_val);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the twai module
*
* @param group_id Group ID
*/
__attribute__((always_inline))
static inline void twai_ll_reset_register(int group_id)
{
(void)group_id;
DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, DPORT_TWAI_RST);
DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, 0);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_reset_register(__VA_ARGS__)
/* ---------------------------- Peripheral Control Register ----------------- */
/**
@ -533,9 +572,9 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID
static inline void twai_ll_parse_err_code_cap(twai_dev_t *hw,
twai_ll_err_type_t *type,
twai_ll_err_dir_t *dir,
twai_ll_err_seg_t *seg)
twai_ll_err_type_t *type,
twai_ll_err_dir_t *dir,
twai_ll_err_seg_t *seg)
{
uint32_t ecc = hw->error_code_capture_reg.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
@ -709,7 +748,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
*/
__attribute__((always_inline))
static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const uint8_t *data,
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
{
bool is_extd = flags & TWAI_MSG_FLAG_EXTD;
bool is_rtr = flags & TWAI_MSG_FLAG_RTR;
@ -753,7 +792,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
*/
__attribute__((always_inline))
static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc,
uint8_t *data, uint32_t *flags)
uint8_t *data, uint32_t *flags)
{
//Copy frame information
*dlc = rx_frame->dlc;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -23,6 +23,7 @@
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/system_struct.h"
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
@ -84,6 +85,40 @@ typedef union {
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
/* ---------------------------- Reset and Clock Control ------------------------------ */
/**
* @brief Enable the bus clock for twai module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
SYSTEM.perip_clk_en0.reg_can_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the twai module
*
* @param group_id Group ID
*/
static inline void twai_ll_reset_register(int group_id)
{
(void)group_id;
SYSTEM.perip_rst_en0.reg_can_rst = 1;
SYSTEM.perip_rst_en0.reg_can_rst = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_reset_register(__VA_ARGS__)
/* ---------------------------- Peripheral Control Register ----------------- */
/**
@ -547,7 +582,7 @@ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec)
* @note Must be called in reset mode
*/
__attribute__((always_inline))
static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_t mask, bool single_filter)
static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_t mask, bool single_filter)
{
uint32_t code_swapped = HAL_SWAP32(code);
uint32_t mask_swapped = HAL_SWAP32(mask);
@ -611,7 +646,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
*/
__attribute__((always_inline))
static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const uint8_t *data,
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
{
bool is_extd = flags & TWAI_MSG_FLAG_EXTD;
bool is_rtr = flags & TWAI_MSG_FLAG_RTR;
@ -655,7 +690,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
*/
__attribute__((always_inline))
static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc,
uint8_t *data, uint32_t *flags)
uint8_t *data, uint32_t *flags)
{
//Copy frame information
*dlc = rx_frame->dlc;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -85,6 +85,39 @@ typedef union {
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
/* ---------------------------- Reset and Clock Control ------------------------------ */
/**
* @brief Enable the bus clock for twai module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
{
if (group_id == 0) {
PCR.twai0_conf.twai0_clk_en = enable;
} else {
PCR.twai1_conf.twai1_clk_en = enable;
}
}
/**
* @brief Reset the twai module
*
* @param group_id Group ID
*/
static inline void twai_ll_reset_register(int group_id)
{
if (group_id == 0) {
PCR.twai0_conf.twai0_rst_en = 1;
PCR.twai0_conf.twai0_rst_en = 0;
} else {
PCR.twai1_conf.twai1_rst_en = 1;
PCR.twai1_conf.twai1_rst_en = 0;
}
}
/* ---------------------------- Peripheral Control Register ----------------- */
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -14,7 +14,6 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
@ -86,6 +85,32 @@ typedef union {
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
/* ---------------------------- Reset and Clock Control ------------------------------ */
/**
* @brief Enable the bus clock for twai module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
PCR.twai0_conf.twai0_clk_en = enable;
}
/**
* @brief Reset the twai module
*
* @param group_id Group ID
*/
static inline void twai_ll_reset_register(int group_id)
{
(void)group_id;
PCR.twai0_conf.twai0_rst_en = 1;
PCR.twai0_conf.twai0_rst_en = 0;
}
/* ---------------------------- Peripheral Control Register ----------------- */
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -23,6 +23,7 @@
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/system_reg.h"
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
@ -84,6 +85,43 @@ typedef union {
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
/* ---------------------------- Reset and Clock Control ------------------------------ */
/**
* @brief Enable the bus clock for twai module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG);
reg_val &= ~DPORT_TWAI_CLK_EN_M;
reg_val |= enable << DPORT_TWAI_CLK_EN_S;
WRITE_PERI_REG(DPORT_PERIP_CLK_EN0_REG, reg_val);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the twai module
*
* @param group_id Group ID
*/
static inline void twai_ll_reset_register(int group_id)
{
(void)group_id;
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, DPORT_TWAI_RST_M);
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, 0);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_reset_register(__VA_ARGS__)
/* ---------------------------- Peripheral Control Register ----------------- */
/**
@ -547,7 +585,7 @@ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec)
* @note Must be called in reset mode
*/
__attribute__((always_inline))
static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_t mask, bool single_filter)
static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_t mask, bool single_filter)
{
uint32_t code_swapped = HAL_SWAP32(code);
uint32_t mask_swapped = HAL_SWAP32(mask);
@ -611,7 +649,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
*/
__attribute__((always_inline))
static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const uint8_t *data,
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
{
bool is_extd = flags & TWAI_MSG_FLAG_EXTD;
bool is_rtr = flags & TWAI_MSG_FLAG_RTR;
@ -655,7 +693,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
*/
__attribute__((always_inline))
static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc,
uint8_t *data, uint32_t *flags)
uint8_t *data, uint32_t *flags)
{
//Copy frame information
*dlc = rx_frame->dlc;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -23,6 +23,7 @@
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/system_struct.h"
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
@ -84,6 +85,40 @@ typedef union {
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
/* ---------------------------- Reset and Clock Control ------------------------------ */
/**
* @brief Enable the bus clock for twai module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
SYSTEM.perip_clk_en0.can_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the twai module
*
* @param group_id Group ID
*/
static inline void twai_ll_reset_register(int group_id)
{
(void)group_id;
SYSTEM.perip_rst_en0.can_rst = 1;
SYSTEM.perip_rst_en0.can_rst = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define twai_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_reset_register(__VA_ARGS__)
/* ---------------------------- Peripheral Control Register ----------------- */
/**

View File

@ -1259,6 +1259,10 @@ config SOC_CLK_RC32K_SUPPORTED
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y
config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
bool
default y

View File

@ -519,6 +519,8 @@
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/
#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1)
#define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1)

View File

@ -992,8 +992,8 @@ config SOC_TIMER_SUPPORT_ETM
default y
config SOC_TWAI_CONTROLLER_NUM
bool
default y
int
default 1
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
@ -1207,6 +1207,10 @@ config SOC_MODEM_CLOCK_IS_INDEPENDENT
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y
config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
bool
default y

View File

@ -413,7 +413,7 @@
#define SOC_TIMER_SUPPORT_ETM (1)
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1
#define SOC_TWAI_CONTROLLER_NUM 1UL
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
@ -496,6 +496,8 @@
#define SOC_CLK_LP_FAST_SUPPORT_LP_PLL (1) /*!< Support LP_PLL clock as the LP_FAST clock source */
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/
#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1)
#define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1)