From 3e361a559f8fc2291f5d62a446f538b44bcdaaf9 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 23 Oct 2025 16:36:58 +0800 Subject: [PATCH] refactor(driver_twai): remove errata config selection 5 --- components/driver/twai/Kconfig.twai | 11 ----------- components/driver/twai/linker.lf | 2 +- components/driver/twai/twai.c | 2 +- components/esp_driver_twai/Kconfig | 2 +- components/esp_driver_twai/esp_twai_onchip.c | 7 +++++-- components/hal/esp32/include/hal/twai_ll.h | 4 ++++ components/hal/twai_hal_v1.c | 20 +++++++++++--------- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/components/driver/twai/Kconfig.twai b/components/driver/twai/Kconfig.twai index 35a535771d4..7ed12e03f17 100644 --- a/components/driver/twai/Kconfig.twai +++ b/components/driver/twai/Kconfig.twai @@ -21,15 +21,4 @@ menu "Legacy TWAI Driver Configurations" help This configuration option used to bypass the conflict check mechanism with legacy code. - config TWAI_ERRATA_FIX_RX_FRAME_INVALID - bool "Add SW workaround for invalid RX frame errata" - depends on IDF_TARGET_ESP32 - default y - help - On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field, - the data of the next received frame could be invalid. Enabling this option will add a workaround that - will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on - the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus - during the reset, the message will be lost. - endmenu # TWAI Configuration diff --git a/components/driver/twai/linker.lf b/components/driver/twai/linker.lf index 67b93ecd9c2..968506ed339 100644 --- a/components/driver/twai/linker.lf +++ b/components/driver/twai/linker.lf @@ -23,7 +23,7 @@ entries: twai_hal_v1: twai_hal_check_state_flags (noflash) twai_hal_v1: twai_hal_clear_rx_fifo_overrun (noflash) - if TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || IDF_TARGET_ESP32 = y: + if IDF_TARGET_ESP32 = y: #For errata workarounds twai_hal_v1: twai_hal_prepare_for_reset (noflash) twai_hal_v1: twai_hal_recover_from_reset (noflash) twai_hal_v1: twai_hal_backup_config (noflash) diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index bb47982bb91..3b107c7b718 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -226,7 +226,7 @@ static void twai_intr_handler_main(void *arg) portENTER_CRITICAL_ISR(&p_twai_obj->spinlock); events = twai_hal_get_events(p_twai_obj->hal); //Get the events that triggered the interrupt -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE // Errata workaround: Reset the peripheral on detection of this errata condition. // Note that if a frame is being sent on the bus during the reset, the message will be lost. if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { diff --git a/components/esp_driver_twai/Kconfig b/components/esp_driver_twai/Kconfig index 6b657a8521a..1b979310563 100644 --- a/components/esp_driver_twai/Kconfig +++ b/components/esp_driver_twai/Kconfig @@ -18,7 +18,7 @@ menu "ESP-Driver:TWAI Configurations" config TWAI_ISR_CACHE_SAFE bool "Allow TWAI ISR execute when cache disabled" if !SPI_FLASH_AUTO_SUSPEND select TWAI_ISR_IN_IRAM - select ESP_PERIPH_CTRL_FUNC_IN_IRAM if TWAI_ERRATA_FIX_RX_FRAME_INVALID || IDF_TARGET_ESP32 + select ESP_PERIPH_CTRL_FUNC_IN_IRAM if IDF_TARGET_ESP32 #For errata workarounds default n help Allow TWAI works under Cache disabled (such as when writing to SPI Flash), diff --git a/components/esp_driver_twai/esp_twai_onchip.c b/components/esp_driver_twai/esp_twai_onchip.c index f83b76dc31f..7a8440842ed 100644 --- a/components/esp_driver_twai/esp_twai_onchip.c +++ b/components/esp_driver_twai/esp_twai_onchip.c @@ -201,8 +201,11 @@ static void _node_isr_main(void *arg) twai_onchip_ctx_t *twai_ctx = arg; uint32_t events = twai_hal_get_events(twai_ctx->hal); //Get the events that triggered the interrupt -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE + // Errata workaround: Reset the peripheral on detection of this errata condition. + // Note that if a frame is being sent on the bus during the reset, the message will be lost. if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { + ESP_EARLY_LOGD(TAG, "Triggered peripheral reset"); twai_hal_prepare_for_reset(twai_ctx->hal); TWAI_RCC_ATOMIC() { twai_ll_reset_register(twai_ctx->ctrlr_id); @@ -498,7 +501,7 @@ static esp_err_t _node_disable(twai_node_handle_t node) ESP_RETURN_ON_ERROR(esp_intr_disable(twai_ctx->intr_hdl), TAG, "disable interrupt failed"); atomic_store(&twai_ctx->state, TWAI_ERROR_BUS_OFF); twai_hal_stop(twai_ctx->hal); -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE // when `disable` happens during hardware busy, the next RX frame is corrupted, a HW reset can fix it if (twai_hal_is_hw_busy(twai_ctx->hal)) { twai_hal_backup_config(twai_ctx->hal); diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index 4a3654446b5..036a8e6c610 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -49,6 +49,10 @@ // RX FIFO is no longer recoverable. #define TWAI_LL_HAS_RX_FIFO_ISSUE 1 +// On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field, +// the data field of the NEXT received frame could be invalid. +#define TWAI_LL_HAS_RX_FRAME_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index f03016d325e..570db8be366 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -17,7 +17,8 @@ #define TWAI_HAL_INIT_REC 0 #define TWAI_HAL_INIT_EWL 96 -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE +// context for errata workarounds typedef struct twai_hal_errata_ctx_t { twai_hal_frame_t tx_frame_save; twai_ll_reg_save_t reg_save; @@ -26,7 +27,7 @@ typedef struct twai_hal_errata_ctx_t { #endif size_t twai_hal_get_mem_requirment(void) { -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#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 return sizeof(twai_hal_context_t); @@ -49,7 +50,7 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config) if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers return false; } -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#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 @@ -289,12 +290,13 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) .ack_err = (type == TWAI_LL_ERR_OTHER) && (seg == TWAI_LL_ERR_SEG_ACK_SLOT), }; hal_ctx->errors = errors; -#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID +#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))) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_NEED_PERIPH_RESET); + HAL_LOGD("TWAI_HAL", "RX frame invalid detected"); } #endif } @@ -308,7 +310,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) HAL_LOGD("TWAI_HAL", "RX FIFO corruption detected"); } #endif -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { //A peripheral reset will invalidate an RX event; TWAI_HAL_CLEAR_BITS(events, (TWAI_HAL_EVENT_RX_BUFF_FRAME)); @@ -317,7 +319,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) return events; } -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE bool twai_hal_is_hw_busy(twai_hal_context_t *hal_ctx) { return (TWAI_LL_STATUS_TS | TWAI_LL_STATUS_RS) & twai_ll_get_status(hal_ctx->dev); @@ -366,7 +368,7 @@ void twai_hal_recover_from_reset(twai_hal_context_t *hal_ctx) TWAI_HAL_CLEAR_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_NEED_RETRY); } } -#endif // CONFIG_IDF_TARGET_ESP32 +#endif // TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE void twai_hal_format_frame(const twai_hal_trans_desc_t *trans_desc, twai_hal_frame_t *frame) { @@ -406,7 +408,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f twai_ll_set_cmd_tx(hal_ctx->dev); } TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED); -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE if (&hal_ctx->errata_ctx->tx_frame_save == tx_frame) { return; } @@ -414,7 +416,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-overlapping-buffers") // TODO IDF-11085 memcpy(&hal_ctx->errata_ctx->tx_frame_save, tx_frame, sizeof(twai_hal_frame_t)); ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-overlapping-buffers") -#endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#endif //TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE } uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx)