Просмотр исходного кода

Merge branch 'bugfix/twai_listen_only_errata' into 'master'

TWAI: Add errata workaround for listen only mode

Closes IDFGH-7602

See merge request espressif/esp-idf!22479
Darian 3 лет назад
Родитель
Сommit
57b6be22a7
3 измененных файлов с 34 добавлено и 2 удалено
  1. 11 0
      components/driver/Kconfig
  2. 8 2
      components/driver/twai/twai.c
  3. 15 0
      components/hal/twai_hal.c

+ 11 - 0
components/driver/Kconfig

@@ -177,6 +177,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 y
+            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 "Temperature sensor Configuration"

+ 8 - 2
components/driver/twai/twai.c

@@ -725,8 +725,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;

+ 15 - 0
components/hal/twai_hal.c

@@ -83,6 +83,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);