mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(driver_twai): bringup s31 twaifd driver support
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
#include "hal/twai_types.h"
|
||||
#include "soc/hp_sys_clkrst_struct.h"
|
||||
#include "soc/hp_system_struct.h"
|
||||
|
||||
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
|
||||
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
|
||||
|
||||
#define TWAI_LL_SUPPORT_TIMESTAMP 1
|
||||
#define TWAI_LL_SUPPORT_RX_STATUS 1
|
||||
#define TWAI_LL_SUPPORT_MEM_LP 1 // support memory low power mode
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TWAI_LL_MEM_LP_MODE_DEEP_SLEEP, // memory will enter deep sleep during low power stage, keep memory data
|
||||
TWAI_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory will enter light sleep during low power stage, keep memory data
|
||||
TWAI_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage
|
||||
TWAI_LL_MEM_LP_MODE_DISABLE, // disable the low power stage
|
||||
} twai_ll_mem_lp_mode_sel_t;
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock and module clock for TWAI module
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void twai_ll_enable_bus_clock(uint8_t twai_id, bool enable)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYS_CLKRST.twai0_ctrl0.reg_twai0_apb_clk_en = enable;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYS_CLKRST.twai1_ctrl0.reg_twai1_apb_clk_en = enable;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Select the power control mode for the TWAI memory block
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
*/
|
||||
static inline void twai_ll_mem_power_by_pmu(uint8_t twai_id)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_force_ctrl = 0;
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_lp_en = 0;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_force_ctrl = 0;
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_lp_en = 0;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Select the low power mode for the TWAI memory block
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
* @param mode Low power mode
|
||||
*/
|
||||
static inline void twai_ll_mem_lp_mode_sel(uint8_t twai_id, twai_ll_mem_lp_mode_sel_t mode)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_lp_mode = mode;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_lp_mode = mode;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Force the TWAI memory block to power on
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
*/
|
||||
static inline void twai_ll_mem_force_power_on(uint8_t twai_id)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_force_ctrl = 1;
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_lp_en = 0;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_force_ctrl = 1;
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_lp_en = 0;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Force the TWAI memory block to enter low power mode
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
*/
|
||||
static inline void twai_ll_mem_force_low_power(uint8_t twai_id)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_force_ctrl = 1;
|
||||
HP_SYSTEM.sys_can0_mem_lp_ctrl.sys_can0_mem_lp_en = 1;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_force_ctrl = 1;
|
||||
HP_SYSTEM.sys_can1_mem_lp_ctrl.sys_can1_mem_lp_en = 1;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the TWAI module
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
*/
|
||||
static inline void twai_ll_reset_register(uint8_t twai_id)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYS_CLKRST.twai0_ctrl0.reg_twai0_rst_en = 1;
|
||||
HP_SYS_CLKRST.twai0_ctrl0.reg_twai0_rst_en = 0;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYS_CLKRST.twai1_ctrl0.reg_twai1_rst_en = 1;
|
||||
HP_SYS_CLKRST.twai1_ctrl0.reg_twai1_rst_en = 0;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set clock source for TWAI module
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
* @param clk_src Clock source
|
||||
*/
|
||||
static inline void twai_ll_set_clock_source(uint8_t twai_id, twai_clock_source_t clk_src)
|
||||
{
|
||||
uint32_t clk_sel = 0;
|
||||
|
||||
switch (clk_src) {
|
||||
case TWAI_CLK_SRC_XTAL:
|
||||
clk_sel = 0;
|
||||
break;
|
||||
case TWAI_CLK_SRC_PLL_F80M:
|
||||
clk_sel = 2;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYS_CLKRST.twai0_ctrl0.reg_twai0_clk_src_sel = clk_sel;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYS_CLKRST.twai1_ctrl0.reg_twai1_clk_src_sel = clk_sel;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable TWAI module clock source
|
||||
*
|
||||
* @param twai_id Hardware ID
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void twai_ll_enable_clock(uint8_t twai_id, bool enable)
|
||||
{
|
||||
switch (twai_id) {
|
||||
case 0:
|
||||
HP_SYS_CLKRST.twai0_ctrl0.reg_twai0_clk_en = enable;
|
||||
break;
|
||||
case 1:
|
||||
HP_SYS_CLKRST.twai1_ctrl0.reg_twai1_clk_en = enable;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "hal/twai_periph.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/interrupts.h"
|
||||
#include "soc/twaifd_reg.h"
|
||||
|
||||
const twai_signal_conn_t twai_periph_signals[2] = {
|
||||
[0] = {
|
||||
.module_name = "TWAI0",
|
||||
.irq_id = ETS_TWAI0_INTR_SOURCE,
|
||||
.timer_irq_id = ETS_TWAI0_TIMER_INTR_SOURCE,
|
||||
.tx_sig = TWAI0_TX_IDX,
|
||||
.rx_sig = TWAI0_RX_IDX,
|
||||
.bus_off_sig = -1,
|
||||
.clk_out_sig = -1,
|
||||
.stand_by_sig = -1,
|
||||
},
|
||||
[1] = {
|
||||
.module_name = "TWAI1",
|
||||
.irq_id = ETS_TWAI1_INTR_SOURCE,
|
||||
.timer_irq_id = ETS_TWAI1_TIMER_INTR_SOURCE,
|
||||
.tx_sig = TWAI1_TX_IDX,
|
||||
.rx_sig = TWAI1_RX_IDX,
|
||||
.bus_off_sig = -1,
|
||||
.clk_out_sig = -1,
|
||||
.stand_by_sig = -1,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* TWAI Registers to be saved during sleep retention
|
||||
* - TWAIFD_MODE_SETTINGS_REG
|
||||
* - TWAIFD_STATUS_REG
|
||||
* - TWAIFD_COMMAND_REG
|
||||
* - TWAIFD_INT_ENA_SET_REG
|
||||
* - TWAIFD_INT_ENA_CLR_REG
|
||||
* - TWAIFD_BTR_REG
|
||||
* - TWAIFD_BTR_FD_REG
|
||||
* - TWAIFD_EWL_ERP_FAULT_STATE_REG
|
||||
* - TWAIFD_REC_TEC_REG
|
||||
* - TWAIFD_ERR_NORM_ERR_FD_REG
|
||||
* - TWAIFD_FILTER_A_MASK_REG
|
||||
* - TWAIFD_FILTER_A_VAL_REG
|
||||
* - TWAIFD_FILTER_B_MASK_REG
|
||||
* - TWAIFD_FILTER_B_VAL_REG
|
||||
* - TWAIFD_FILTER_C_MASK_REG
|
||||
* - TWAIFD_FILTER_C_VAL_REG
|
||||
* - TWAIFD_FILTER_RAN_LOW_REG
|
||||
* - TWAIFD_FILTER_RAN_HIGH_REG
|
||||
* - TWAIFD_FILTER_CONTROL_FILTER_STATUS_REG
|
||||
* - TWAIFD_RX_STATUS_RX_SETTINGS_REG
|
||||
* - TWAIFD_TX_COMMAND_TXTB_INFO_REG
|
||||
* - TWAIFD_TX_PRIORITY_REG
|
||||
* - TWAIFD_TRV_DELAY_SSP_CFG_REG
|
||||
* - TWAIFD_RX_FR_CTR_REG
|
||||
* - TWAIFD_TX_FR_CTR_REG
|
||||
*/
|
||||
#define TWAI_RETENTION_REGS_CNT 25
|
||||
#define TWAI_RETENTION_REGS_BASE(i) REG_TWAIFD_BASE(i)
|
||||
static const uint32_t twai_regs_map[4] = {0xb27fdf37, 0x3, 0x0, 0x0};
|
||||
|
||||
// twai timer registers is far away from twai registers, so we need a separate link
|
||||
// - TWAIFD_TIMER_INT_ENA_REG
|
||||
// - TWAIFD_TIMER_CFG_REG
|
||||
#define TWAI_TIMER_RETENTION_REGS_CNT 2
|
||||
#define TWAI_TIMER_RETENTION_REGS_BASE(i) (REG_TWAIFD_BASE(i) + 0xfe0)
|
||||
static const uint32_t twai_timer_regs_map[4] = {0x5, 0x0, 0x0, 0x0};
|
||||
|
||||
#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
|
||||
REGDMA_TWAI_LINK(0x00), \
|
||||
TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \
|
||||
TWAI_RETENTION_REGS_CNT, 0, 0, \
|
||||
twai_regs_map[0], twai_regs_map[1], \
|
||||
twai_regs_map[2], twai_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
|
||||
REGDMA_TWAI_LINK(0x01), \
|
||||
TWAI_TIMER_RETENTION_REGS_BASE(id), TWAI_TIMER_RETENTION_REGS_BASE(id), \
|
||||
TWAI_TIMER_RETENTION_REGS_CNT, 0, 0, \
|
||||
twai_timer_regs_map[0], twai_timer_regs_map[1], \
|
||||
twai_timer_regs_map[2], twai_timer_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||
}
|
||||
|
||||
static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1);
|
||||
|
||||
const twai_reg_retention_info_t twai_reg_retention_info[2] = {
|
||||
[0] = {
|
||||
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
|
||||
.entry_array = twai0_regs_retention,
|
||||
.array_size = ARRAY_SIZE(twai0_regs_retention)
|
||||
},
|
||||
[1] = {
|
||||
.module_id = SLEEP_RETENTION_MODULE_TWAI1,
|
||||
.entry_array = twai1_regs_retention,
|
||||
.array_size = ARRAY_SIZE(twai1_regs_retention)
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user