diff --git a/components/driver/test_apps/legacy_twai/README.md b/components/driver/test_apps/legacy_twai/README.md index bf6a3f380d..5edaa3c4ca 100644 --- a/components/driver/test_apps/legacy_twai/README.md +++ b/components/driver/test_apps/legacy_twai/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # Enable Socket CAN Device with bitrate 250Kbps diff --git a/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c b/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c index 324114b1f4..c4d4fa2de7 100644 --- a/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c +++ b/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c @@ -134,6 +134,7 @@ TEST_CASE("twai_mode_ext_no_ack_250kbps", "[twai-loop-back]") } } +#if SOC_LIGHT_SLEEP_SUPPORTED static void s_test_sleep_retention(bool allow_pd) { // Prepare a TOP PD sleep @@ -220,3 +221,4 @@ TEST_CASE("twai_mode_ext_no_ack_250kbps with sleep retention (no pd)", "[twai-lo { s_test_sleep_retention(false); } +#endif // SOC_LIGHT_SLEEP_SUPPORTED diff --git a/components/esp_driver_twai/test_apps/test_twai/README.md b/components/esp_driver_twai/test_apps/test_twai/README.md index 46d16c788c..f921835020 100644 --- a/components/esp_driver_twai/test_apps/test_twai/README.md +++ b/components/esp_driver_twai/test_apps/test_twai/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | diff --git a/components/hal/esp32h2/include/hal/twai_ll.h b/components/hal/esp32h2/include/hal/twai_ll.h index b37d630f11..7e40b972d2 100644 --- a/components/hal/esp32h2/include/hal/twai_ll.h +++ b/components/hal/esp32h2/include/hal/twai_ll.h @@ -190,7 +190,7 @@ static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t cl { (void)group_id; switch (clk_src) { - case TWAI_CLK_SRC_DEFAULT: + case TWAI_CLK_SRC_XTAL: PCR.twai0_func_clk_conf.twai0_func_clk_sel = 0; break; default: diff --git a/components/hal/esp32h21/include/hal/twai_ll.h b/components/hal/esp32h21/include/hal/twai_ll.h new file mode 100644 index 0000000000..5bf5ed818f --- /dev/null +++ b/components/hal/esp32h21/include/hal/twai_ll.h @@ -0,0 +1,808 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * 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 +#include +#include +#include "esp_assert.h" +#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_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL) + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------- Defines and Typedefs --------------------------- */ +#define TWAI_LL_BRP_MIN 2 +#define TWAI_LL_BRP_MAX 32768 +#define TWAI_LL_TSEG1_MIN 1 +#define TWAI_LL_TSEG2_MIN 1 +#define TWAI_LL_TSEG1_MAX (TWAI_TIME_SEGMENT1 + 1) +#define TWAI_LL_TSEG2_MAX (TWAI_TIME_SEGMENT2 + 1) +#define TWAI_LL_SJW_MAX (TWAI_SYNC_JUMP_WIDTH + 1) + +#define TWAI_LL_STATUS_RBS (0x1 << 0) //Receive Buffer Status +#define TWAI_LL_STATUS_DOS (0x1 << 1) //Data Overrun Status +#define TWAI_LL_STATUS_TBS (0x1 << 2) //Transmit Buffer Status +#define TWAI_LL_STATUS_TCS (0x1 << 3) //Transmission Complete Status +#define TWAI_LL_STATUS_RS (0x1 << 4) //Receive Status +#define TWAI_LL_STATUS_TS (0x1 << 5) //Transmit Status +#define TWAI_LL_STATUS_ES (0x1 << 6) //Error Status +#define TWAI_LL_STATUS_BS (0x1 << 7) //Bus Status +#define TWAI_LL_STATUS_MS (0x1 << 8) //Miss Status + +#define TWAI_LL_INTR_RI (0x1 << 0) //Receive Interrupt +#define TWAI_LL_INTR_TI (0x1 << 1) //Transmit Interrupt +#define TWAI_LL_INTR_EI (0x1 << 2) //Error Interrupt +//Data overrun interrupt not supported in SW due to HW peculiarities +#define TWAI_LL_INTR_EPI (0x1 << 5) //Error Passive Interrupt +#define TWAI_LL_INTR_ALI (0x1 << 6) //Arbitration Lost Interrupt +#define TWAI_LL_INTR_BEI (0x1 << 7) //Bus Error Interrupt + +#define TWAI_LL_DRIVER_INTERRUPTS (TWAI_LL_INTR_RI | TWAI_LL_INTR_TI | TWAI_LL_INTR_EI | \ + TWAI_LL_INTR_EPI | TWAI_LL_INTR_ALI | TWAI_LL_INTR_BEI) + +typedef enum { + TWAI_LL_ERR_BIT = 0, + TWAI_LL_ERR_FORM, + TWAI_LL_ERR_STUFF, + TWAI_LL_ERR_OTHER, + TWAI_LL_ERR_MAX, +} twai_ll_err_type_t; + +typedef enum { + TWAI_LL_ERR_DIR_TX = 0, + TWAI_LL_ERR_DIR_RX, + TWAI_LL_ERR_DIR_MAX, +} twai_ll_err_dir_t; + +typedef enum { + TWAI_LL_ERR_SEG_SOF = 3, + TWAI_LL_ERR_SEG_ID_28_21 = 2, + TWAI_LL_ERR_SEG_SRTR = 4, + TWAI_LL_ERR_SEG_IDE = 5, + TWAI_LL_ERR_SEG_ID_20_18 = 6, + TWAI_LL_ERR_SEG_ID_17_13 = 7, + TWAI_LL_ERR_SEG_CRC_SEQ = 8, + TWAI_LL_ERR_SEG_R0 = 9, + TWAI_LL_ERR_SEG_DATA = 10, + TWAI_LL_ERR_SEG_DLC = 11, + TWAI_LL_ERR_SEG_RTR = 12, + TWAI_LL_ERR_SEG_R1 = 13, + TWAI_LL_ERR_SEG_ID_4_0 = 14, + TWAI_LL_ERR_SEG_ID_12_5 = 15, + TWAI_LL_ERR_SEG_ACT_FLAG = 17, + TWAI_LL_ERR_SEG_INTER = 18, + TWAI_LL_ERR_SEG_SUPERPOS = 19, + TWAI_LL_ERR_SEG_PASS_FLAG = 22, + TWAI_LL_ERR_SEG_ERR_DELIM = 23, + TWAI_LL_ERR_SEG_CRC_DELIM = 24, + TWAI_LL_ERR_SEG_ACK_SLOT = 25, + TWAI_LL_ERR_SEG_EOF = 26, + TWAI_LL_ERR_SEG_ACK_DELIM = 27, + TWAI_LL_ERR_SEG_OVRLD_FLAG = 28, + TWAI_LL_ERR_SEG_MAX = 29, +} twai_ll_err_seg_t; + +/* + * The following frame structure has an NEARLY identical bit field layout to + * each byte of the TX buffer. This allows for formatting and parsing frames to + * be done outside of time critical regions (i.e., ISRs). All the ISR needs to + * do is to copy byte by byte to/from the TX/RX buffer. The two reserved bits in + * TX buffer are used in the frame structure to store the self_reception and + * single_shot flags which in turn indicate the type of transmission to execute. + */ +typedef union twai_ll_frame_buffer_t { + struct { + struct { + uint8_t dlc: 4; //Data length code (0 to 8) of the frame + uint8_t self_reception: 1; //This frame should be transmitted using self reception command + uint8_t single_shot: 1; //This frame should be transmitted using single shot command + uint8_t rtr: 1; //This frame is a remote transmission request + uint8_t frame_format: 1; //Format of the frame (1 = extended, 0 = standard) + }; + union { + struct { + uint8_t id[2]; //11 bit standard frame identifier + uint8_t data[8]; //Data bytes (0 to 8) + uint8_t reserved8[2]; + } standard; + struct { + uint8_t id[4]; //29 bit extended frame identifier + uint8_t data[8]; //Data bytes (0 to 8) + } extended; + }; + }; + uint8_t bytes[13]; +} __attribute__((packed)) twai_ll_frame_buffer_t; + +ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes"); + +/* ---------------------------- Reset and Clock Control ------------------------------ */ + +/** + * @brief Enable the bus clock for twai module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void twai_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.twai0_conf.twai0_clk_en = enable; +} + +/** + * @brief Reset the twai module + * + * @param group_id Group ID + */ +static inline void twai_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.twai0_conf.twai0_rst_en = 1; + PCR.twai0_conf.twai0_rst_en = 0; +} + +/* ---------------------------- Peripheral Control Register ----------------- */ + +/** + * @brief Enable TWAI module clock + * + * @param group_id Group ID + * @param en true to enable, false to disable + */ +__attribute__((always_inline)) +static inline void twai_ll_enable_clock(int group_id, bool en) +{ + (void)group_id; + PCR.twai0_func_clk_conf.twai0_func_clk_en = en; +} + +/** + * @brief Set clock source for TWAI module + * + * @param group_id Group ID + * @param clk_src Clock source + */ +__attribute__((always_inline)) +static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src) +{ + (void)group_id; + switch (clk_src) { + case TWAI_CLK_SRC_XTAL: + PCR.twai0_func_clk_conf.twai0_func_clk_sel = 0; + break; + default: + HAL_ASSERT(false); + } +} + +/* ---------------------------- Mode Register ------------------------------- */ + +/** + * @brief Enter reset mode + * + * When in reset mode, the TWAI controller is effectively disconnected from the + * TWAI bus and will not participate in any bus activates. Reset mode is required + * in order to write the majority of configuration registers. + * + * @param hw Start address of the TWAI registers + * + * @note Reset mode is automatically entered on BUS OFF condition + */ +__attribute__((always_inline)) +static inline void twai_ll_enter_reset_mode(twai_dev_t *hw) +{ + hw->mode.reset_mode = 1; +} + +/** + * @brief Exit reset mode + * + * When not in reset mode, the TWAI controller will take part in bus activities + * (e.g., send/receive/acknowledge messages and error frames) depending on the + * operating mode. + * + * @param hw Start address of the TWAI registers + * + * @note Reset mode must be exit to initiate BUS OFF recovery + */ +__attribute__((always_inline)) +static inline void twai_ll_exit_reset_mode(twai_dev_t *hw) +{ + hw->mode.reset_mode = 0; +} + +/** + * @brief Check if in reset mode + * @param hw Start address of the TWAI registers + * @return true if in reset mode + */ +__attribute__((always_inline)) +static inline bool twai_ll_is_in_reset_mode(twai_dev_t *hw) +{ + return hw->mode.reset_mode; +} + +/** + * @brief Set operating mode of TWAI controller + * + * @param hw Start address of the TWAI registers + * @param mode Operating mode + * + * @note Must be called in reset mode + */ +__attribute__((always_inline)) +static inline void twai_ll_set_mode(twai_dev_t *hw, bool listen_only, bool no_ack, bool loopback) +{ + hw->mode.listen_only_mode = listen_only; + hw->mode.self_test_mode = no_ack; +} + +/* --------------------------- Command Register ----------------------------- */ + +/** + * @brief Set TX 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 + * + * @note Transmit commands should be called last (i.e., after handling buffer + * release and clear data overrun) in order to prevent the other commands + * overwriting this latched TX bit with 0. + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_tx(twai_dev_t *hw) +{ + hw->cmd.tx_request = 1; +} + +/** + * @brief Set single shot TX command + * + * Similar to setting TX command, but the TWAI controller will not automatically + * retry transmission upon an error (e.g., due to an acknowledgement error). + * + * @param hw Start address of the TWAI registers + * + * @note Transmit commands should be called last (i.e., after handling buffer + * release and clear data overrun) in order to prevent the other commands + * overwriting this latched TX bit with 0. + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_tx_single_shot(twai_dev_t *hw) +{ + hw->cmd.val = 0x03; //Set cmd.tx_request and cmd.abort_tx simultaneously for single shot transmitting request +} + +/** + * @brief Aborts TX + * + * Frames awaiting TX will be aborted. Frames already being TX are not aborted. + * Transmission Complete Status bit is automatically set to 1. + * Similar to setting TX command, but the TWAI controller will not automatically + * retry transmission upon an error (e.g., due to acknowledge error). + * + * @param hw Start address of the TWAI registers + * + * @note Transmit commands should be called last (i.e., after handling buffer + * release and clear data overrun) in order to prevent the other commands + * overwriting this latched TX bit with 0. + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_abort_tx(twai_dev_t *hw) +{ + hw->cmd.abort_tx = 1; +} + +/** + * @brief Release RX buffer + * + * Rotates RX buffer to the next frame in the RX FIFO. + * + * @param hw Start address of the TWAI registers + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_release_rx_buffer(twai_dev_t *hw) +{ + hw->cmd.release_buffer = 1; +} + +/** + * @brief Clear data overrun + * + * Clears the data overrun status bit + * + * @param hw Start address of the TWAI registers + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_clear_data_overrun(twai_dev_t *hw) +{ + hw->cmd.clear_data_overrun = 1; +} + +/** + * @brief Set self reception single shot command + * + * Similar to setting TX command, but the TWAI controller also simultaneously + * receive the transmitted frame and is generally used for self testing + * purposes. The TWAI controller will not ACK the received message, so consider + * using the NO_ACK operating mode. + * + * @param hw Start address of the TWAI registers + * + * @note Transmit commands should be called last (i.e., after handling buffer + * release and clear data overrun) in order to prevent the other commands + * overwriting this latched TX bit with 0. + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_self_rx_request(twai_dev_t *hw) +{ + hw->cmd.self_rx_request = 1; +} + +/** + * @brief Set self reception request command + * + * Similar to setting the self reception request, but the TWAI controller will + * not automatically retry transmission upon an error (e.g., due to and + * acknowledgement error). + * + * @param hw Start address of the TWAI registers + * + * @note Transmit commands should be called last (i.e., after handling buffer + * release and clear data overrun) in order to prevent the other commands + * overwriting this latched TX bit with 0. + */ +__attribute__((always_inline)) +static inline void twai_ll_set_cmd_self_rx_single_shot(twai_dev_t *hw) +{ + hw->cmd.val = 0x12; //Set cmd.self_rx_request and cmd.abort_tx simultaneously for single shot self reception request +} + +/* --------------------------- Status Register ------------------------------ */ + +/** + * @brief Get all status bits + * + * @param hw Start address of the TWAI registers + * @return Status bits + */ +__attribute__((always_inline)) +static inline uint32_t twai_ll_get_status(twai_dev_t *hw) +{ + return hw->status.val; +} + +/* -------------------------- Interrupt Register ---------------------------- */ + +/** + * @brief Get currently set interrupts + * + * Reading the interrupt registers will automatically clear all interrupts + * except for the Receive Interrupt. + * + * @param hw Start address of the TWAI registers + * @return Bit mask of set interrupts + */ +__attribute__((always_inline)) +static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw) +{ + return hw->interrupt.val; +} + +/* ----------------------- Interrupt Enable Register ------------------------ */ + +/** + * @brief Set which interrupts are enabled + * + * @param hw Start address of the TWAI registers + * @param Bit mask of interrupts to enable + * + * @note Must be called in reset mode + */ +__attribute__((always_inline)) +static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask) +{ + hw->interrupt_enable.val = intr_mask; +} + +/* ------------------------ Bus Timing Registers --------------------------- */ + +/** + * @brief Check if the brp value valid + * + * @param brp Bit rate prescaler value + * @return true or False + */ +__attribute__((always_inline)) +static inline bool twai_ll_check_brp_validation(uint32_t brp) +{ + bool valid = (brp >= TWAI_LL_BRP_MIN) && (brp <= TWAI_LL_BRP_MAX); + // should be an even number + valid = valid && !(brp & 0x01); + return valid; +} + +/** + * @brief Set bus timing + * + * @param hw Start address of the TWAI registers + * @param brp Baud Rate Prescaler + * @param sjw Synchronization Jump Width + * @param tseg1 Timing Segment 1 + * @param tseg2 Timing Segment 2 + * @param triple_sampling Triple Sampling enable/disable + * + * @note Must be called in reset mode + * @note ESP32H21 brp can be any even number between 2 to 32768 + */ +__attribute__((always_inline)) +static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t sjw, uint32_t tseg1, uint32_t tseg2, bool triple_sampling) +{ + hw->bus_timing_0.baud_presc = (brp / 2) - 1; + hw->bus_timing_0.sync_jump_width = sjw - 1; + hw->bus_timing_1.time_segment1 = tseg1 - 1; + hw->bus_timing_1.time_segment2 = tseg2 - 1; + hw->bus_timing_1.time_sampling = triple_sampling; +} + +/* ----------------------------- ALC Register ------------------------------- */ + +/** + * @brief Clear Arbitration Lost Capture Register + * + * Reading the ALC register rearms the Arbitration Lost Interrupt + * + * @param hw Start address of the TWAI registers + */ +__attribute__((always_inline)) +static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw) +{ + (void)hw->arb_lost_cap.val; +} + +/* ----------------------------- ECC Register ------------------------------- */ + +/** + * @brief Parse Error Code Capture register + * + * Reading the ECC register rearms the Bus Error Interrupt + * + * @param hw Start address of the TWAI registers + */ +__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); +} + +/* ----------------------------- EWL Register ------------------------------- */ + +/** + * @brief Set Error Warning Limit + * + * @param hw Start address of the TWAI registers + * @param ewl Error Warning Limit + * + * @note Must be called in reset mode + */ +__attribute__((always_inline)) +static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->err_warning_limit, err_warning_limit, ewl); +} + +/** + * @brief Get Error Warning Limit + * + * @param hw Start address of the TWAI registers + * @return Error Warning Limit + */ +__attribute__((always_inline)) +static inline uint32_t twai_ll_get_err_warn_lim(twai_dev_t *hw) +{ + return hw->err_warning_limit.val; +} + +/* ------------------------ RX Error Count Register ------------------------- */ + +/** + * @brief Get RX Error Counter + * + * @param hw Start address of the TWAI registers + * @return REC value + * + * @note REC is not frozen in reset mode. Listen only mode will freeze it. A BUS + * OFF condition automatically sets the REC to 0. + */ +__attribute__((always_inline)) +static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) +{ + return hw->rx_err_cnt.val; +} + +/** + * @brief Set RX Error Counter + * + * @param hw Start address of the TWAI registers + * @param rec REC value + * + * @note Must be called in reset mode + */ +__attribute__((always_inline)) +static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_err_cnt, rx_err_cnt, rec); +} + +/* ------------------------ TX Error Count Register ------------------------- */ + +/** + * @brief Get TX Error Counter + * + * @param hw Start address of the TWAI registers + * @return TEC value + * + * @note A BUS OFF condition will automatically set this to 128 + */ +__attribute__((always_inline)) +static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) +{ + return hw->tx_err_cnt.val; +} + +/** + * @brief Set TX Error Counter + * + * @param hw Start address of the TWAI registers + * @param tec TEC value + * + * @note Must be called in reset mode + */ +__attribute__((always_inline)) +static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_err_cnt, tx_err_cnt, tec); +} + +/* ---------------------- Acceptance Filter Registers ----------------------- */ + +/** + * @brief Set Acceptance Filter + * @param hw Start address of the TWAI registers + * @param code Acceptance Code + * @param mask Acceptance Mask + * @param single_filter Whether to enable single filter mode + * + * @note Must be called in reset mode + */ +__attribute__((always_inline)) +static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_t mask, bool single_filter) +{ + uint32_t code_swapped = HAL_SWAP32(code); + uint32_t mask_swapped = HAL_SWAP32(mask); + for (int i = 0; i < 4; i++) { + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); + } + hw->mode.acceptance_filter_mode = single_filter; +} + +/* ------------------------- TX/RX Buffer Registers ------------------------- */ + +/** + * @brief Copy a formatted TWAI frame into TX buffer for transmission + * + * @param hw Start address of the TWAI registers + * @param tx_frame Pointer to formatted frame + * + * @note Call twai_ll_format_frame_buffer() to format a frame + */ +__attribute__((always_inline)) +static inline void twai_ll_set_tx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t *tx_frame) +{ + //Copy formatted frame into TX buffer + for (int i = 0; i < 13; i++) { + hw->tx_rx_buffer[i].val = tx_frame->bytes[i]; + } +} + +/** + * @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 + * + * @note Call twai_ll_parse_frame_buffer() to parse the formatted frame + */ +__attribute__((always_inline)) +static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t *rx_frame) +{ + //Copy RX buffer registers into frame + for (int i = 0; i < 13; i++) { + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); + } +} + +/** + * @brief Format contents of a TWAI frame into layout of TX Buffer + * + * This function encodes a message into a frame structure. The frame structure + * has an identical layout to the TX buffer, allowing the frame structure to be + * directly copied into TX buffer. + * + * @param[in] 11bit or 29bit ID + * @param[in] dlc Data length code + * @param[in] data Pointer to an 8 byte array containing data. NULL if no data + * @param[in] format Type of TWAI frame + * @param[in] single_shot Frame will not be retransmitted on failure + * @param[in] self_rx Frame will also be simultaneously received + * @param[out] tx_frame Pointer to store formatted frame + */ +__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) +{ + bool is_extd = flags & TWAI_MSG_FLAG_EXTD; + bool is_rtr = flags & TWAI_MSG_FLAG_RTR; + + //Set frame information + tx_frame->dlc = dlc; + tx_frame->frame_format = is_extd; + tx_frame->rtr = is_rtr; + tx_frame->self_reception = (flags & TWAI_MSG_FLAG_SELF) ? 1 : 0; + tx_frame->single_shot = (flags & TWAI_MSG_FLAG_SS) ? 1 : 0; + + //Set ID. The ID registers are big endian and left aligned, therefore a bswap will be required + if (is_extd) { + uint32_t id_temp = HAL_SWAP32((id & TWAI_EXTD_ID_MASK) << 3); //((id << 3) >> 8*(3-i)) + for (int i = 0; i < 4; i++) { + tx_frame->extended.id[i] = (id_temp >> (8 * i)) & 0xFF; + } + } else { + uint32_t id_temp = HAL_SWAP16((id & TWAI_STD_ID_MASK) << 5); //((id << 5) >> 8*(1-i)) + for (int i = 0; i < 2; i++) { + tx_frame->standard.id[i] = (id_temp >> (8 * i)) & 0xFF; + } + } + + uint8_t *data_buffer = (is_extd) ? tx_frame->extended.data : tx_frame->standard.data; + if (!is_rtr) { //Only copy data if the frame is a data frame (i.e not a remote frame) + for (int i = 0; (i < dlc) && (i < TWAI_FRAME_MAX_DLC); i++) { + data_buffer[i] = data[i]; + } + } +} + +/** + * @brief Check if the message in twai_ll_frame_buffer is extend id format or not + * + * @param rx_frame The rx_frame in twai_ll_frame_buffer_t type + * @return true if the message is extend id format, false if not + */ +__attribute__((always_inline)) +static inline bool twai_ll_frame_is_ext_format(twai_ll_frame_buffer_t *rx_frame) +{ + return rx_frame->frame_format; +} + +/** + * @brief Parse formatted TWAI frame (RX Buffer Layout) into its constituent contents + * + * @param[in] rx_frame Pointer to formatted frame + * @param[out] id 11 or 29bit ID + * @param[out] dlc Data length code + * @param[out] data Data. Left over bytes set to 0. + * @param[out] format Type of TWAI frame + */ +__attribute__((always_inline)) +static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc, + uint8_t *data, uint32_t buf_sz, uint32_t *flags) +{ + //Copy frame information + *dlc = rx_frame->dlc; + uint32_t flags_temp = 0; + flags_temp |= (rx_frame->frame_format) ? TWAI_MSG_FLAG_EXTD : 0; + flags_temp |= (rx_frame->rtr) ? TWAI_MSG_FLAG_RTR : 0; + flags_temp |= (rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_MSG_FLAG_DLC_NON_COMP : 0; + *flags = flags_temp; + + //Copy ID. The ID registers are big endian and left aligned, therefore a bswap will be required + if (rx_frame->frame_format) { + uint32_t id_temp = 0; + for (int i = 0; i < 4; i++) { + id_temp |= rx_frame->extended.id[i] << (8 * i); + } + id_temp = HAL_SWAP32(id_temp) >> 3; //((byte[i] << 8*(3-i)) >> 3) + *id = id_temp & TWAI_EXTD_ID_MASK; + } else { + uint32_t id_temp = 0; + for (int i = 0; i < 2; i++) { + id_temp |= rx_frame->standard.id[i] << (8 * i); + } + id_temp = HAL_SWAP16(id_temp) >> 5; //((byte[i] << 8*(1-i)) >> 5) + *id = id_temp & TWAI_STD_ID_MASK; + } + + uint8_t *data_buffer = (rx_frame->frame_format) ? rx_frame->extended.data : rx_frame->standard.data; + //Only copy data if the frame is a data frame (i.e. not a remote frame) + int data_length = (rx_frame->rtr) ? 0 : ((rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_FRAME_MAX_DLC : rx_frame->dlc); + data_length = (data_length < buf_sz) ? data_length : buf_sz; + for (int i = 0; i < data_length; i++) { + data[i] = data_buffer[i]; + } +} + +/* ----------------------- RX Message Count Register ------------------------ */ + +/** + * @brief Get RX Message Counter + * + * @param hw Start address of the TWAI registers + * @return RX Message Counter + */ +__attribute__((always_inline)) +static inline uint32_t twai_ll_get_rx_msg_count(twai_dev_t *hw) +{ + return hw->rx_message_counter.val; +} + +/* ------------------------- Clock Divider Register ------------------------- */ + +/** + * @brief Set CLKOUT Divider and enable/disable + * + * Configure CLKOUT. CLKOUT is a pre-scaled version of peripheral source clock. Divider can be + * 1, or any even number from 2 to 490. Set the divider to 0 to disable CLKOUT. + * + * @param hw Start address of the TWAI registers + * @param divider Divider for CLKOUT (any even number from 2 to 490). Set to 0 to disable CLKOUT + */ +__attribute__((always_inline)) +static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) +{ + if (divider >= 2 && divider <= 490) { + hw->clock_divider.clock_off = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider, cd, (divider / 2) - 1); + } else if (divider == 1) { + //Setting the divider reg to max value (255) means a divider of 1 + hw->clock_divider.clock_off = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider, cd, 255); + } else { + hw->clock_divider.clock_off = 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider, cd, 0); + + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 0902e9b0ac..2c7520c1be 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -115,6 +115,10 @@ config SOC_REG_I2C_SUPPORTED bool default y +config SOC_TWAI_SUPPORTED + bool + default y + config SOC_RMT_SUPPORTED bool default y @@ -711,6 +715,34 @@ config SOC_MWDT_SUPPORT_SLEEP_RETENTION bool default y +config SOC_TWAI_CONTROLLER_NUM + int + default 1 + +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 + config SOC_EFUSE_DIS_PAD_JTAG bool default y diff --git a/components/soc/esp32h21/include/soc/clk_tree_defs.h b/components/soc/esp32h21/include/soc/clk_tree_defs.h index b1a9a6596a..0e29e70840 100644 --- a/components/soc/esp32h21/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h21/include/soc/clk_tree_defs.h @@ -290,6 +290,21 @@ typedef enum { SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as SPI source clock */ } soc_periph_spi_clk_src_t; +//////////////////////////////////////////////////TWAI///////////////////////////////////////////////////////////////// + +/** + * @brief Array initializer for all supported clock sources of TWAI + */ +#define SOC_TWAI_CLKS {SOC_MOD_CLK_XTAL} + +/** + * @brief TWAI clock source + */ +typedef enum { + TWAI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + TWAI_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default clock choice */ +} soc_periph_twai_clk_src_t; + //////////////////////////////////////////////////MWDT///////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32h21/include/soc/gpio_sig_map.h b/components/soc/esp32h21/include/soc/gpio_sig_map.h index e6e4080df8..00314572cb 100644 --- a/components/soc/esp32h21/include/soc/gpio_sig_map.h +++ b/components/soc/esp32h21/include/soc/gpio_sig_map.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 49732ef5cd..007d767c0e 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -74,7 +74,7 @@ // #define SOC_PHY_SUPPORTED 1 // #define SOC_PCNT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11566 // #define SOC_MCPWM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11601 -// #define SOC_TWAI_SUPPORTED 1 //TODO: [ESP32H21] IDF-11574 +#define SOC_TWAI_SUPPORTED 1 // #define SOC_ETM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11576 // #define SOC_PARLIO_SUPPORTED 1 //TODO: [ESP32H21] IDF-11570, IDF-11572 #define SOC_RMT_SUPPORTED 1 @@ -446,11 +446,13 @@ #define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- TWAI CAPS ---------------------------------------*/ -// #define SOC_TWAI_CONTROLLER_NUM 1UL -// #define SOC_TWAI_CLK_SUPPORT_XTAL 1 -// #define SOC_TWAI_BRP_MIN 2 -// #define SOC_TWAI_BRP_MAX 32768 -// #define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#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----------------------------*/ #define SOC_EFUSE_DIS_PAD_JTAG 1 diff --git a/components/soc/esp32h21/register/soc/twai_struct.h b/components/soc/esp32h21/register/soc/twai_struct.h index 2905bf2c8c..134f93f1e2 100644 --- a/components/soc/esp32h21/register/soc/twai_struct.h +++ b/components/soc/esp32h21/register/soc/twai_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -484,215 +484,46 @@ typedef union { uint32_t val; } twai_interrupt_enable_reg_t; - /** Group: Data Registers */ -/** Type of data_0 register - * Data register 0. +/** Type of buffer register + * TX RX Buffer. */ typedef union { struct { - /** data_0 : R/W; bitpos: [7:0]; default: 0; + /** byte : R/W; bitpos: [7:0]; default: 0; * In reset mode, it is acceptance code register 0 with R/W Permission. In operation * mode, when software initiate write operation, it is tx data register 0 and when * software initiate read operation, it is rx data register 0. */ - uint32_t data_0:8; + uint32_t byte:8; uint32_t reserved_8:24; }; uint32_t val; -} twai_data_0_reg_t; +} twai_tx_rx_buffer_reg_t; -/** Type of data_1 register - * Data register 1. - */ -typedef union { - struct { - /** data_1 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance code register 1 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 1 and when - * software initiate read operation, it is rx data register 1. - */ - uint32_t data_1:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_1_reg_t; +typedef struct { + union { + struct { + uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ + uint32_t reserved8: 24; /* Internal Reserved */ + }; + uint32_t val; + } acr[4]; + union { + struct { + uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ + uint32_t reserved8: 24; /* Internal Reserved */ + }; + uint32_t val; + } amr[4]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; +} acceptance_filter_reg_t; -/** Type of data_2 register - * Data register 2. - */ -typedef union { - struct { - /** data_2 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance code register 2 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 2 and when - * software initiate read operation, it is rx data register 2. - */ - uint32_t data_2:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_2_reg_t; -/** Type of data_3 register - * Data register 3. - */ -typedef union { - struct { - /** data_3 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance code register 3 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 3 and when - * software initiate read operation, it is rx data register 3. - */ - uint32_t data_3:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_3_reg_t; - -/** Type of data_4 register - * Data register 4. - */ -typedef union { - struct { - /** data_4 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance mask register 0 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 4 and when - * software initiate read operation, it is rx data register 4. - */ - uint32_t data_4:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_4_reg_t; - -/** Type of data_5 register - * Data register 5. - */ -typedef union { - struct { - /** data_5 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance mask register 1 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 5 and when - * software initiate read operation, it is rx data register 5. - */ - uint32_t data_5:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_5_reg_t; - -/** Type of data_6 register - * Data register 6. - */ -typedef union { - struct { - /** data_6 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance mask register 2 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 6 and when - * software initiate read operation, it is rx data register 6. - */ - uint32_t data_6:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_6_reg_t; - -/** Type of data_7 register - * Data register 7. - */ -typedef union { - struct { - /** data_7 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, it is acceptance mask register 3 with R/W Permission. In operation - * mode, when software initiate write operation, it is tx data register 7 and when - * software initiate read operation, it is rx data register 7. - */ - uint32_t data_7:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_7_reg_t; - -/** Type of data_8 register - * Data register 8. - */ -typedef union { - struct { - /** data_8 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, reserved with RO. In operation mode, when software initiate write - * operation, it is tx data register 8 and when software initiate read operation, it - * is rx data register 8. - */ - uint32_t data_8:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_8_reg_t; - -/** Type of data_9 register - * Data register 9. - */ -typedef union { - struct { - /** data_9 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, reserved with RO. In operation mode, when software initiate write - * operation, it is tx data register 9 and when software initiate read operation, it - * is rx data register 9. - */ - uint32_t data_9:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_9_reg_t; - -/** Type of data_10 register - * Data register 10. - */ -typedef union { - struct { - /** data_10 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, reserved with RO. In operation mode, when software initiate write - * operation, it is tx data register 10 and when software initiate read operation, it - * is rx data register 10. - */ - uint32_t data_10:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_10_reg_t; - -/** Type of data_11 register - * Data register 11. - */ -typedef union { - struct { - /** data_11 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, reserved with RO. In operation mode, when software initiate write - * operation, it is tx data register 11 and when software initiate read operation, it - * is rx data register 11. - */ - uint32_t data_11:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_11_reg_t; - -/** Type of data_12 register - * Data register 12. - */ -typedef union { - struct { - /** data_12 : R/W; bitpos: [7:0]; default: 0; - * In reset mode, reserved with RO. In operation mode, when software initiate write - * operation, it is tx data register 12 and when software initiate read operation, it - * is rx data register 12. - */ - uint32_t data_12:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} twai_data_12_reg_t; typedef struct twai_dev_t { @@ -710,19 +541,10 @@ typedef struct twai_dev_t { volatile twai_err_warning_limit_reg_t err_warning_limit; volatile twai_rx_err_cnt_reg_t rx_err_cnt; volatile twai_tx_err_cnt_reg_t tx_err_cnt; - volatile twai_data_0_reg_t data_0; - volatile twai_data_1_reg_t data_1; - volatile twai_data_2_reg_t data_2; - volatile twai_data_3_reg_t data_3; - volatile twai_data_4_reg_t data_4; - volatile twai_data_5_reg_t data_5; - volatile twai_data_6_reg_t data_6; - volatile twai_data_7_reg_t data_7; - volatile twai_data_8_reg_t data_8; - volatile twai_data_9_reg_t data_9; - volatile twai_data_10_reg_t data_10; - volatile twai_data_11_reg_t data_11; - volatile twai_data_12_reg_t data_12; + volatile union { + acceptance_filter_reg_t acceptance_filter; + twai_tx_rx_buffer_reg_t tx_rx_buffer[13]; + }; volatile twai_rx_message_counter_reg_t rx_message_counter; uint32_t reserved_078; volatile twai_clock_divider_reg_t clock_divider; diff --git a/components/soc/esp32h21/twai_periph.c b/components/soc/esp32h21/twai_periph.c new file mode 100644 index 0000000000..4c958a59dd --- /dev/null +++ b/components/soc/esp32h21/twai_periph.c @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/twai_periph.h" +#include "soc/twai_reg.h" +#include "soc/gpio_sig_map.h" + +const twai_signal_conn_t twai_periph_signals[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_name = "TWAI0", + .irq_id = ETS_TWAI0_INTR_SOURCE, + .tx_sig = TWAI0_TX_IDX, + .rx_sig = TWAI0_RX_IDX, + .bus_off_sig = TWAI0_BUS_OFF_ON_IDX, + .clk_out_sig = TWAI0_CLKOUT_IDX, + .stand_by_sig = TWAI0_STANDBY_IDX, + } +}; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) DR_REG_TWAI_BASE +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +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] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, +}; diff --git a/docs/docs_not_updated/esp32h21.txt b/docs/docs_not_updated/esp32h21.txt index e1b93bbf7d..097084c644 100644 --- a/docs/docs_not_updated/esp32h21.txt +++ b/docs/docs_not_updated/esp32h21.txt @@ -142,7 +142,6 @@ api-reference/peripherals/mcpwm.rst api-reference/peripherals/usb_host.rst api-reference/peripherals/camera_driver.rst api-reference/peripherals/adc_oneshot.rst -api-reference/peripherals/twai.rst api-reference/peripherals/etm.rst api-reference/peripherals/sdspi_share.rst api-reference/peripherals/ana_cmpr.rst diff --git a/examples/peripherals/twai/twai_alert_and_recovery/README.md b/examples/peripherals/twai/twai_alert_and_recovery/README.md index 860c76d494..f53817ca00 100644 --- a/examples/peripherals/twai/twai_alert_and_recovery/README.md +++ b/examples/peripherals/twai/twai_alert_and_recovery/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # TWAI Alert and Recovery Example diff --git a/examples/peripherals/twai/twai_network/README.md b/examples/peripherals/twai/twai_network/README.md index a10d4ca76f..9d5878a880 100644 --- a/examples/peripherals/twai/twai_network/README.md +++ b/examples/peripherals/twai/twai_network/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # TWAI Network Example diff --git a/examples/peripherals/twai/twai_self_test/README.md b/examples/peripherals/twai/twai_self_test/README.md index ae75e83231..f321f6aea1 100644 --- a/examples/peripherals/twai/twai_self_test/README.md +++ b/examples/peripherals/twai/twai_self_test/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | # TWAI Self Test Example