fix: Make TWAI init non-fatal + add recovery backoff

TWAI init now logs error and sets g_twai_bus_off instead of panicking.
Bus-off recovery loop increased from 100ms to 1000ms to prevent
watchdog reset when no CAN transceiver is connected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sebastien Vayrette 2026-04-20 13:56:11 -04:00
parent affaefea3a
commit 2622696772

View File

@ -35,19 +35,25 @@ void vesc_can_init(void)
(gpio_num_t)VESC_CAN_RX_GPIO, (gpio_num_t)VESC_CAN_RX_GPIO,
TWAI_MODE_NORMAL); TWAI_MODE_NORMAL);
gcfg.rx_queue_len = VESC_CAN_RX_QUEUE; gcfg.rx_queue_len = VESC_CAN_RX_QUEUE;
gcfg.tx_queue_len = 5;
twai_timing_config_t tcfg = TWAI_TIMING_CONFIG_500KBITS(); twai_timing_config_t tcfg = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t fcfg = TWAI_FILTER_CONFIG_ACCEPT_ALL(); twai_filter_config_t fcfg = TWAI_FILTER_CONFIG_ACCEPT_ALL();
gcfg.tx_queue_len = 5;
ESP_LOGI(TAG, "TWAI: installing driver tx=%d rx=%d 500kbps", VESC_CAN_TX_GPIO, VESC_CAN_RX_GPIO); ESP_LOGI(TAG, "TWAI: installing driver tx=%d rx=%d 500kbps", VESC_CAN_TX_GPIO, VESC_CAN_RX_GPIO);
ESP_ERROR_CHECK(twai_driver_install(&gcfg, &tcfg, &fcfg)); esp_err_t err = twai_driver_install(&gcfg, &tcfg, &fcfg);
ESP_LOGI(TAG, "TWAI: driver installed OK"); if (err != ESP_OK) {
ESP_LOGE(TAG, "TWAI install failed (0x%x) — CAN disabled", err);
g_twai_bus_off = true;
return;
}
ESP_ERROR_CHECK(twai_start()); err = twai_start();
/* Wait for VESC to join the bus before drive_task begins TX — prevents if (err != ESP_OK) {
* immediate TEC runup and BUS_OFF if VESC CAN isn't ready at ESP32 boot. */ ESP_LOGE(TAG, "TWAI start failed (0x%x) — CAN disabled", err);
g_twai_bus_off = true;
return;
}
vTaskDelay(pdMS_TO_TICKS(200)); vTaskDelay(pdMS_TO_TICKS(200));
ESP_LOGI(TAG, "TWAI: started OK — bus active"); ESP_LOGI(TAG, "TWAI: started OK — bus active");
} }
@ -94,17 +100,15 @@ void vesc_can_rx_task(void *arg)
ESP_LOGE(TAG, "TWAI BUS OFF tx_err=%lu rx_err=%lu — recovering", ESP_LOGE(TAG, "TWAI BUS OFF tx_err=%lu rx_err=%lu — recovering",
(unsigned long)si.tx_error_counter, (unsigned long)si.rx_error_counter); (unsigned long)si.tx_error_counter, (unsigned long)si.rx_error_counter);
twai_initiate_recovery(); twai_initiate_recovery();
/* Driver auto-transitions RECOVERING→STOPPED after 128 recessive vTaskDelay(pdMS_TO_TICKS(1000));
* bit occurrences (~3 ms min at 500kbps); 100 ms is safe headroom. */
vTaskDelay(pdMS_TO_TICKS(100));
} else if (si.state == TWAI_STATE_STOPPED) { } else if (si.state == TWAI_STATE_STOPPED) {
/* Recovery completed — restart the driver. */
esp_err_t serr = twai_start(); esp_err_t serr = twai_start();
if (serr == ESP_OK) { if (serr == ESP_OK) {
g_twai_bus_off = false; g_twai_bus_off = false;
ESP_LOGI(TAG, "TWAI recovered — bus active"); ESP_LOGI(TAG, "TWAI recovered — bus active");
} else { } else {
ESP_LOGE(TAG, "TWAI restart failed 0x%x", serr); ESP_LOGE(TAG, "TWAI restart failed 0x%x — backing off", serr);
vTaskDelay(pdMS_TO_TICKS(2000));
} }
} }
/* TWAI_STATE_RECOVERING: initiation already called, just wait. */ /* TWAI_STATE_RECOVERING: initiation already called, just wait. */