feat(twai): graduate the hal drivers into esp_hal_twai component

This commit is contained in:
morris
2025-11-20 19:20:01 +08:00
parent b9db95731f
commit 37c614d626
74 changed files with 1025 additions and 784 deletions
+2 -2
View File
@@ -32,7 +32,7 @@ endif()
# TWAI related source files
# TWAIFD is not supported by the legacy driver
if(CONFIG_SOC_TWAI_SUPPORTED AND NOT CONFIG_SOC_TWAI_SUPPORT_FD)
if(CONFIG_SOC_TWAI_SUPPORTED AND NOT CONFIG_SOC_TWAI_FD_SUPPORTED)
list(APPEND srcs "twai/twai.c")
list(APPEND ldfragments "twai/linker.lf")
endif()
@@ -45,7 +45,7 @@ else()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${includes}
PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio esp_ringbuf esp_pm
REQUIRES freertos soc hal esp_hw_support esp_hal_i2c
REQUIRES esp_hal_i2c esp_hal_twai
LDFRAGMENTS ${ldfragments}
)
endif()
@@ -10,7 +10,7 @@ components/driver/test_apps/legacy_i2c_driver:
components/driver/test_apps/legacy_twai:
disable:
- if: SOC_TWAI_SUPPORTED != 1 or SOC_TWAI_SUPPORT_FD == 1
- if: SOC_TWAI_SUPPORTED != 1 or SOC_TWAI_FD_SUPPORTED == 1
reason: legacy driver doesn't support FD
- if: IDF_TARGET == "esp32p4"
temporary: true
+1 -1
View File
@@ -8,7 +8,7 @@ entries:
twai: twai_intr_handler_main (noflash)
[mapping:twai_hal_legacy]
archive: libhal.a
archive: libesp_hal_twai.a
entries:
if TWAI_ISR_IN_IRAM = y || TWAI_ISR_IN_IRAM_LEGACY = y:
twai_hal_v1: twai_hal_decode_interrupt (noflash)
+6 -6
View File
@@ -27,7 +27,7 @@
#include "soc/soc_caps.h"
#include "soc/soc.h"
#include "soc/io_mux_reg.h"
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "hal/twai_hal.h"
#include "hal/twai_ll.h"
#include "esp_rom_gpio.h"
@@ -139,7 +139,7 @@ static void twai_alert_handler(twai_obj_t *p_twai_obj, uint32_t alert_code, int
static inline void twai_handle_rx_buffer_frames(twai_obj_t *p_twai_obj, BaseType_t *task_woken, int *alert_req)
{
#ifdef SOC_TWAI_SUPPORTS_RX_STATUS
#if TWAI_LL_SUPPORT(RX_STATUS)
uint32_t msg_count = twai_hal_get_rx_msg_count(p_twai_obj->hal);
for (uint32_t i = 0; i < msg_count; i++) {
@@ -158,7 +158,7 @@ static inline void twai_handle_rx_buffer_frames(twai_obj_t *p_twai_obj, BaseType
twai_alert_handler(p_twai_obj, TWAI_ALERT_RX_FIFO_OVERRUN, alert_req);
}
}
#else //SOC_TWAI_SUPPORTS_RX_STATUS
#else
uint32_t msg_count = twai_hal_get_rx_msg_count(p_twai_obj->hal);
bool overrun = false;
//Clear all valid RX frames
@@ -183,7 +183,7 @@ static inline void twai_handle_rx_buffer_frames(twai_obj_t *p_twai_obj, BaseType
p_twai_obj->rx_overrun_count += twai_hal_clear_rx_fifo_overrun(p_twai_obj->hal);
twai_alert_handler(p_twai_obj, TWAI_ALERT_RX_FIFO_OVERRUN, alert_req);
}
#endif //SOC_TWAI_SUPPORTS_RX_STATUS
#endif // TWAI_LL_SUPPORT(RX_STATUS)
}
static inline void twai_handle_tx_buffer_frame(twai_obj_t *p_twai_obj, bool tx_success, BaseType_t *task_woken, int *alert_req)
@@ -429,7 +429,7 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
p_obj->hal = (twai_hal_context_t *)(p_obj + 1); //hal context is place at end of driver context
#if CONFIG_PM_ENABLE
#if SOC_TWAI_CLK_SUPPORT_APB
#if TWAI_LL_SUPPORT(APB_CLK)
// DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing
if (clk_src == TWAI_CLK_SRC_APB) {
// TODO: pm_lock name should also reflect the controller ID
@@ -444,7 +444,7 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
if (ret != ESP_OK) {
goto err;
}
#endif //SOC_TWAI_CLK_SUPPORT_APB
#endif // TWAI_LL_SUPPORT(APB_CLK)
#endif //CONFIG_PM_ENABLE
#if TWAI_USE_RETENTION_LINK
@@ -15,6 +15,7 @@ endif()
idf_component_register(
SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES esp_hal_twai
PRIV_REQUIRES ${priv_req}
LDFRAGMENTS "linker.lf"
)
+15 -31
View File
@@ -9,6 +9,11 @@
#include "esp_private/twai_interface.h"
#include "esp_private/twai_utils.h"
#include "twai_private.h"
#include "hal/twai_periph.h"
#include "hal/twai_hal.h"
#if SOC_HAS(TWAI_FD)
#include "hal/twaifd_ll.h"
#endif
#if !SOC_RCC_IS_INDEPENDENT
#define TWAI_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
@@ -22,26 +27,6 @@
#define TWAI_PERI_ATOMIC()
#endif
#if SOC_TWAI_SUPPORT_FD
#include "hal/twaifd_ll.h"
static void _twai_rcc_clock_ctrl(uint8_t ctrlr_id, bool enable)
{
TWAI_RCC_ATOMIC() {
twaifd_ll_enable_bus_clock(ctrlr_id, enable);
twaifd_ll_reset_register(ctrlr_id);
}
TWAI_PERI_ATOMIC() {
twaifd_ll_enable_clock(ctrlr_id, enable);
}
}
static void _twai_rcc_clock_sel(uint8_t ctrlr_id, twai_clock_source_t clock)
{
TWAI_PERI_ATOMIC() {
twaifd_ll_set_clock_source(ctrlr_id, clock);
}
}
#else
#include "hal/twai_ll.h"
static void _twai_rcc_clock_ctrl(uint8_t ctrlr_id, bool enable)
{
TWAI_RCC_ATOMIC() {
@@ -58,7 +43,6 @@ static void _twai_rcc_clock_sel(uint8_t ctrlr_id, twai_clock_source_t clock)
twai_ll_set_clock_source(ctrlr_id, clock);
}
}
#endif //SOC_TWAI_SUPPORT_FD
#define TWAI_IDLE_EVENT_BIT BIT0 //event used for tx_wait_all_done
@@ -254,7 +238,7 @@ static void _node_isr_main(void *arg)
if (events & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
while (twai_hal_get_rx_msg_count(twai_ctx->hal)) {
if (twai_hal_read_rx_fifo(twai_ctx->hal, &twai_ctx->rcv_buff)) {
#if !SOC_TWAI_SUPPORT_FD
#if !SOC_HAS(TWAI_FD)
// the legacy hardware filter don't support split frame format std/ext in filter, check in software
if (!twai_hal_soft_filter_check_msg(twai_ctx->hal, &twai_ctx->rcv_buff)) {
continue; // soft filter to check if id type match the filter config
@@ -267,7 +251,7 @@ static void _node_isr_main(void *arg)
atomic_store(&twai_ctx->rx_isr, false);
}
} else { // failed to read from RX fifo because message is overrun
#if !SOC_TWAI_SUPPORTS_RX_STATUS
#if !TWAI_LL_SUPPORT(RX_STATUS)
twai_hal_clear_rx_fifo_overrun(twai_ctx->hal);
break;
#endif
@@ -415,7 +399,7 @@ static esp_err_t _node_set_bit_timing(twai_node_handle_t node, const twai_timing
if (timing) {
twai_hal_configure_timing(twai_ctx->hal, timing);
}
#if SOC_TWAI_SUPPORT_FD
#if SOC_HAS(TWAI_FD)
if (timing_fd) {
twai_ctx->valid_fd_timing = true;
twai_hal_configure_timing_fd(twai_ctx->hal, timing_fd);
@@ -428,7 +412,7 @@ static esp_err_t _node_set_bit_timing(twai_node_handle_t node, const twai_timing
static esp_err_t _node_calc_set_bit_timing(twai_node_handle_t node, twai_clock_source_t clk_src, const twai_timing_basic_config_t *timing, const twai_timing_basic_config_t *timing_fd)
{
ESP_RETURN_ON_FALSE(timing->bitrate, ESP_ERR_INVALID_ARG, TAG, "classic timing config is required");
#if !SOC_TWAI_SUPPORT_FD
#if !SOC_HAS(TWAI_FD)
ESP_RETURN_ON_FALSE((!timing_fd->bitrate) || (timing_fd->bitrate == timing->bitrate), ESP_ERR_INVALID_ARG, TAG, "FD stage bitrate is not supported");
#endif
twai_clock_source_t root_clock_src = clk_src ? clk_src : TWAI_CLK_SRC_DEFAULT;
@@ -452,7 +436,7 @@ static esp_err_t _node_calc_set_bit_timing(twai_node_handle_t node, twai_clock_s
if (timing->bitrate != real_baud) {
ESP_LOGW(TAG, "bitrate precision loss, adjust from %ld to %ld", timing->bitrate, real_baud);
}
#if SOC_TWAI_SUPPORT_FD
#if SOC_HAS(TWAI_FD)
twai_timing_advanced_config_t timing_adv_fd = { .clk_src = root_clock_src, };
if (timing_fd->bitrate) {
real_baud = twai_node_timing_calc_param(source_freq, timing_fd, &hw_const, &timing_adv_fd);
@@ -528,13 +512,13 @@ static esp_err_t _node_config_mask_filter(twai_node_handle_t node, uint8_t filte
uint32_t id = mask_cfg->num_of_ids ? mask_cfg->id_list[0] : mask_cfg->id;
bool full_close = (mask_cfg->mask == UINT32_MAX) && (id == UINT32_MAX);
ESP_RETURN_ON_FALSE(full_close || mask_cfg->dual_filter || mask_cfg->is_ext || !((mask_cfg->mask | id) & ~TWAI_STD_ID_MASK), ESP_ERR_INVALID_ARG, TAG, "std_id only (is_ext=0) but valid id/mask larger than 11 bits");
#if SOC_TWAI_SUPPORT_FD
#if SOC_HAS(TWAI_FD)
// FD targets don't support Dual filter
ESP_RETURN_ON_FALSE(!mask_cfg->dual_filter, ESP_ERR_NOT_SUPPORTED, TAG, "The target don't support Dual Filter");
#endif
ESP_RETURN_ON_FALSE(atomic_load(&twai_ctx->state) == TWAI_ERROR_BUS_OFF, ESP_ERR_INVALID_STATE, TAG, "filter config must do when node stopped");
twai_hal_configure_filter(twai_ctx->hal, filter_id, mask_cfg);
twai_hal_configure_mask_filter(twai_ctx->hal, filter_id, mask_cfg);
return ESP_OK;
}
@@ -587,7 +571,7 @@ static esp_err_t _node_queue_tx(twai_node_handle_t node, const twai_frame_t *fra
if (frame->header.dlc && frame->buffer_len) {
ESP_RETURN_ON_FALSE_ISR(frame->header.dlc == twaifd_len2dlc(frame->buffer_len), ESP_ERR_INVALID_ARG, TAG, "unmatched dlc and buffer_len");
}
#if !SOC_TWAI_SUPPORT_FD
#if !SOC_HAS(TWAI_FD)
ESP_RETURN_ON_FALSE_ISR(!frame->header.fdf || frame->buffer_len <= TWAI_FRAME_MAX_LEN, ESP_ERR_INVALID_ARG, TAG, "fdf flag or buffer_len not supported");
#endif
ESP_RETURN_ON_FALSE_ISR((frame->header.dlc <= TWAIFD_FRAME_MAX_DLC) && \
@@ -714,13 +698,13 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
// Configure GPIO
ESP_GOTO_ON_ERROR(_node_config_io(node, node_config), err, TAG, "gpio config failed");
#if CONFIG_PM_ENABLE
#if SOC_TWAI_CLK_SUPPORT_APB
#if TWAI_LL_SUPPORT(APB_CLK)
// DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, twai_periph_signals[ctrlr_id].module_name, &node->pm_lock), err, TAG, "init power manager failed");
#else // XTAL
// XTAL freq can be closed in light sleep, so we need to create a lock to prevent light sleep
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, twai_periph_signals[ctrlr_id].module_name, &node->pm_lock), err, TAG, "init power manager failed");
#endif //SOC_TWAI_CLK_SUPPORT_APB
#endif //TWAI_LL_SUPPORT(APB_CLK)
#endif //CONFIG_PM_ENABLE
node->api_base.enable = _node_enable;
@@ -31,8 +31,8 @@ typedef struct {
int intr_priority; /**< Interrupt priority, [0:3] */
struct {
uint32_t enable_self_test: 1; /**< Transmission does not require acknowledgment. Use this mode for self testing */
uint32_t enable_loopback: 1; /**< The TWAI controller receive back frames what it send out */
uint32_t enable_listen_only: 1; /**< The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages */
uint32_t enable_loopback: 1; /**< The TWAI controller receives back frames that it sends out, but does not acknowledge them */
uint32_t enable_listen_only: 1; /**< No transmissions or acknowledgements. The controller only monitors the bus without participating */
uint32_t no_receive_rtr: 1; /**< Don't receive remote frames */
} flags; /**< Misc configuration flags */
} twai_onchip_node_config_t;
+2 -2
View File
@@ -12,10 +12,10 @@ entries:
esp_twai: twai_node_transmit (noflash)
[mapping:twai_hal]
archive: libhal.a
archive: libesp_hal_twai.a
entries:
if TWAI_ISR_IN_IRAM = y:
if SOC_TWAI_SUPPORT_FD = y:
if SOC_TWAI_FD_SUPPORTED = y:
twai_hal_v2: twai_hal_format_frame (noflash)
twai_hal_v2: twai_hal_parse_frame (noflash)
twai_hal_v2: twai_hal_set_tx_buffer_and_transmit (noflash)
@@ -15,10 +15,18 @@ check_register_rw_half_word(SOC_MODULES "twai*" "pcr" "hp_sys_clkrst"
HAL_MODULES "twai*")
if(CONFIG_COMPILER_DUMP_RTL_FILES)
# Collect RTL directories in a variable for readability. Join them
# with commas so they are passed as a single --rtl-dirs argument to the script.
set(TWAI_RTL_DIRS
${CMAKE_BINARY_DIR}/esp-idf/esp_driver_twai
${CMAKE_BINARY_DIR}/esp-idf/hal
${CMAKE_BINARY_DIR}/esp-idf/esp_hal_twai
)
string(JOIN "," TWAI_RTL_DIRS_JOINED ${TWAI_RTL_DIRS})
add_custom_target(
check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_twai/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--rtl-dirs ${TWAI_RTL_DIRS_JOINED}
--elf-file ${CMAKE_BINARY_DIR}/test_twai.elf
find-refs
--from-sections=.iram0.text
@@ -4,7 +4,7 @@ if(CONFIG_SOC_TWAI_SUPPORTED)
list(APPEND srcs "test_twai_common.cpp" "test_twai_network.cpp")
endif()
if(CONFIG_SOC_TWAI_SUPPORT_FD)
if(CONFIG_SOC_TWAI_FD_SUPPORTED)
list(APPEND srcs "test_twai_fd.cpp")
endif()
@@ -17,7 +17,7 @@
#include "freertos/FreeRTOS.h"
#include "esp_twai.h"
#include "esp_twai_onchip.h"
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "esp_private/gpio.h"
#include "driver/uart.h" // for baudrate detection
@@ -340,7 +340,7 @@ TEST_CASE("twai mask filter (loopback)", "[twai]")
}
//------------------ Dual Filter Test -------------------//
#if !SOC_TWAI_SUPPORT_FD
#if !SOC_HAS(TWAI_FD)
static IRAM_ATTR bool test_dual_filter_rx_done_cb(twai_node_handle_t handle, const twai_rx_done_event_data_t *edata, void *user_ctx)
{
uint8_t *test_ctrl = (uint8_t *)user_ctx;
@@ -547,7 +547,7 @@ TEST_CASE("twai bus off recovery (loopback)", "[twai]")
}
// recover node
#if SOC_TWAI_SUPPORT_FD
#if SOC_HAS(TWAI_FD)
TEST_ASSERT_GREATER_THAN(200, node_status.tx_error_count);
#else
TEST_ASSERT_EQUAL(128, node_status.tx_error_count); // TEC become 128 when bus off on legacy chips
@@ -25,8 +25,6 @@
#include "esp_check.h"
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "soc/twai_periph.h"
#include "hal/twai_hal.h"
#include "esp_intr_alloc.h"
#include "esp_heap_caps.h"
#include "esp_clk_tree.h"
+25
View File
@@ -0,0 +1,25 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs)
set(public_include "include")
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
list(APPEND public_include "${target}/include")
endif()
if(CONFIG_SOC_TWAI_SUPPORTED)
list(APPEND srcs "${target}/twai_periph.c")
if(CONFIG_SOC_TWAI_FD_SUPPORTED)
list(APPEND srcs "twai_hal_v2.c")
else()
list(APPEND srcs "twai_hal_v1.c")
endif()
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES soc hal)
+49
View File
@@ -0,0 +1,49 @@
# ESP Hardware Abstraction Layer for TWAI Peripheral
> [!NOTE]
> This component is currently in beta. Its API, behavior, and compatibility may change at any time and without notice; backward compatibility is not guaranteed. Use caution when integrating into production systems.
## Overview
The `esp_hal_twai` component provides a **Hardware Abstraction Layer** for the TWAI (Two-Wire Automotive Interface) peripheral across all ESP-IDF supported targets. TWAI is Espressif's implementation of the CAN (Controller Area Network) protocol, widely used in automotive and industrial applications for reliable communication between microcontrollers and devices.
## Architecture
The TWAI HAL is structured in two main sub-layers:
1. **HAL Layer (Upper)**: Defines the operational steps and data structures required to control the TWAI peripheral (e.g., initialization, message transmission/reception, error handling, bus recovery).
2. **Low-Level Layer (Bottom)**: Serves as a translation layer between the HAL and the register files defined in the `soc` component, handling target-specific register configurations.
## Supported TWAI Controllers
This HAL supports two versions of TWAI controllers depending on the ESP chip:
- **TWAI Version 1**: Standard CAN 2.0 controller supporting standard and extended frame formats
- Implementation: `twai_hal_v1.c`
- **TWAI Version 2**: Enhanced controller with TWAI-FD (CAN-FD) support, enabling flexible data-rate for higher bandwidth communication
- Implementation: `twai_hal_v2.c`
## Features
- Message transmission and reception with configurable filtering
- Standard (11-bit) and extended (29-bit) identifier support
- Configurable bit timing and baud rates
- Error detection and error state management
- Bus-off recovery mechanisms
- Interrupt-driven operations
- Self-test mode support
- Acceptance filters for selective message reception
- CAN-FD support with flexible data-rate (on supported chips)
## Usage
The HAL functions primarily serve ESP-IDF peripheral drivers such as the `esp_driver_twai` component.
Advanced developers can use these interfaces directly when implementing custom drivers, with the understanding that API stability is not guaranteed.
## Dependencies
- `soc`: Provides chip-specific register definitions
- `hal`: Core hardware abstraction utilities and macros
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -23,10 +15,15 @@
#include "hal/twai_types.h"
#include "hal/efuse_hal.h"
#include "soc/chip_revision.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/dport_reg.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_APB_CLK 1
#define TWAI_LL_SUPPORT_MULTI_ADDRESS_LAYOUT 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
// When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the
@@ -584,9 +581,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->error_code_capture_reg.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -754,7 +751,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;
@@ -5,10 +5,10 @@
*/
#include "soc/soc.h"
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/gpio_sig_map.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI_INTR_SOURCE,
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,10 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/system_struct.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_SUPPORT_APB_CLK 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send
@@ -510,9 +507,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->error_code_capture_reg.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -680,7 +677,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;
@@ -4,10 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI_INTR_SOURCE,
@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <string.h>
#include "hal/twai_types.h"
#include "soc/pcr_reg.h"
#include "soc/pcr_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
#ifdef __cplusplus
extern "C" {
#endif
/**
* @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)
{
PCR.twai[twai_id].twai_conf.twai_clk_en = enable;
}
/**
* @brief Reset the twai module
*
* @param twai_id Hardware ID
*/
static inline void twai_ll_reset_register(uint8_t twai_id)
{
PCR.twai[twai_id].twai_conf.twai_rst_en = 1;
PCR.twai[twai_id].twai_conf.twai_rst_en = 0;
}
/**
* @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)
{
switch (clk_src) {
case TWAI_CLK_SRC_PLL_F80M:
PCR.twai[twai_id].twai_func_clk_conf.twai_func_clk_sel = 1;
break;
case TWAI_CLK_SRC_XTAL:
PCR.twai[twai_id].twai_func_clk_conf.twai_func_clk_sel = 0;
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)
{
PCR.twai[twai_id].twai_func_clk_conf.twai_func_clk_en = enable;
if (enable) {
while (!PCR.twai[twai_id].twai_conf.twai_ready);
}
}
#ifdef __cplusplus
}
#endif
@@ -4,17 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The Lowlevel layer for TWAI is not public api, don't use in application code.
******************************************************************************/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include "soc/pcr_reg.h"
#include "soc/pcr_struct.h"
@@ -53,76 +44,35 @@ extern "C" {
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
#define TWAIFD_LL_HW_CMD_CLR_OVERRUN TWAIFD_CDO // Clear RX buffer overrun flag
#define TWAIFD_LL_HW_CMD_RX_FLUSH TWAIFD_RRB // Flush RX buffer (read and write pointers are set to 0 and the frame counter is set to 0)
#define TWAIFD_LL_INTR_TX_DONE TWAIFD_TXBHCI_INT_ST// Transmit finish (ok or error)
#define TWAIFD_LL_INTR_TX_SUCCESS TWAIFD_TXI_INT_ST // Transmit success without error
#define TWAIFD_LL_INTR_TX_FRAME TWAIFD_TXI_INT_ST // A frame is transmitted
#define TWAIFD_LL_INTR_RX_FRAME TWAIFD_RXI_INT_ST // A frame is received
#define TWAIFD_LL_INTR_RX_NOT_EMPTY TWAIFD_RBNEI_INT_ST // RX buffer not empty interrupt
#define TWAIFD_LL_INTR_RX_FULL TWAIFD_RXFI_INT_ST // RX buffer full interrupt
#define TWAIFD_LL_INTR_ERR_WARN TWAIFD_EWLI_INT_ST // Error Interrupt
#define TWAIFD_LL_INTR_OVERLOAD TWAIFD_OFI_INT_ST // Overload Frame Interrupt
#define TWAIFD_LL_INTR_ERR_WARN TWAIFD_EWLI_INT_ST // Error warning limit Interrupt
#define TWAIFD_LL_INTR_BUS_ERR TWAIFD_BEI_INT_ST // Bus error interrupt
#define TWAIFD_LL_INTR_FSM_CHANGE TWAIFD_FCSI_INT_ST // Fault confinement state changed interrupt
#define TWAIFD_LL_INTR_ARBI_LOST TWAIFD_ALI_INT_ST // Arbitration Lost Interrupt
#define TWAIFD_LL_INTR_ARBIT_LOST TWAIFD_ALI_INT_ST // Arbitration Lost Interrupt
#define TWAIFD_LL_INTR_DATA_OVERRUN TWAIFD_DOI_INT_ST // Data Overrun Interrupt
#define TWAIFD_LL_INTR_TIMER_OVERFLOW TWAIFD_TIMER_OVERFLOW_INT_ST // Timer overflow interrupt
#define TWAI_LL_DRIVER_INTERRUPTS (TWAIFD_LL_INTR_TX_DONE | TWAIFD_LL_INTR_RX_NOT_EMPTY | TWAIFD_LL_INTR_RX_FULL | \
TWAIFD_LL_INTR_ERR_WARN | TWAIFD_LL_INTR_BUS_ERR | TWAIFD_LL_INTR_FSM_CHANGE | \
TWAIFD_LL_INTR_ARBI_LOST | TWAIFD_LL_INTR_DATA_OVERRUN)
TWAIFD_LL_INTR_ARBIT_LOST | TWAIFD_LL_INTR_DATA_OVERRUN)
/**
* @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 twaifd_ll_enable_bus_clock(uint8_t twai_id, bool enable)
{
PCR.twai[twai_id].twai_conf.twai_clk_en = enable;
}
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Reset the twai module
*
* @param twai_id Hardware ID
*/
static inline void twaifd_ll_reset_register(uint8_t twai_id)
{
PCR.twai[twai_id].twai_conf.twai_rst_en = 1;
PCR.twai[twai_id].twai_conf.twai_rst_en = 0;
}
/**
* @brief Set clock source for TWAI module
*
* @param twai_id Hardware ID
* @param clk_src Clock source
*/
static inline void twaifd_ll_set_clock_source(uint8_t twai_id, twai_clock_source_t clk_src)
{
switch (clk_src) {
case TWAI_CLK_SRC_PLL_F80M:
PCR.twai[twai_id].twai_func_clk_conf.twai_func_clk_sel = 1;
break;
case TWAI_CLK_SRC_XTAL:
PCR.twai[twai_id].twai_func_clk_conf.twai_func_clk_sel = 0;
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 twaifd_ll_enable_clock(uint8_t twai_id, bool enable)
{
PCR.twai[twai_id].twai_func_clk_conf.twai_func_clk_en = enable;
if (enable) {
while (!PCR.twai[twai_id].twai_conf.twai_ready);
}
}
typedef enum {
TWAIFD_LL_TS_POINT_EOF = 0, // in 6th bit of end of frame (moment when the received frame is considered valid)
TWAIFD_LL_TS_POINT_SOF = 1, // start of frame bit
} twaifd_ll_timestamp_point_t;
/**
* @brief Waits for pending changes to take effect in the hardware.
@@ -134,7 +84,6 @@ static inline void twaifd_ll_waiting_state_change(twaifd_dev_t *hw)
while (!hw->int_stat.fcsi_int_st); // Wait until the change is applied
}
/* ---------------------------- Mode Register ------------------------------- */
// WARNING!! Following 'mode_settings' should in same spin_lock` !!!
@@ -151,6 +100,9 @@ static inline void twaifd_ll_reset(twaifd_dev_t *hw)
/**
* @brief Enable or disable hardware.
*
* @note After enable, the node will join the bus after receiving 11 consecutive recessive bits
* @note If disable, the node becomes "bus-off", all TX buffers goes to "empty" state without resetting the memories, RX buffer is flushed.
*
* @param hw Pointer to hardware structure.
* @param enable Boolean flag to enable (true) or disable (false).
*/
@@ -187,6 +139,8 @@ static inline void twaifd_ll_set_mode(twaifd_dev_t *hw, bool listen_only, bool s
/**
* @brief Set the TX retransmission limit.
*
* @note First attempt to transmit TWAI frames does not count as retransmission.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param limit Retransmission limit (0-15, or negative for infinite).
*/
@@ -199,20 +153,31 @@ static inline void twaifd_ll_set_tx_retrans_limit(twaifd_dev_t *hw, int8_t limit
/**
* set bit rate flexible between nominal field and data field
* when set this bit, all frame will be regarded as CANFD frame, even though nominal bit rate and data bit rate are the same
* when set this bit, all frame will be regarded as TWAI FD frame, even though nominal bit rate and data bit rate are the same
*/
static inline void twaifd_ll_enable_fd_mode(twaifd_dev_t *hw, bool ena)
{
hw->mode_settings.fde = ena;
}
/**
* @brief Whether to enable protocol exception handling
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param ena Set to true to enable PEX, false to disable.
*/
static inline void twaifd_ll_enable_pex(twaifd_dev_t *hw, bool ena)
{
hw->mode_settings.pex = ena;
}
/**
* @brief Enable or disable the RX fifo automatic increase when read to register
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param ena Set to true to enable RX automatic mode, false to disable.
*/
static inline void twaifd_ll_enable_rxfifo_auto_incrase(twaifd_dev_t *hw, bool ena)
static inline void twaifd_ll_enable_rxfifo_auto_increase(twaifd_dev_t *hw, bool ena)
{
hw->mode_settings.rxbam = ena;
}
@@ -231,12 +196,36 @@ static inline void twaifd_ll_enable_filter_mode(twaifd_dev_t* hw, bool enable)
}
/**
* @brief Set remote frame filtering behaviour.
* @brief Enable or disable the test mode for the TWAI-FD peripheral.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable test mode, false to disable.
*/
static inline void twaifd_ll_enable_test_mode(twaifd_dev_t* hw, bool enable)
{
hw->mode_settings.tstm = enable;
}
/**
* @brief Enable or disable the parity error detection for the RX and TX buffers.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable parity error detection, false to disable.
*/
static inline void twaifd_ll_enable_parity_error_detection(twaifd_dev_t* hw, bool enable)
{
// Must be called when hardware is disabled.
HAL_ASSERT(hw->mode_settings.ena == 0);
hw->mode_settings.pchke = enable;
}
/**
* @brief Whether to drop the RTR frames in filter.
*
* @param hw Pointer to hardware structure.
* @param en True to drop, false to Receive to next filter
* @param en True to drop, false to pass it to the next filter
*/
static inline void twaifd_ll_filter_block_rtr(twaifd_dev_t* hw, bool en)
static inline void twaifd_ll_filter_drop_rtr(twaifd_dev_t* hw, bool en)
{
hw->mode_settings.fdrf = en;
}
@@ -244,6 +233,8 @@ static inline void twaifd_ll_filter_block_rtr(twaifd_dev_t* hw, bool en)
/**
* @brief Enable or disable the time-triggered transmission mode for the TWAI-FD peripheral.
*
* @note Time triggered transmission is always considered only from the highest priority TX buffer in ready state.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable time-triggered transmission mode, false to disable.
*/
@@ -252,6 +243,19 @@ static inline void twaifd_ll_enable_time_trig_trans_mode(twaifd_dev_t* hw, bool
hw->mode_settings.tttm = enable;
}
/**
* @brief Whether to treat bus-off as TX failure
*
* @note Disable it, it allows going bus-off and re-integrating without the need of software interaction with TX buffers.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable, false to disable.
*/
static inline void twaifd_ll_enable_bus_off_tx_fail_mode(twaifd_dev_t* hw, bool enable)
{
hw->mode_settings.tbfbo = enable;
}
/* --------------------------- Command Register ----------------------------- */
/**
* @brief Set command to TWAIFD hardware
@@ -365,6 +369,17 @@ static inline void twaifd_ll_config_secondary_sample_point(twaifd_dev_t *hw, uin
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->trv_delay_ssp_cfg, ssp_offset, offset_val);
}
/**
* @brief Get measured transmitter delay
*
* @param hw Start address of the TWAI registers
* @return Transmitter Delay Value in clock source cycles, include the input delay of TWAI FD (2 cycles)
*/
static inline uint32_t twaifd_ll_get_transmitter_delay(twaifd_dev_t *hw)
{
return hw->trv_delay_ssp_cfg.trv_delay_value;
}
/* ----------------------------- ERR Capt Register ------------------------------- */
/**
@@ -426,10 +441,10 @@ static inline twai_error_state_t twaifd_ll_get_fault_state(twaifd_dev_t *hw)
}
/**
* @brief Get the error count in normal mode for the TWAI-FD peripheral.
* @brief Get the error count in nominal bit rate stage.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Error count in normal mode.
* @return Error count in nominal bit rate stage.
*/
static inline uint32_t twaifd_ll_get_err_count_norm(twaifd_dev_t *hw)
{
@@ -437,10 +452,10 @@ static inline uint32_t twaifd_ll_get_err_count_norm(twaifd_dev_t *hw)
}
/**
* @brief Get the error count in FD mode for the TWAI-FD peripheral.
* @brief Get the error count in FD data bit rate stage.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Error count in FD mode.
* @return Error count in FD data bit rate stage.
*/
static inline uint32_t twaifd_ll_get_err_count_fd(twaifd_dev_t *hw)
{
@@ -475,122 +490,174 @@ static inline uint32_t twaifd_ll_get_tec(twaifd_dev_t *hw)
/* ---------------------- Acceptance Filter Registers ----------------------- */
/**
* @brief Enable or disable filter to receive basic frame with std id
* @brief Enable or disable mask filter to receive classic frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_basic_std(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_classic_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FANB << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x01 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FANB << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x01 << (filter_id * 4));
}
}
/**
* @brief Enable or disable filter to receive basic frame with ext id
* @brief Enable or disable mask filter to receive classic frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_basic_ext(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_classic_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FANE << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x02 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FANE << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x02 << (filter_id * 4));
}
}
/**
* @brief Enable or disable filter to receive fd frame with std id
* @brief Enable or disable mask filter to receive fd frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_fd_std(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_fd_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FAFB << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x04 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FAFB << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x04 << (filter_id * 4));
}
}
/**
* @brief Enable or disable filter to receive fd frame with ext id
* @brief Enable or disable mask filter to receive fd frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_fd_ext(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_fd_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FAFE << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x08 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FAFE << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x08 << (filter_id * 4));
}
}
/**
* @brief Set Bit Acceptance Filter
* @brief Enable or disable range filter to receive classic frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_classic_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x01 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x01 << (hw_filter_id * 4));
}
}
/**
* @brief Enable or disable range filter to receive classic frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_classic_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x02 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x02 << (hw_filter_id * 4));
}
}
/**
* @brief Enable or disable range filter to receive fd frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_fd_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x04 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x04 << (hw_filter_id * 4));
}
}
/**
* @brief Enable or disable range filter to receive fd frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_fd_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x08 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x08 << (hw_filter_id * 4));
}
}
/**
* @brief Set the ID and mask for mask filter
* @param hw Start address of the TWAI registers
* @param filter_id Filter number id
* @param is_ext Filter for ext_id or std_id
* @param code Acceptance Code
* @param mask Acceptance Mask
*/
static inline void twaifd_ll_filter_set_id_mask(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t code, uint32_t mask)
static inline void twaifd_ll_mask_filter_set_id_mask(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t code, uint32_t mask)
{
hw->mask_filters[filter_id].filter_mask.bit_mask_val = is_ext ? mask : (mask << TWAIFD_IDENTIFIER_BASE_S);
hw->mask_filters[filter_id].filter_val.bit_val = is_ext ? code : (code << TWAIFD_IDENTIFIER_BASE_S);
}
/**
* @brief Set Range Acceptance Filter
* @brief Set the ID range for range filter
* @param hw Start address of the TWAI registers
* @param filter_id Filter number id
* @param is_ext Filter for ext_id or std_id
* @param high The id range high limit
* @param low The id range low limit
*/
static inline void twaifd_ll_filter_set_range(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t high, uint32_t low)
static inline void twaifd_ll_range_filter_set_id_thres(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t high, uint32_t low)
{
hw->range_filters[filter_id].ran_low.bit_ran_low_val = is_ext ? low : (low << TWAIFD_IDENTIFIER_BASE_S);
hw->range_filters[filter_id].ran_high.bit_ran_high_val = is_ext ? high : (high << TWAIFD_IDENTIFIER_BASE_S);
hw->range_filters[filter_id].ran_high.bit_ran_high_val = is_ext ? high : (high << TWAIFD_IDENTIFIER_BASE_S) | 0x3FFFF;
}
/* ------------------------- TX Buffer Registers ------------------------- */
/**
* @brief Get the number of TX buffers available.
* @brief Get the number of TX buffers that are preset in the hardware.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return The number of TX buffers available.
*/
static inline uint32_t twaifd_ll_get_tx_buffer_quantity(twaifd_dev_t *hw)
static inline uint32_t twaifd_ll_get_tx_buffer_total(twaifd_dev_t *hw)
{
return hw->tx_command_txtb_info.txt_buffer_count;
}
@@ -604,24 +671,24 @@ static inline uint32_t twaifd_ll_get_tx_buffer_quantity(twaifd_dev_t *hw)
*/
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
{
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_quantity(hw)); // Ensure buffer index is valid
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
uint32_t reg_val = hw->tx_status.val;
return reg_val & (TWAIFD_TX2S_V << (TWAIFD_TX2S_S * buffer_idx)); // Get status for buffer
}
/**
* @brief Set TX Buffer command
* @brief Set TX Buffer command
*
* Setting the TX command will cause the TWAI controller to attempt to transmit
* the frame stored in the TX buffer. The TX buffer will be occupied (i.e.,
* locked) until TX completes.
*
* @param hw Start address of the TWAI registers
* @param buffer_idx
* @param buffer_idx The tx buffer index to set the command
* @param cmd The command want to set, see `TWAIFD_LL_TX_CMD_`
*/
__attribute__((always_inline))
static inline void twaifd_ll_set_tx_cmd(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t cmd)
static inline void twaifd_ll_set_tx_buffer_cmd(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t cmd)
{
hw->tx_command_txtb_info.val = (cmd | BIT(buffer_idx + TWAIFD_TXB1_S));
}
@@ -629,13 +696,15 @@ static inline void twaifd_ll_set_tx_cmd(twaifd_dev_t *hw, uint8_t buffer_idx, ui
/**
* @brief Set the priority for a specific TX buffer.
*
* @note If two TX buffers have equal priority, TX buffer with the lower index has precedence.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param buffer_idx Index of the TX buffer (0-7).
* @param priority The priority level to set for the buffer.
* @param priority The priority level to set for the buffer. Higher values indicate higher priority.
*/
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
{
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_quantity(hw)); // Ensure buffer index is valid
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
uint32_t reg_val = hw->tx_priority.val;
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
@@ -665,14 +734,27 @@ static inline void twaifd_ll_mount_tx_buffer(twaifd_dev_t *hw, twaifd_frame_buff
/**
* @brief Get the size of the RX buffer.
*
* @note It contains a single RX buffer where received frames are stored.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Size of the RX buffer.
* @return Size of the RX buffer, in multiple of 32-bit words.
*/
static inline uint32_t twaifd_ll_get_rx_buffer_size(twaifd_dev_t *hw)
{
return hw->rx_mem_info.rx_buff_size;
}
/**
* @brief Get the free space in the RX buffer.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Free space in the RX buffer, in multiple of 32-bit words.
*/
static inline uint32_t twaifd_ll_get_rx_free_space(twaifd_dev_t *hw)
{
return hw->rx_mem_info.rx_free;
}
/**
* @brief Get the number of frames in the RX buffer.
*
@@ -689,15 +771,26 @@ static inline uint32_t twaifd_ll_get_rx_frame_count(twaifd_dev_t *hw)
* @brief Check if the RX FIFO is empty.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return 1 if RX FIFO is empty, 0 otherwise.
* @return true if RX FIFO is empty, false otherwise.
*/
static inline uint32_t twaifd_ll_is_rx_buffer_empty(twaifd_dev_t *hw)
static inline bool twaifd_ll_is_rx_buffer_empty(twaifd_dev_t *hw)
{
return hw->rx_status_rx_settings.rxe;
}
/**
* @brief Copy a received frame from the RX buffer for parsing
* @brief Check if the RX FIFO is full.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return true if RX FIFO is full, false otherwise.
*/
static inline bool twaifd_ll_is_rx_buffer_full(twaifd_dev_t *hw)
{
return hw->rx_status_rx_settings.rxf;
}
/**
* @brief Copy a received frame from the RX buffer for parsing
*
* @param hw Start address of the TWAI registers
* @param rx_frame Pointer to store formatted frame
@@ -835,18 +928,29 @@ static inline uint32_t twaifd_ll_get_tx_traffic_counter(twaifd_dev_t *hw)
/* ------------------------- Timestamp Register ------------------------- */
/**
* @brief Enable or disable the timer clock.
* @brief Set the sample point for the timestamp.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param sample_point Sample point for the timestamp.
*/
static inline void twaifd_ll_ts_set_sample_point(twaifd_dev_t *hw, twaifd_ll_timestamp_point_t sample_point)
{
hw->rx_status_rx_settings.rtsop = sample_point;
}
/**
* @brief Whether to force enable the register config clock of the timer
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable True to enable, false to disable.
*/
static inline void twaifd_ll_timer_enable_clock(twaifd_dev_t *hw, bool enable)
static inline void twaifd_ll_timer_force_enable_cfg_clock(twaifd_dev_t *hw, bool enable)
{
hw->timer_clk_en.clk_en = enable;
}
/**
* @brief Enable or disable timer power.
* @brief Enable or disable the timer.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable True to enable, false to disable.
@@ -856,9 +960,34 @@ static inline void twaifd_ll_timer_enable(twaifd_dev_t *hw, bool enable)
hw->timer_cfg.timer_ce = enable;
}
/**
* @brief Get the bit width of the timer.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Bit width of the timer.
*/
static inline uint8_t twaifd_ll_timer_get_bitwidth(twaifd_dev_t *hw)
{
return hw->err_capt_retr_ctr_alc_ts_info.ts_bits + 1;
}
/**
* @brief Get the current timer count.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Current timer count as a 64-bit value.
*/
static inline uint64_t twaifd_ll_timer_get_count(twaifd_dev_t *hw)
{
uint64_t count = ((uint64_t)hw->timestamp_high.val << 32) | hw->timestamp_low.val;
return count;
}
/**
* @brief Set the timer step value.
*
* @note This is to determine the resolution of the timer. We can also treat it as a prescaler.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param step Step value to set (actual step = step - 1).
*/
@@ -4,8 +4,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[2] = {
[0] = {
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,11 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/twai_struct.h"
#include "soc/pcr_struct.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI0) : (&TWAI1))
#ifdef __cplusplus
@@ -521,9 +517,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->err_code_cap.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -691,7 +687,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;
@@ -4,11 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[2] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI0_INTR_SOURCE,
@@ -62,7 +63,7 @@ static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0};
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[SOC_TWAI_CONTROLLER_NUM] = {
const twai_reg_retention_info_t twai_reg_retention_info[2] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,11 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/twai_struct.h"
#include "soc/pcr_struct.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI0) : NULL)
#ifdef __cplusplus
@@ -499,9 +495,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->err_code_cap.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -669,7 +665,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;
@@ -4,11 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI0_INTR_SOURCE,
@@ -51,7 +52,7 @@ static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0};
}
static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0);
const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = {
const twai_reg_retention_info_t twai_reg_retention_info[1] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,11 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/twai_struct.h"
#include "soc/pcr_struct.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
#ifdef __cplusplus
@@ -499,9 +495,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->err_code_cap.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -669,7 +665,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;
@@ -4,11 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI0_INTR_SOURCE,
@@ -51,7 +52,7 @@ static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0};
}
static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0);
const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = {
const twai_reg_retention_info_t twai_reg_retention_info[1] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
@@ -0,0 +1,87 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <string.h>
#include "hal/twai_types.h"
#include "soc/pcr_reg.h"
#include "soc/pcr_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
#ifdef __cplusplus
extern "C" {
#endif
/**
* @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)
{
PCR.twai0_conf.twai0_clk_en = enable;
}
/**
* @brief Reset the twai module
*
* @param twai_id Hardware ID
*/
static inline void twai_ll_reset_register(uint8_t twai_id)
{
PCR.twai0_conf.twai0_rst_en = 1;
PCR.twai0_conf.twai0_rst_en = 0;
}
/**
* @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)
{
switch (clk_src) {
case TWAI_CLK_SRC_XTAL:
PCR.twai0_func_clk_conf.twai0_func_clk_sel = 0;
break;
case TWAI_CLK_SRC_PLL_F96M:
PCR.twai0_func_clk_conf.twai0_func_clk_sel = 2;
break;
// We do not plan to support the TWAI_CLK_SRC_RC_FAST clock source,
// as the accuracy of this clock does not meet the requirements for the baud rate
// case TWAI_CLK_SRC_RC_FAST:
// PCR.twai0_func_clk_conf.twai0_func_clk_sel = 1;
// 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)
{
PCR.twai0_func_clk_conf.twai0_func_clk_en = enable;
if (enable) {
while (!PCR.twai0_conf.twai0_ready);
}
}
#ifdef __cplusplus
}
#endif
@@ -4,17 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The Lowlevel layer for TWAI is not public api, don't use in application code.
******************************************************************************/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include "soc/pcr_reg.h"
#include "soc/pcr_struct.h"
@@ -53,81 +44,35 @@ extern "C" {
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
#define TWAIFD_LL_HW_CMD_CLR_OVERRUN TWAIFD_CDO // Clear RX buffer overrun flag
#define TWAIFD_LL_HW_CMD_RX_FLUSH TWAIFD_RRB // Flush RX buffer (read and write pointers are set to 0 and the frame counter is set to 0)
#define TWAIFD_LL_INTR_TX_DONE TWAIFD_TXBHCI_INT_ST// Transmit finish (ok or error)
#define TWAIFD_LL_INTR_TX_SUCCESS TWAIFD_TXI_INT_ST // Transmit success without error
#define TWAIFD_LL_INTR_TX_FRAME TWAIFD_TXI_INT_ST // A frame is transmitted
#define TWAIFD_LL_INTR_RX_FRAME TWAIFD_RXI_INT_ST // A frame is received
#define TWAIFD_LL_INTR_RX_NOT_EMPTY TWAIFD_RBNEI_INT_ST // RX buffer not empty interrupt
#define TWAIFD_LL_INTR_RX_FULL TWAIFD_RXFI_INT_ST // RX buffer full interrupt
#define TWAIFD_LL_INTR_ERR_WARN TWAIFD_EWLI_INT_ST // Error Interrupt
#define TWAIFD_LL_INTR_OVERLOAD TWAIFD_OFI_INT_ST // Overload Frame Interrupt
#define TWAIFD_LL_INTR_ERR_WARN TWAIFD_EWLI_INT_ST // Error warning limit Interrupt
#define TWAIFD_LL_INTR_BUS_ERR TWAIFD_BEI_INT_ST // Bus error interrupt
#define TWAIFD_LL_INTR_FSM_CHANGE TWAIFD_FCSI_INT_ST // Fault confinement state changed interrupt
#define TWAIFD_LL_INTR_ARBI_LOST TWAIFD_ALI_INT_ST // Arbitration Lost Interrupt
#define TWAIFD_LL_INTR_ARBIT_LOST TWAIFD_ALI_INT_ST // Arbitration Lost Interrupt
#define TWAIFD_LL_INTR_DATA_OVERRUN TWAIFD_DOI_INT_ST // Data Overrun Interrupt
#define TWAIFD_LL_INTR_TIMER_OVERFLOW TWAIFD_TIMER_OVERFLOW_INT_ST // Timer overflow interrupt
#define TWAI_LL_DRIVER_INTERRUPTS (TWAIFD_LL_INTR_TX_DONE | TWAIFD_LL_INTR_RX_NOT_EMPTY | TWAIFD_LL_INTR_RX_FULL | \
TWAIFD_LL_INTR_ERR_WARN | TWAIFD_LL_INTR_BUS_ERR | TWAIFD_LL_INTR_FSM_CHANGE | \
TWAIFD_LL_INTR_ARBI_LOST | TWAIFD_LL_INTR_DATA_OVERRUN)
TWAIFD_LL_INTR_ARBIT_LOST | TWAIFD_LL_INTR_DATA_OVERRUN)
/**
* @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 twaifd_ll_enable_bus_clock(uint8_t twai_id, bool enable)
{
PCR.twai0_conf.twai0_clk_en = enable;
}
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Reset the twai module
*
* @param twai_id Hardware ID
*/
static inline void twaifd_ll_reset_register(uint8_t twai_id)
{
PCR.twai0_conf.twai0_rst_en = 1;
PCR.twai0_conf.twai0_rst_en = 0;
}
/**
* @brief Set clock source for TWAI module
*
* @param twai_id Hardware ID
* @param clk_src Clock source
*/
static inline void twaifd_ll_set_clock_source(uint8_t twai_id, twai_clock_source_t clk_src)
{
switch (clk_src) {
case TWAI_CLK_SRC_XTAL:
PCR.twai0_func_clk_conf.twai0_func_clk_sel = 0;
break;
case TWAI_CLK_SRC_PLL_F96M:
PCR.twai0_func_clk_conf.twai0_func_clk_sel = 2;
break;
// We do not plan to support the TWAI_CLK_SRC_RC_FAST clock source,
// as the accuracy of this clock does not meet the requirements for the baud rate
// case TWAI_CLK_SRC_RC_FAST:
// PCR.twai0_func_clk_conf.twai0_func_clk_sel = 1;
// 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 twaifd_ll_enable_clock(uint8_t twai_id, bool enable)
{
PCR.twai0_func_clk_conf.twai0_func_clk_en = enable;
if (enable) {
while (!PCR.twai0_conf.twai0_ready);
}
}
typedef enum {
TWAIFD_LL_TS_POINT_EOF = 0, // in 6th bit of end of frame (moment when the received frame is considered valid)
TWAIFD_LL_TS_POINT_SOF = 1, // start of frame bit
} twaifd_ll_timestamp_point_t;
/**
* @brief Waits for pending changes to take effect in the hardware.
@@ -139,7 +84,6 @@ static inline void twaifd_ll_waiting_state_change(twaifd_dev_t *hw)
while (!hw->int_stat.fcsi_int_st); // Wait until the change is applied
}
/* ---------------------------- Mode Register ------------------------------- */
// WARNING!! Following 'mode_settings' should in same spin_lock` !!!
@@ -156,6 +100,9 @@ static inline void twaifd_ll_reset(twaifd_dev_t *hw)
/**
* @brief Enable or disable hardware.
*
* @note After enable, the node will join the bus after receiving 11 consecutive recessive bits
* @note If disable, the node becomes "bus-off", all TX buffers goes to "empty" state without resetting the memories, RX buffer is flushed.
*
* @param hw Pointer to hardware structure.
* @param enable Boolean flag to enable (true) or disable (false).
*/
@@ -191,6 +138,8 @@ static inline void twaifd_ll_set_mode(twaifd_dev_t *hw, bool listen_only, bool s
/**
* @brief Set the TX retransmission limit.
*
* @note First attempt to transmit TWAI frames does not count as retransmission.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param limit Retransmission limit (0-15, or negative for infinite).
*/
@@ -203,20 +152,31 @@ static inline void twaifd_ll_set_tx_retrans_limit(twaifd_dev_t *hw, int8_t limit
/**
* set bit rate flexible between nominal field and data field
* when set this bit, all frame will be regarded as CANFD frame, even though nominal bit rate and data bit rate are the same
* when set this bit, all frame will be regarded as TWAI FD frame, even though nominal bit rate and data bit rate are the same
*/
static inline void twaifd_ll_enable_fd_mode(twaifd_dev_t *hw, bool ena)
{
hw->mode_settings.fde = ena;
}
/**
* @brief Whether to enable protocol exception handling
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param ena Set to true to enable PEX, false to disable.
*/
static inline void twaifd_ll_enable_pex(twaifd_dev_t *hw, bool ena)
{
hw->mode_settings.pex = ena;
}
/**
* @brief Enable or disable the RX fifo automatic increase when read to register
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param ena Set to true to enable RX automatic mode, false to disable.
*/
static inline void twaifd_ll_enable_rxfifo_auto_incrase(twaifd_dev_t *hw, bool ena)
static inline void twaifd_ll_enable_rxfifo_auto_increase(twaifd_dev_t *hw, bool ena)
{
hw->mode_settings.rxbam = ena;
}
@@ -235,12 +195,36 @@ static inline void twaifd_ll_enable_filter_mode(twaifd_dev_t* hw, bool enable)
}
/**
* @brief Set remote frame filtering behaviour.
* @brief Enable or disable the test mode for the TWAI-FD peripheral.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable test mode, false to disable.
*/
static inline void twaifd_ll_enable_test_mode(twaifd_dev_t* hw, bool enable)
{
hw->mode_settings.tstm = enable;
}
/**
* @brief Enable or disable the parity error detection for the RX and TX buffers.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable parity error detection, false to disable.
*/
static inline void twaifd_ll_enable_parity_error_detection(twaifd_dev_t* hw, bool enable)
{
// Must be called when hardware is disabled.
HAL_ASSERT(hw->mode_settings.ena == 0);
hw->mode_settings.pchke = enable;
}
/**
* @brief Whether to drop the RTR frames in filter.
*
* @param hw Pointer to hardware structure.
* @param en True to drop, false to Receive to next filter
* @param en True to drop, false to pass it to the next filter
*/
static inline void twaifd_ll_filter_block_rtr(twaifd_dev_t* hw, bool en)
static inline void twaifd_ll_filter_drop_rtr(twaifd_dev_t* hw, bool en)
{
hw->mode_settings.fdrf = en;
}
@@ -248,6 +232,8 @@ static inline void twaifd_ll_filter_block_rtr(twaifd_dev_t* hw, bool en)
/**
* @brief Enable or disable the time-triggered transmission mode for the TWAI-FD peripheral.
*
* @note Time triggered transmission is always considered only from the highest priority TX buffer in ready state.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable time-triggered transmission mode, false to disable.
*/
@@ -256,6 +242,19 @@ static inline void twaifd_ll_enable_time_trig_trans_mode(twaifd_dev_t* hw, bool
hw->mode_settings.tttm = enable;
}
/**
* @brief Whether to treat bus-off as TX failure
*
* @note Disable it, it allows going bus-off and re-integrating without the need of software interaction with TX buffers.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable Set to true to enable, false to disable.
*/
static inline void twaifd_ll_enable_bus_off_tx_fail_mode(twaifd_dev_t* hw, bool enable)
{
hw->mode_settings.tbfbo = enable;
}
/* --------------------------- Command Register ----------------------------- */
/**
* @brief Set command to TWAIFD hardware
@@ -369,6 +368,17 @@ static inline void twaifd_ll_config_secondary_sample_point(twaifd_dev_t *hw, uin
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->trv_delay_ssp_cfg, ssp_offset, offset_val);
}
/**
* @brief Get measured transmitter delay
*
* @param hw Start address of the TWAI registers
* @return Transmitter Delay Value in clock source cycles, include the input delay of TWAI FD (2 cycles)
*/
static inline uint32_t twaifd_ll_get_transmitter_delay(twaifd_dev_t *hw)
{
return hw->trv_delay_ssp_cfg.trv_delay_value;
}
/* ----------------------------- ERR Capt Register ------------------------------- */
/**
@@ -430,10 +440,10 @@ static inline twai_error_state_t twaifd_ll_get_fault_state(twaifd_dev_t *hw)
}
/**
* @brief Get the error count in normal mode for the TWAI-FD peripheral.
* @brief Get the error count in nominal bit rate stage.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Error count in normal mode.
* @return Error count in nominal bit rate stage.
*/
static inline uint32_t twaifd_ll_get_err_count_norm(twaifd_dev_t *hw)
{
@@ -441,10 +451,10 @@ static inline uint32_t twaifd_ll_get_err_count_norm(twaifd_dev_t *hw)
}
/**
* @brief Get the error count in FD mode for the TWAI-FD peripheral.
* @brief Get the error count in FD data bit rate stage.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Error count in FD mode.
* @return Error count in FD data bit rate stage.
*/
static inline uint32_t twaifd_ll_get_err_count_fd(twaifd_dev_t *hw)
{
@@ -479,122 +489,174 @@ static inline uint32_t twaifd_ll_get_tec(twaifd_dev_t *hw)
/* ---------------------- Acceptance Filter Registers ----------------------- */
/**
* @brief Enable or disable filter to receive basic frame with std id
* @brief Enable or disable mask filter to receive classic frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_basic_std(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_classic_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FANB << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x01 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FANB << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x01 << (filter_id * 4));
}
}
/**
* @brief Enable or disable filter to receive basic frame with ext id
* @brief Enable or disable mask filter to receive classic frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_basic_ext(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_classic_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FANE << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x02 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FANE << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x02 << (filter_id * 4));
}
}
/**
* @brief Enable or disable filter to receive fd frame with std id
* @brief Enable or disable mask filter to receive fd frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_fd_std(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_fd_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FAFB << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x04 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FAFB << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x04 << (filter_id * 4));
}
}
/**
* @brief Enable or disable filter to receive fd frame with ext id
* @brief Enable or disable mask filter to receive fd frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the filter to configure
* @param is_range Setting for range filter or mask filter
* @param en True to receive, False to drop
* @param filter_id The unique ID of the mask filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_filter_enable_fd_ext(twaifd_dev_t* hw, uint8_t filter_id, bool is_range, bool en)
static inline void twaifd_ll_mask_filter_accept_fd_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
HAL_ASSERT(filter_id < (is_range ? SOC_TWAI_RANGE_FILTER_NUM : SOC_TWAI_MASK_FILTER_NUM));
// The hw_filter_id of range_filter is indexed after mask_filter
uint8_t hw_filter_id = is_range ? filter_id + SOC_TWAI_MASK_FILTER_NUM : filter_id;
if (en) {
hw->filter_control_filter_status.val |= TWAIFD_FAFE << (hw_filter_id * TWAIFD_FBNB_S);
if (accept) {
hw->filter_control_filter_status.val |= 0x08 << (filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(TWAIFD_FAFE << (hw_filter_id * TWAIFD_FBNB_S));
hw->filter_control_filter_status.val &= ~(0x08 << (filter_id * 4));
}
}
/**
* @brief Set Bit Acceptance Filter
* @brief Enable or disable range filter to receive classic frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_classic_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x01 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x01 << (hw_filter_id * 4));
}
}
/**
* @brief Enable or disable range filter to receive classic frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_classic_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x02 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x02 << (hw_filter_id * 4));
}
}
/**
* @brief Enable or disable range filter to receive fd frame with std id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_fd_std(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x04 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x04 << (hw_filter_id * 4));
}
}
/**
* @brief Enable or disable range filter to receive fd frame with ext id
*
* @param hw Pointer to the TWAI FD hardware instance
* @param filter_id The unique ID of the range filter to configure
* @param accept True to accept the frame, False to drop the frame
*/
static inline void twaifd_ll_range_filter_accept_fd_ext(twaifd_dev_t* hw, uint8_t filter_id, bool accept)
{
uint8_t hw_filter_id = filter_id + 3;
if (accept) {
hw->filter_control_filter_status.val |= 0x08 << (hw_filter_id * 4);
} else {
hw->filter_control_filter_status.val &= ~(0x08 << (hw_filter_id * 4));
}
}
/**
* @brief Set the ID and mask for mask filter
* @param hw Start address of the TWAI registers
* @param filter_id Filter number id
* @param is_ext Filter for ext_id or std_id
* @param code Acceptance Code
* @param mask Acceptance Mask
*/
static inline void twaifd_ll_filter_set_id_mask(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t code, uint32_t mask)
static inline void twaifd_ll_mask_filter_set_id_mask(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t code, uint32_t mask)
{
hw->mask_filters[filter_id].filter_mask.bit_mask_val = is_ext ? mask : (mask << TWAIFD_IDENTIFIER_BASE_S);
hw->mask_filters[filter_id].filter_val.bit_val = is_ext ? code : (code << TWAIFD_IDENTIFIER_BASE_S);
}
/**
* @brief Set Range Acceptance Filter
* @brief Set the ID range for range filter
* @param hw Start address of the TWAI registers
* @param filter_id Filter number id
* @param is_ext Filter for ext_id or std_id
* @param high The id range high limit
* @param low The id range low limit
*/
static inline void twaifd_ll_filter_set_range(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t high, uint32_t low)
static inline void twaifd_ll_range_filter_set_id_thres(twaifd_dev_t* hw, uint8_t filter_id, bool is_ext, uint32_t high, uint32_t low)
{
hw->range_filters[filter_id].ran_low.bit_ran_low_val = is_ext ? low : (low << TWAIFD_IDENTIFIER_BASE_S);
hw->range_filters[filter_id].ran_high.bit_ran_high_val = is_ext ? high : (high << TWAIFD_IDENTIFIER_BASE_S);
hw->range_filters[filter_id].ran_high.bit_ran_high_val = is_ext ? high : (high << TWAIFD_IDENTIFIER_BASE_S) | 0x3FFFF;
}
/* ------------------------- TX Buffer Registers ------------------------- */
/**
* @brief Get the number of TX buffers available.
* @brief Get the number of TX buffers that are preset in the hardware.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return The number of TX buffers available.
*/
static inline uint32_t twaifd_ll_get_tx_buffer_quantity(twaifd_dev_t *hw)
static inline uint32_t twaifd_ll_get_tx_buffer_total(twaifd_dev_t *hw)
{
return hw->tx_command_txtb_info.txt_buffer_count;
}
@@ -608,24 +670,24 @@ static inline uint32_t twaifd_ll_get_tx_buffer_quantity(twaifd_dev_t *hw)
*/
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
{
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_quantity(hw)); // Ensure buffer index is valid
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
uint32_t reg_val = hw->tx_status.val;
return reg_val & (TWAIFD_TX2S_V << (TWAIFD_TX2S_S * buffer_idx)); // Get status for buffer
}
/**
* @brief Set TX Buffer command
* @brief Set TX Buffer command
*
* Setting the TX command will cause the TWAI controller to attempt to transmit
* the frame stored in the TX buffer. The TX buffer will be occupied (i.e.,
* locked) until TX completes.
*
* @param hw Start address of the TWAI registers
* @param buffer_idx
* @param buffer_idx The tx buffer index to set the command
* @param cmd The command want to set, see `TWAIFD_LL_TX_CMD_`
*/
__attribute__((always_inline))
static inline void twaifd_ll_set_tx_cmd(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t cmd)
static inline void twaifd_ll_set_tx_buffer_cmd(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t cmd)
{
hw->tx_command_txtb_info.val = (cmd | BIT(buffer_idx + TWAIFD_TXB1_S));
}
@@ -633,13 +695,15 @@ static inline void twaifd_ll_set_tx_cmd(twaifd_dev_t *hw, uint8_t buffer_idx, ui
/**
* @brief Set the priority for a specific TX buffer.
*
* @note If two TX buffers have equal priority, TX buffer with the lower index has precedence.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param buffer_idx Index of the TX buffer (0-7).
* @param priority The priority level to set for the buffer.
* @param priority The priority level to set for the buffer. Higher values indicate higher priority.
*/
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
{
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_quantity(hw)); // Ensure buffer index is valid
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
uint32_t reg_val = hw->tx_priority.val;
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
@@ -669,14 +733,27 @@ static inline void twaifd_ll_mount_tx_buffer(twaifd_dev_t *hw, twaifd_frame_buff
/**
* @brief Get the size of the RX buffer.
*
* @note It contains a single RX buffer where received frames are stored.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Size of the RX buffer.
* @return Size of the RX buffer, in multiple of 32-bit words.
*/
static inline uint32_t twaifd_ll_get_rx_buffer_size(twaifd_dev_t *hw)
{
return hw->rx_mem_info.rx_buff_size;
}
/**
* @brief Get the free space in the RX buffer.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Free space in the RX buffer, in multiple of 32-bit words.
*/
static inline uint32_t twaifd_ll_get_rx_free_space(twaifd_dev_t *hw)
{
return hw->rx_mem_info.rx_free;
}
/**
* @brief Get the number of frames in the RX buffer.
*
@@ -693,15 +770,26 @@ static inline uint32_t twaifd_ll_get_rx_frame_count(twaifd_dev_t *hw)
* @brief Check if the RX FIFO is empty.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return 1 if RX FIFO is empty, 0 otherwise.
* @return true if RX FIFO is empty, false otherwise.
*/
static inline uint32_t twaifd_ll_is_rx_buffer_empty(twaifd_dev_t *hw)
static inline bool twaifd_ll_is_rx_buffer_empty(twaifd_dev_t *hw)
{
return hw->rx_status_rx_settings.rxe;
}
/**
* @brief Copy a received frame from the RX buffer for parsing
* @brief Check if the RX FIFO is full.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return true if RX FIFO is full, false otherwise.
*/
static inline bool twaifd_ll_is_rx_buffer_full(twaifd_dev_t *hw)
{
return hw->rx_status_rx_settings.rxf;
}
/**
* @brief Copy a received frame from the RX buffer for parsing
*
* @param hw Start address of the TWAI registers
* @param rx_frame Pointer to store formatted frame
@@ -839,18 +927,29 @@ static inline uint32_t twaifd_ll_get_tx_traffic_counter(twaifd_dev_t *hw)
/* ------------------------- Timestamp Register ------------------------- */
/**
* @brief Enable or disable the timer clock.
* @brief Set the sample point for the timestamp.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param sample_point Sample point for the timestamp.
*/
static inline void twaifd_ll_ts_set_sample_point(twaifd_dev_t *hw, twaifd_ll_timestamp_point_t sample_point)
{
hw->rx_status_rx_settings.rtsop = sample_point;
}
/**
* @brief Whether to force enable the register config clock of the timer
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable True to enable, false to disable.
*/
static inline void twaifd_ll_timer_enable_clock(twaifd_dev_t *hw, bool enable)
static inline void twaifd_ll_timer_force_enable_cfg_clock(twaifd_dev_t *hw, bool enable)
{
hw->timer_clk_en.clk_en = enable;
}
/**
* @brief Enable or disable timer power.
* @brief Enable or disable the timer.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param enable True to enable, false to disable.
@@ -860,9 +959,34 @@ static inline void twaifd_ll_timer_enable(twaifd_dev_t *hw, bool enable)
hw->timer_cfg.timer_ce = enable;
}
/**
* @brief Get the bit width of the timer.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Bit width of the timer.
*/
static inline uint8_t twaifd_ll_timer_get_bitwidth(twaifd_dev_t *hw)
{
return hw->err_capt_retr_ctr_alc_ts_info.ts_bits + 1;
}
/**
* @brief Get the current timer count.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @return Current timer count as a 64-bit value.
*/
static inline uint64_t twaifd_ll_timer_get_count(twaifd_dev_t *hw)
{
uint64_t count = ((uint64_t)hw->timestamp_high.val << 32) | hw->timestamp_low.val;
return count;
}
/**
* @brief Set the timer step value.
*
* @note This is to determine the resolution of the timer. We can also treat it as a prescaler.
*
* @param hw Pointer to the TWAI-FD device hardware.
* @param step Step value to set (actual step = step - 1).
*/
@@ -4,8 +4,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,11 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/twai_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI0) : (controller_id == 1) ? (&TWAI1) : (&TWAI2))
#ifdef __cplusplus
@@ -4,11 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[3] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI0_INTR_SOURCE,
@@ -72,7 +73,7 @@ static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTI
static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1);
static const regdma_entries_config_t twai2_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(2);
const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = {
const twai_reg_retention_info_t twai_reg_retention_info[3] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,10 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/system_reg.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_SUPPORT_APB_CLK 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send
@@ -513,9 +510,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->error_code_capture_reg.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -683,7 +680,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;
@@ -4,10 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI_INTR_SOURCE,
@@ -4,14 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
#pragma once
#include <stdint.h>
@@ -21,10 +13,15 @@
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/twai_struct.h"
#include "soc/system_struct.h"
#define TWAI_LL_GET(_attr) TWAI_LL_ ## _attr
#define TWAI_LL_SUPPORT(_feat) TWAI_LL_SUPPORT_ ## _feat
#define TWAI_LL_SUPPORT_RX_STATUS 1
#define TWAI_LL_SUPPORT_APB_CLK 1
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send
@@ -510,9 +507,9 @@ __attribute__((always_inline))
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)
{
uint32_t ecc = hw->error_code_capture_reg.val;
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
*type = (twai_ll_err_type_t)((ecc >> 6) & 0x3);
*dir = (twai_ll_err_dir_t)((ecc >> 5) & 0x1);
*seg = (twai_ll_err_seg_t)(ecc & 0x1F);
}
/* ----------------------------- EWL Register ------------------------------- */
@@ -680,7 +677,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;
@@ -4,10 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "hal/twai_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/interrupts.h"
const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = {
const twai_signal_conn_t twai_periph_signals[1] = {
[0] = {
.module_name = "TWAI0",
.irq_id = ETS_TWAI_INTR_SOURCE,
@@ -4,11 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
******************************************************************************/
#pragma once
#include <stddef.h>
@@ -16,23 +11,22 @@
#include "soc/soc_caps.h"
#include "hal/twai_types.h"
#if SOC_TWAI_SUPPORTED
#if SOC_TWAI_SUPPORT_FD
typedef struct twaifd_dev_t *twai_soc_handle_t;
typedef union twaifd_frame_buffer_t twai_hal_frame_t;
#else
typedef struct twai_dev_t *twai_soc_handle_t;
typedef union twai_ll_frame_buffer_t twai_hal_frame_t;
#endif
typedef struct twai_hal_errata_ctx_t twai_hal_errata_ctx_t;
#ifdef __cplusplus
extern "C" {
#endif
/* ------------------------- Defines and Typedefs --------------------------- */
typedef struct twai_hal_errata_ctx_t twai_hal_errata_ctx_t;
#if SOC_HAS(TWAI_FD)
typedef struct twaifd_dev_t *twai_soc_handle_t;
typedef union twaifd_frame_buffer_t twai_hal_frame_t;
#else
typedef struct twai_dev_t *twai_soc_handle_t;
typedef union twai_ll_frame_buffer_t twai_hal_frame_t;
#endif // SOC_HAS(TWAI_FD)
#define TWAI_HAL_SET_BITS(var, flag) ((var) |= (flag))
#define TWAI_HAL_CLEAR_BITS(var, flag) ((var) &= ~(flag))
@@ -156,7 +150,7 @@ void twai_hal_configure_timing_fd(twai_hal_context_t *hal_ctx, const twai_timing
* @param filter_id Which filter to be configured
* @param f_config Pointer to filter configuration structure
*/
void twai_hal_configure_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_mask_filter_config_t *f_config);
void twai_hal_configure_mask_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_mask_filter_config_t *f_config);
/**
* @brief Configure the TWAI range filter
@@ -350,7 +344,6 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f
*/
bool twai_hal_read_rx_fifo(twai_hal_context_t *hal_ctx, twai_hal_frame_t *rx_frame);
#ifndef SOC_TWAI_SUPPORTS_RX_STATUS
/**
* @brief Clear the RX FIFO of overrun frames
*
@@ -361,7 +354,6 @@ bool twai_hal_read_rx_fifo(twai_hal_context_t *hal_ctx, twai_hal_frame_t *rx_fra
* @return Number of overrun messages cleared from RX FIFO
*/
uint32_t twai_hal_clear_rx_fifo_overrun(twai_hal_context_t *hal_ctx);
#endif //SOC_TWAI_SUPPORTS_RX_STATUS
/* --------------------------- Errata Workarounds --------------------------- */
@@ -428,4 +420,3 @@ uint32_t twai_hal_get_reset_lost_rx_cnt(twai_hal_context_t *hal_ctx);
#ifdef __cplusplus
}
#endif
#endif // SOC_TWAI_SUPPORTED
@@ -8,23 +8,25 @@
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#if SOC_PAU_SUPPORTED
#include "soc/regdma.h"
#if SOC_HAS(PAU)
#include "soc/retention_periph_defs.h"
#endif
#if SOC_HAS(TWAI)
#include "hal/twai_ll.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_TWAI_SUPPORTED
#if SOC_HAS(TWAI)
typedef struct {
const char *module_name; // peripheral name
const int irq_id; // interrupt source ID
#if SOC_TWAI_SUPPORT_TIMESTAMP
const int timer_irq_id;
#if TWAI_LL_SUPPORT(TIMESTAMP)
const int timer_irq_id; // time base interrupt source ID
#endif
const int tx_sig; // TX signal ID in GPIO matrix
const int rx_sig; // RX signal ID in GPIO matrix
@@ -35,7 +37,7 @@ typedef struct {
extern const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM];
#if SOC_PAU_SUPPORTED
#if SOC_HAS(PAU)
typedef struct {
const periph_retention_module_t module_id;
const regdma_entries_config_t *entry_array;
@@ -43,9 +45,9 @@ typedef struct {
} twai_reg_retention_info_t;
extern const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM];
#endif // SOC_PAU_SUPPORTED
#endif // SOC_HAS(PAU)
#endif // SOC_TWAI_SUPPORTED
#endif // SOC_HAS(TWAI)
#ifdef __cplusplus
}
@@ -88,7 +88,7 @@ typedef twai_timing_config_t twai_timing_advanced_config_t;
* @brief Configuration for TWAI mask filter
*/
typedef struct {
union{
union {
uint32_t id; /**< Single base ID for filtering */
struct {
uint32_t *id_list; /**< Base ID list array for filtering, which share the same `mask` */
@@ -108,8 +108,8 @@ typedef struct {
* @brief Range-based filter configuration structure
*/
typedef struct {
uint32_t range_low; /**< Lower bound of the filtering range */
uint32_t range_high; /**< Upper bound of the filtering range */
uint32_t range_low; /**< Lower bound of the ID filtering range, included */
uint32_t range_high; /**< Upper bound of the ID filtering range, included */
struct {
uint32_t is_ext: 1; /**< True for extended ID filtering, false for standard ID */
uint32_t no_classic: 1; /**< If true, Classic TWAI frames are excluded (only TWAI FD allowed) */
@@ -142,7 +142,8 @@ typedef struct {
* @return The byte length of DLC stand for
*/
__attribute__((always_inline))
static inline uint16_t twaifd_dlc2len(uint16_t dlc) {
static inline uint16_t twaifd_dlc2len(uint16_t dlc)
{
HAL_ASSERT(dlc <= TWAIFD_FRAME_MAX_DLC);
return (dlc <= 8) ? dlc :
(dlc <= 12) ? (dlc - 8) * 4 + 8 :
@@ -156,7 +157,8 @@ static inline uint16_t twaifd_dlc2len(uint16_t dlc) {
* @return The FD adopted frame DLC code
*/
__attribute__((always_inline))
static inline uint16_t twaifd_len2dlc(uint16_t byte_len) {
static inline uint16_t twaifd_len2dlc(uint16_t byte_len)
{
HAL_ASSERT(byte_len <= TWAIFD_FRAME_MAX_LEN);
return (byte_len <= 8) ? byte_len :
(byte_len <= 24) ? (byte_len - 8 + 3) / 4 + 8 :
@@ -39,9 +39,6 @@ extern "C" {
#define TWAI_MSG_FLAG_SELF 0x08 /**< Transmit as a Self Reception Request. Unused for received. */
#define TWAI_MSG_FLAG_DLC_NON_COMP 0x10 /**< Message's Data length code is larger than 8. This will break compliance with TWAI */
#define TWAI_BRP_MAX SOC_TWAI_BRP_MAX /**< Maximum configurable BRP value */
#define TWAI_BRP_MIN SOC_TWAI_BRP_MIN /**< Minimum configurable BRP value */
/**
* @brief Initializer macros for timing configuration structure
*
@@ -50,32 +47,32 @@ extern "C" {
*
* @note The available bit rates are dependent on the chip target and ECO version.
*/
#if SOC_TWAI_BRP_MAX > 256
#define TWAI_TIMING_CONFIG_1KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_5KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 100000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_10KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 200000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#endif // SOC_TWAI_BRP_MAX > 256
#if (SOC_TWAI_BRP_MAX > 128) || (SOC_IS(ESP32) && (HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 200))
#define TWAI_TIMING_CONFIG_12_5KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 312500, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_16KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 400000, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_20KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 400000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#if SOC_IS(ESP32) || SOC_IS(ESP32S2) || SOC_IS(ESP32C3) || SOC_IS(ESP32S3)
// default clock source is APB=80MHz
#define TWAI_TIMING_CONFIG_25KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 625000, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#else
#define TWAI_TIMING_CONFIG_25KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 500000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#endif
#if SOC_TWAI_CLK_SUPPORT_XTAL
#define TWAI_TIMING_CONFIG_25KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 500000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#else // APB80M
#define TWAI_TIMING_CONFIG_25KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 625000, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#endif
#define TWAI_TIMING_CONFIG_50KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 1000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_100KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 2000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_125KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 2000000, .brp = 0, .prop_seg = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_250KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 4000000, .brp = 0, .prop_seg = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 2, .ssp_offset = 0, .triple_sampling = false}
#if SOC_TWAI_CLK_SUPPORT_XTAL && HAL_CONFIG(XTAL_HINT_FREQ_MHZ) == 40 // TWAI_CLK_SRC_XTAL = 40M
#if SOC_IS(ESP32C6) || SOC_IS(ESP32P4)
// default clock source is XTAL=40MHz
#define TWAI_TIMING_CONFIG_500KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 10000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_800KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000000, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_1MBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false}
#else // 32M, 48M, APB80M
#else
#define TWAI_TIMING_CONFIG_500KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 8000000, .brp = 0, .prop_seg = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 2, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_800KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 8000000, .brp = 0, .prop_seg = 0, .tseg_1 = 6, .tseg_2 = 3, .sjw = 1, .ssp_offset = 0, .triple_sampling = false}
#define TWAI_TIMING_CONFIG_1MBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 8000000, .brp = 0, .prop_seg = 0, .tseg_1 = 5, .tseg_2 = 2, .sjw = 1, .ssp_offset = 0, .triple_sampling = false}
@@ -25,7 +25,8 @@ typedef struct twai_hal_errata_ctx_t {
} twai_hal_errata_ctx_t;
#endif
size_t twai_hal_get_mem_requirment(void) {
size_t twai_hal_get_mem_requirment(void)
{
#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE
return sizeof(twai_hal_context_t) + sizeof(twai_hal_errata_ctx_t);
#else
@@ -52,7 +53,7 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config)
#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE
hal_ctx->errata_ctx = (twai_hal_errata_ctx_t *)(hal_ctx + 1); //errata context is place at end of hal_ctx
#endif
#if SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT
#if TWAI_LL_SUPPORT(MULTI_ADDRESS_LAYOUT)
twai_ll_enable_extended_reg_layout(hal_ctx->dev); //Changes the address layout of the registers
#endif
twai_ll_set_mode(hal_ctx->dev, true, false, false); //Freeze REC by changing to LOM mode
@@ -108,7 +109,7 @@ void twai_hal_configure_timing(twai_hal_context_t *hal_ctx, const twai_timing_ad
twai_ll_set_clkout(hal_ctx->dev, brp);
}
void twai_hal_configure_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_mask_filter_config_t *f_config)
void twai_hal_configure_mask_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_mask_filter_config_t *f_config)
{
uint32_t id = f_config->num_of_ids ? f_config->id_list[0] : f_config->id;
bool full_open = (f_config->mask == 0) && (id == 0);
@@ -292,8 +293,8 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
#if TWAI_LL_HAS_RX_FRAME_ISSUE
//Check for errata condition (RX message has bus error at particular segments)
if (dir == TWAI_LL_ERR_DIR_RX &&
((seg == TWAI_LL_ERR_SEG_DATA || seg == TWAI_LL_ERR_SEG_CRC_SEQ) ||
(seg == TWAI_LL_ERR_SEG_ACK_DELIM && type == TWAI_LL_ERR_OTHER))) {
((seg == TWAI_LL_ERR_SEG_DATA || seg == TWAI_LL_ERR_SEG_CRC_SEQ) ||
(seg == TWAI_LL_ERR_SEG_ACK_DELIM && type == TWAI_LL_ERR_OTHER))) {
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_NEED_PERIPH_RESET);
HAL_LOGD("TWAI_HAL", "RX frame invalid detected");
}
@@ -401,7 +402,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f
} else {
twai_ll_set_cmd_self_rx_request(hal_ctx->dev);
}
} else if (tx_frame->single_shot){
} else if (tx_frame->single_shot) {
twai_ll_set_cmd_tx_single_shot(hal_ctx->dev);
} else {
twai_ll_set_cmd_tx(hal_ctx->dev);
@@ -425,7 +426,7 @@ uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx)
bool twai_hal_read_rx_fifo(twai_hal_context_t *hal_ctx, twai_hal_frame_t *rx_frame)
{
#ifdef SOC_TWAI_SUPPORTS_RX_STATUS
#if TWAI_LL_SUPPORT(RX_STATUS)
if (twai_ll_get_status(hal_ctx->dev) & TWAI_LL_STATUS_MS) {
//Release the buffer for this particular overrun frame
twai_ll_set_cmd_release_rx_buffer(hal_ctx->dev);
@@ -8,7 +8,8 @@
#include "hal/twai_hal.h"
#include "hal/twaifd_ll.h"
size_t twai_hal_get_mem_requirment(void) {
size_t twai_hal_get_mem_requirment(void)
{
return sizeof(twai_hal_context_t);
}
@@ -24,10 +25,12 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config)
twaifd_ll_enable_hw(hal_ctx->dev, false); //mode should be changed under disabled
twaifd_ll_set_mode(hal_ctx->dev, config->enable_listen_only, config->enable_self_test, config->enable_loopback);
twaifd_ll_set_tx_retrans_limit(hal_ctx->dev, config->retry_cnt);
twaifd_ll_filter_block_rtr(hal_ctx->dev, config->no_receive_rtr);
twaifd_ll_filter_drop_rtr(hal_ctx->dev, config->no_receive_rtr);
twaifd_ll_enable_filter_mode(hal_ctx->dev, true); // each filter still has independent enable control
twaifd_ll_enable_fd_mode(hal_ctx->dev, true); // fd frame still controlled by `header.fdf`
twaifd_ll_enable_rxfifo_auto_incrase(hal_ctx->dev, true);
twaifd_ll_enable_bus_off_tx_fail_mode(hal_ctx->dev, true); // all buffers go to "TX failed" state upon bus-off
twaifd_ll_enable_rxfifo_auto_increase(hal_ctx->dev, true);
twaifd_ll_ts_set_sample_point(hal_ctx->dev, TWAIFD_LL_TS_POINT_EOF);
twaifd_ll_enable_intr(hal_ctx->dev, config->intr_mask);
return true;
}
@@ -63,7 +66,7 @@ void twai_hal_configure_timing_fd(twai_hal_context_t *hal_ctx, const twai_timing
}
}
void twai_hal_configure_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_mask_filter_config_t *f_config)
void twai_hal_configure_mask_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_mask_filter_config_t *f_config)
{
uint32_t id = f_config->num_of_ids ? f_config->id_list[0] : f_config->id;
bool full_open = (f_config->mask == 0) && (id == 0);
@@ -72,11 +75,11 @@ void twai_hal_configure_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, c
bool fd_ext = full_open || (!full_close && f_config->is_ext && !f_config->no_fd);
bool cc_std = full_open || (!full_close && !f_config->is_ext && !f_config->no_classic);
bool fd_std = full_open || (!full_close && !f_config->is_ext && !f_config->no_fd);
twaifd_ll_filter_enable_basic_ext(hal_ctx->dev, filter_id, false, cc_ext);
twaifd_ll_filter_enable_fd_ext(hal_ctx->dev, filter_id, false, fd_ext);
twaifd_ll_filter_enable_basic_std(hal_ctx->dev, filter_id, false, cc_std);
twaifd_ll_filter_enable_fd_std(hal_ctx->dev, filter_id, false, fd_std);
twaifd_ll_filter_set_id_mask(hal_ctx->dev, filter_id, f_config->is_ext, id, f_config->mask);
twaifd_ll_mask_filter_accept_classic_std(hal_ctx->dev, filter_id, cc_std);
twaifd_ll_mask_filter_accept_classic_ext(hal_ctx->dev, filter_id, cc_ext);
twaifd_ll_mask_filter_accept_fd_std(hal_ctx->dev, filter_id, fd_std);
twaifd_ll_mask_filter_accept_fd_ext(hal_ctx->dev, filter_id, fd_ext);
twaifd_ll_mask_filter_set_id_mask(hal_ctx->dev, filter_id, f_config->is_ext, id, f_config->mask);
}
void twai_hal_configure_range_filter(twai_hal_context_t *hal_ctx, uint8_t filter_id, const twai_range_filter_config_t *f_config)
@@ -85,11 +88,11 @@ void twai_hal_configure_range_filter(twai_hal_context_t *hal_ctx, uint8_t filter
bool fd_ext = f_config->is_ext && !f_config->no_fd;
bool cc_std = !f_config->is_ext && !f_config->no_classic;
bool fd_std = !f_config->is_ext && !f_config->no_fd;
twaifd_ll_filter_enable_basic_ext(hal_ctx->dev, filter_id, true, cc_ext);
twaifd_ll_filter_enable_fd_ext(hal_ctx->dev, filter_id, true, fd_ext);
twaifd_ll_filter_enable_basic_std(hal_ctx->dev, filter_id, true, cc_std);
twaifd_ll_filter_enable_fd_std(hal_ctx->dev, filter_id, true, fd_std);
twaifd_ll_filter_set_range(hal_ctx->dev, 0, f_config->is_ext, f_config->range_high, f_config->range_low);
twaifd_ll_range_filter_accept_classic_std(hal_ctx->dev, filter_id, cc_std);
twaifd_ll_range_filter_accept_classic_ext(hal_ctx->dev, filter_id, cc_ext);
twaifd_ll_range_filter_accept_fd_std(hal_ctx->dev, filter_id, fd_std);
twaifd_ll_range_filter_accept_fd_ext(hal_ctx->dev, filter_id, fd_ext);
twaifd_ll_range_filter_set_id_thres(hal_ctx->dev, 0, f_config->is_ext, f_config->range_high, f_config->range_low);
}
void twai_hal_start(twai_hal_context_t *hal_ctx)
@@ -152,7 +155,7 @@ void twai_hal_parse_frame(const twai_hal_frame_t *frame, twai_frame_header_t *he
void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_frame_t *tx_frame, uint8_t buffer_idx)
{
twaifd_ll_mount_tx_buffer(hal_ctx->dev, tx_frame, buffer_idx);
twaifd_ll_set_tx_cmd(hal_ctx->dev, buffer_idx, TWAIFD_LL_TX_CMD_READY);
twaifd_ll_set_tx_buffer_cmd(hal_ctx->dev, buffer_idx, TWAIFD_LL_TX_CMD_READY);
}
uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx)
@@ -176,7 +179,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
if (int_stat & (TWAIFD_LL_INTR_TX_DONE)) {
hal_events |= TWAI_HAL_EVENT_TX_BUFF_FREE;
if (int_stat & TWAIFD_LL_INTR_TX_SUCCESS) {
if (int_stat & TWAIFD_LL_INTR_TX_FRAME) {
hal_events |= TWAI_HAL_EVENT_TX_SUCCESS;
}
}
@@ -187,7 +190,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
hal_ctx->errors = twaifd_ll_get_err_reason(hal_ctx->dev);
hal_events |= TWAI_HAL_EVENT_BUS_ERR;
}
if (int_stat & TWAIFD_LL_INTR_ARBI_LOST) {
if (int_stat & TWAIFD_LL_INTR_ARBIT_LOST) {
hal_events |= TWAI_HAL_EVENT_ARB_LOST;
}
if (int_stat & (TWAIFD_LL_INTR_FSM_CHANGE | TWAIFD_LL_INTR_ERR_WARN)) {
+1
View File
@@ -84,6 +84,7 @@ else()
esp_hal_mcpwm
esp_hal_pcnt
esp_hal_cam
esp_hal_twai
LDFRAGMENTS "linker.lf" "app.lf")
add_subdirectory(port)
+5 -5
View File
@@ -55,7 +55,7 @@
#include "hal/spi_ll.h"
#include "hal/temperature_sensor_ll.h"
#include "hal/timer_ll.h"
#include "hal/twaifd_ll.h"
#include "hal/twai_ll.h"
#include "hal/uart_ll.h"
#include "hal/uhci_ll.h"
#include "hal/usb_serial_jtag_ll.h"
@@ -290,10 +290,10 @@ __attribute__((weak)) void esp_perip_clk_init(void)
timer_ll_enable_clock(1, 0, false);
_timg_ll_enable_bus_clock(0, false);
_timg_ll_enable_bus_clock(1, false);
twaifd_ll_enable_clock(0, false);
twaifd_ll_enable_bus_clock(0, false);
twaifd_ll_enable_clock(1, false);
twaifd_ll_enable_bus_clock(1, false);
twai_ll_enable_clock(0, false);
twai_ll_enable_bus_clock(0, false);
twai_ll_enable_clock(1, false);
twai_ll_enable_bus_clock(1, false);
i2s_ll_enable_bus_clock(0, false);
i2s_ll_tx_disable_clock(&I2S0);
i2s_ll_rx_disable_clock(&I2S0);
-8
View File
@@ -107,14 +107,6 @@ elseif(NOT BOOTLOADER_BUILD)
list(APPEND srcs "uhci_hal.c")
endif()
if(CONFIG_SOC_TWAI_SUPPORTED)
if(CONFIG_SOC_TWAI_SUPPORT_FD)
list(APPEND srcs "twai_hal_v2.c")
else()
list(APPEND srcs "twai_hal_v1.c")
endif()
endif()
if(CONFIG_SOC_I2S_SUPPORTED)
list(APPEND srcs "i2s_hal.c")
endif()
-4
View File
@@ -124,10 +124,6 @@ if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
list(APPEND srcs "${target_folder}/touch_sensor_periph.c")
endif()
if(CONFIG_SOC_TWAI_SUPPORTED)
list(APPEND srcs "${target_folder}/twai_periph.c")
endif()
if(CONFIG_SOC_IEEE802154_SUPPORTED)
if(NOT target STREQUAL "esp32h4")
list(APPEND srcs "${target_folder}/ieee802154_periph.c")
@@ -611,18 +611,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_CLK_SUPPORT_APB
bool
default y
config SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT
bool
default y
config SOC_UART_NUM
int
default 3
@@ -296,14 +296,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_BRP_MIN 2
#if SOC_CAPS_ECO_VER >= 200
# define SOC_TWAI_BRP_MAX 256
#else
# define SOC_TWAI_BRP_MAX 128
#endif
#define SOC_TWAI_CLK_SUPPORT_APB 1
#define SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT 1
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32 have 3 UART.
@@ -831,22 +831,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_APB
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 16384
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_EFUSE_DIS_DOWNLOAD_ICACHE
bool
default y
@@ -360,10 +360,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_APB 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 16384
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 1
@@ -47,6 +47,10 @@ config SOC_TWAI_SUPPORTED
bool
default y
config SOC_TWAI_FD_SUPPORTED
bool
default y
config SOC_ETM_SUPPORTED
bool
default y
@@ -1227,30 +1231,6 @@ config SOC_TWAI_RANGE_FILTER_NUM
int
default 1
config SOC_TWAI_BRP_MIN
int
default 1
config SOC_TWAI_BRP_MAX
int
default 255
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
default y
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_FD
bool
default y
config SOC_TWAI_SUPPORT_TIMESTAMP
bool
default y
config SOC_EFUSE_DIS_PAD_JTAG
bool
default y
@@ -34,6 +34,7 @@
#define SOC_PCNT_SUPPORTED 1
#define SOC_MCPWM_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
#define SOC_TWAI_FD_SUPPORTED 1
#define SOC_ETM_SUPPORTED 1
#define SOC_PARLIO_SUPPORTED 1
#define SOC_PARLIO_LCD_SUPPORTED 1
@@ -493,12 +494,6 @@
#define SOC_TWAI_CONTROLLER_NUM 2
#define SOC_TWAI_MASK_FILTER_NUM 3
#define SOC_TWAI_RANGE_FILTER_NUM 1U
#define SOC_TWAI_BRP_MIN 1U
#define SOC_TWAI_BRP_MAX 255
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_FD 1
#define SOC_TWAI_SUPPORT_TIMESTAMP 1
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_PAD_JTAG 1
@@ -1754,7 +1754,7 @@ typedef union twaifd_frame_buffer_t {
struct {
uint32_t dlc: 4; // Data length code (0-15)
uint32_t reserved4: 1; // Reserved bit
uint32_t rtr: 1; // Remote transmission request
uint32_t rtr: 1; // Remote transmission request. Note there are no remote frames in CAN FD protocol
uint32_t ide: 1; // Identifier extension bit
uint32_t fdf: 1; // Flexible data-rate format bit
uint32_t reserved8: 1; // Reserved bit
@@ -1824,7 +1824,7 @@ typedef struct twaifd_dev_t {
volatile twaifd_timestamp_low_reg_t timestamp_low;
volatile twaifd_timestamp_high_reg_t timestamp_high;
uint32_t reserved_09c[25];
volatile twaifd_frame_mem_t txt_mem_cell[8];
volatile twaifd_frame_mem_t txt_mem_cell[8]; // only 4 are actively used
uint32_t reserved_900[437];
volatile twaifd_timer_clk_en_reg_t timer_clk_en;
volatile twaifd_timer_int_raw_reg_t timer_int_raw;
@@ -1067,22 +1067,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 32768
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
@@ -438,10 +438,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 2
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
@@ -1079,22 +1079,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 32768
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
@@ -454,10 +454,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
@@ -775,22 +775,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 32768
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
@@ -435,10 +435,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
@@ -35,6 +35,10 @@ config SOC_TWAI_SUPPORTED
bool
default y
config SOC_TWAI_FD_SUPPORTED
bool
default y
config SOC_ETM_SUPPORTED
bool
default y
@@ -779,30 +783,6 @@ config SOC_TWAI_RANGE_FILTER_NUM
int
default 1
config SOC_TWAI_BRP_MIN
int
default 1
config SOC_TWAI_BRP_MAX
int
default 255
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
default y
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_FD
bool
default y
config SOC_TWAI_SUPPORT_TIMESTAMP
bool
default y
config SOC_EFUSE_DIS_DOWNLOAD_ICACHE
bool
default n
@@ -41,6 +41,7 @@
#define SOC_PCNT_SUPPORTED 1
#define SOC_MCPWM_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
#define SOC_TWAI_FD_SUPPORTED 1
#define SOC_ETM_SUPPORTED 1
// #define SOC_PARLIO_SUPPORTED 1 // TODO: [ESP32H4] IDF-12345 IDF-12347
// #define SOC_BT_SUPPORTED 1
@@ -424,12 +425,6 @@
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 3
#define SOC_TWAI_RANGE_FILTER_NUM 1U
#define SOC_TWAI_BRP_MIN 1U
#define SOC_TWAI_BRP_MAX 255
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_FD 1
#define SOC_TWAI_SUPPORT_TIMESTAMP 1
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 0
@@ -1761,7 +1761,7 @@ typedef union twaifd_frame_buffer_t {
struct {
uint32_t dlc: 4; // Data length code (0-15)
uint32_t reserved4: 1; // Reserved bit
uint32_t rtr: 1; // Remote transmission request
uint32_t rtr: 1; // Remote transmission request. Note there are no remote frames in CAN FD protocol
uint32_t ide: 1; // Identifier extension bit
uint32_t fdf: 1; // Flexible data-rate format bit
uint32_t reserved8: 1; // Reserved bit
@@ -1647,22 +1647,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_XTAL
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 32768
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
@@ -625,10 +625,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 3
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
@@ -751,22 +751,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_APB
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 32768
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_UART_NUM
int
default 2
@@ -325,10 +325,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_APB 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-S2 has 2 UART.
@@ -891,22 +891,6 @@ config SOC_TWAI_MASK_FILTER_NUM
int
default 1
config SOC_TWAI_CLK_SUPPORT_APB
bool
default y
config SOC_TWAI_BRP_MIN
int
default 2
config SOC_TWAI_BRP_MAX
int
default 16384
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_UART_NUM
int
default 3
@@ -360,10 +360,6 @@
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1U
#define SOC_TWAI_MASK_FILTER_NUM 1U
#define SOC_TWAI_CLK_SUPPORT_APB 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 16384
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-S3 has 3 UARTs
+1 -1
View File
@@ -171,6 +171,7 @@ INPUT = \
$(PROJECT_PATH)/components/esp_hal_lcd/include/hal/lcd_types.h \
$(PROJECT_PATH)/components/esp_hal_mspi/include/hal/esp_flash_err.h \
$(PROJECT_PATH)/components/esp_hal_mspi/include/hal/spi_flash_types.h \
$(PROJECT_PATH)/components/esp_hal_twai/include/hal/twai_types.h \
$(PROJECT_PATH)/components/esp_http_client/include/esp_http_client.h \
$(PROJECT_PATH)/components/esp_http_server/include/esp_http_server.h \
$(PROJECT_PATH)/components/esp_https_ota/include/esp_https_ota.h \
@@ -267,7 +268,6 @@ INPUT = \
$(PROJECT_PATH)/components/hal/include/hal/sdio_slave_types.h \
$(PROJECT_PATH)/components/hal/include/hal/spi_types.h \
$(PROJECT_PATH)/components/hal/include/hal/temperature_sensor_types.h \
$(PROJECT_PATH)/components/hal/include/hal/twai_types.h \
$(PROJECT_PATH)/components/hal/include/hal/uart_types.h \
$(PROJECT_PATH)/components/hal/include/hal/efuse_hal.h \
$(PROJECT_PATH)/components/hal/include/hal/eth_types.h \
+4 -4
View File
@@ -15,11 +15,11 @@ Overview
TWAI is a highly reliable, multi-master, real-time, serial asynchronous communication protocol designed for automotive and industrial applications. It is compatible with the frame structure defined in the ISO 11898-1 standard and supports both standard frames with 11-bit identifiers and extended frames with 29-bit identifiers. The protocol supports message prioritization with lossless arbitration, automatic retransmission, and fault confinement mechanisms. The {IDF_TARGET_NAME} includes {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} TWAI controllers, allowing for the creation of {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} driver instances.
.. only:: SOC_TWAI_SUPPORT_FD
.. only:: SOC_TWAI_FD_SUPPORTED
The TWAI controllers on the {IDF_TARGET_NAME} also compatible with FD format (a.k.a. CAN FD) frames defined in ISO 11898-1, and can transmit and receive both classic and FD format frames.
.. only:: not SOC_TWAI_SUPPORT_FD
.. only:: not SOC_TWAI_FD_SUPPORTED
The TWAI controllers on the {IDF_TARGET_NAME} are **not compatible with FD format frames and will interpret such frames as errors.**
@@ -277,7 +277,7 @@ The following code demonstrates how to calculate the MASK and configure a filter
};
ESP_ERROR_CHECK(twai_node_config_mask_filter(node_hdl, 0, &mfilter_cfg)); // Configure on filter 0
.. only:: not SOC_TWAI_SUPPORT_FD
.. only:: not SOC_TWAI_FD_SUPPORTED
Dual Filter Mode
^^^^^^^^^^^^^^^^
@@ -291,7 +291,7 @@ The following code demonstrates how to calculate the MASK and configure a filter
twai_mask_filter_config_t dual_config = twai_make_dual_filter(0x020, 0x7f0, 0x013, 0x7f8, false); // id1, mask1, id2, mask2, no extend ID
ESP_ERROR_CHECK(twai_node_config_mask_filter(node_hdl, 0, &dual_config));
.. only:: SOC_TWAI_SUPPORT_FD
.. only:: SOC_TWAI_FD_SUPPORTED
Range Filter
^^^^^^^^^^^^
@@ -15,11 +15,11 @@
TWAI 是一种适用于汽车和工业应用的高可靠性的多主机实时串行异步通信协议。它兼容 ISO11898-1 标准定义的帧结构,可以支持 11 位 ID 的标准帧和 29 位 ID 的扩展帧。支持报文优先级和无损仲裁,支持自动重传和故障自动隔离机制。{IDF_TARGET_NAME} 包含 {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} 个 TWAI 控制器,可以创建 {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} 个驱动实例。
.. only:: SOC_TWAI_SUPPORT_FD
.. only:: SOC_TWAI_FD_SUPPORTED
{IDF_TARGET_NAME} TWAI 控制器兼容 ISO11898-1 FD (a.k.a. CAN FD) 格式帧,可以发送和接收经典格式和 FD 格式帧。
.. only:: not SOC_TWAI_SUPPORT_FD
.. only:: not SOC_TWAI_FD_SUPPORTED
{IDF_TARGET_NAME} TWAI 控制器 **不兼容 ISO11898-1 FD 格式帧,并会将这些帧解析为错误。**
@@ -277,7 +277,7 @@ TWAI 控制器硬件可以根据 ID 对报文进行过滤,从而减少软硬
};
ESP_ERROR_CHECK(twai_node_config_mask_filter(node_hdl, 0, &mfilter_cfg)); //配置过滤器0
.. only:: not SOC_TWAI_SUPPORT_FD
.. only:: not SOC_TWAI_FD_SUPPORTED
双过滤器模式
^^^^^^^^^^^^
@@ -291,7 +291,7 @@ TWAI 控制器硬件可以根据 ID 对报文进行过滤,从而减少软硬
twai_mask_filter_config_t dual_config = twai_make_dual_filter(0x020, 0x7f0, 0x013, 0x7f8, false); // id1, mask1, id2, mask2, 不接收扩展ID
ESP_ERROR_CHECK(twai_node_config_mask_filter(node_hdl, 0, &dual_config));
.. only:: SOC_TWAI_SUPPORT_FD
.. only:: SOC_TWAI_FD_SUPPORTED
范围过滤器
^^^^^^^^^^
@@ -5,7 +5,7 @@ menu "TWAI Configuration"
config EXAMPLE_ENABLE_TWAI_FD
bool "Enable TWAI-FD Support"
depends on SOC_TWAI_SUPPORT_FD
depends on SOC_TWAI_FD_SUPPORTED
default false
help
Enable TWAI-FD (Flexible Data-rate) support.
@@ -388,8 +388,6 @@ static int twai_dump_handler(int argc, char **argv)
ret = twai_node_disable(controller->node_handle);
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to disable TWAI node%d for filter configuration: %s", controller_id, esp_err_to_name(ret));
ret = (SOC_TWAI_MASK_FILTER_NUM > 0) ? ESP_OK : ESP_ERR_INVALID_STATE;
ESP_RETURN_ON_ERROR(ret, TAG, "TWAI%d does not support %d mask filters", controller_id, SOC_TWAI_MASK_FILTER_NUM);
if (mask_count > 0) {
for (int i = 0; i < mask_count; i++) {
ret = twai_node_config_mask_filter(controller->node_handle, i,
@@ -477,7 +477,7 @@ def test_twai_utils_send_various_frames(twai: TwaiTestHelper) -> None:
@pytest.mark.generic
@idf_parametrize('target', soc_filtered_targets('SOC_TWAI_SUPPORT_FD == 1'), indirect=['target'])
@idf_parametrize('target', soc_filtered_targets('SOC_TWAI_FD_SUPPORTED == 1'), indirect=['target'])
def test_twai_utils_fd_frames(twai: TwaiTestHelper) -> None:
with twai.session():
FD_FRAMES = [