diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 4169d734f4..127c09350a 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -143,6 +143,17 @@ menu "Driver configurations" on detection of this errata condition. Note that if a frame is being sent on the bus during the reset bus during the reset, the message will be lost. + config TWAI_ERRATA_FIX_LISTEN_ONLY_DOM + bool "Add SW workaround for listen only transmits dominant bit errata" + depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3 + default n + help + When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send + any dominant bits). However, while in listen only mode on the ESP32/ESP32-S2/ESP32-S3/ESP32-C3, the + TWAI controller will still transmit dominant bits when it detects an error (i.e., as part of an active + error frame). Enabling this option will add a workaround that forces the TWAI controller into an error + passive state on initialization, thus preventing any dominant bits from being sent. + endmenu # TWAI Configuration menu "UART configuration" diff --git a/components/driver/twai.c b/components/driver/twai.c index 17d34e9ccd..cb9a14a315 100644 --- a/components/driver/twai.c +++ b/components/driver/twai.c @@ -668,8 +668,14 @@ esp_err_t twai_get_status_info(twai_status_info_t *status_info) TWAI_CHECK(status_info != NULL, ESP_ERR_INVALID_ARG); TWAI_ENTER_CRITICAL(); - status_info->tx_error_counter = twai_hal_get_tec(&twai_context); - status_info->rx_error_counter = twai_hal_get_rec(&twai_context); + if (p_twai_obj->mode == TWAI_MODE_LISTEN_ONLY) { + //Error counters are frozen under listen only mode thus are meaningless. Simply return 0 in this case. + status_info->tx_error_counter = 0; + status_info->rx_error_counter = 0; + } else { + status_info->tx_error_counter = twai_hal_get_tec(&twai_context); + status_info->rx_error_counter = twai_hal_get_rec(&twai_context); + } status_info->msgs_to_tx = p_twai_obj->tx_msg_count; status_info->msgs_to_rx = p_twai_obj->rx_msg_count; status_info->tx_failed_count = p_twai_obj->tx_failed_count; diff --git a/components/hal/twai_hal.c b/components/hal/twai_hal.c index ee6163817e..001b62273c 100644 --- a/components/hal/twai_hal.c +++ b/components/hal/twai_hal.c @@ -70,6 +70,21 @@ void twai_hal_configure(twai_hal_context_t *hal_ctx, const twai_timing_config_t void twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode) { twai_ll_set_mode(hal_ctx->dev, mode); //Set operating mode + //Clear the TEC and REC + twai_ll_set_tec(hal_ctx->dev, 0); +#ifdef CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM + /* + Errata workaround: Prevent transmission of dominant error frame while in listen only mode by setting REC to 128 + before exiting reset mode. This forces the controller to be error passive (thus only transmits recessive bits). + The TEC/REC remain frozen in listen only mode thus ensuring we remain error passive. + */ + if (mode == TWAI_MODE_LISTEN_ONLY) { + twai_ll_set_rec(hal_ctx->dev, 128); + } else +#endif + { + twai_ll_set_rec(hal_ctx->dev, 0); + } (void) twai_ll_get_and_clear_intrs(hal_ctx->dev); //Clear any latched interrupts TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RUNNING); twai_ll_exit_reset_mode(hal_ctx->dev);