mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(driver_twai): fixed TWAI arbitration lost event handling
Merges https://github.com/espressif/esp-idf/pull/18100
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "esp_twai_onchip.h"
|
||||
#include "hal/twai_periph.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "driver/uart.h" // for baudrate detection
|
||||
|
||||
#define TEST_TX_GPIO GPIO_NUM_4
|
||||
@@ -575,6 +576,55 @@ TEST_CASE("twai bus off recovery (loopback)", "[twai]")
|
||||
TEST_ESP_OK(twai_node_delete(node_hdl));
|
||||
}
|
||||
|
||||
static IRAM_ATTR bool test_arb_error_cb(twai_node_handle_t handle, const twai_error_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
esp_rom_printf("bus error: 0x%lx\n", edata->err_flags.val);
|
||||
// only arb lost or stuff err is expected, stuff_err comes from RX section after arb lost
|
||||
// test using loopback mode, arb_lost -> switch to RX -> no one is sending -> can't receive new waves -> stuff err
|
||||
TEST_ASSERT(edata->err_flags.arb_lost || edata->err_flags.stuff_err);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CASE("test arb lost and stuff err", "[twai]")
|
||||
{
|
||||
twai_node_handle_t node_hdl;
|
||||
twai_onchip_node_config_t node_config = {};
|
||||
node_config.io_cfg.tx = TEST_TX_GPIO;
|
||||
node_config.io_cfg.rx = TEST_TX_GPIO; // Using same pin for test without transceiver
|
||||
node_config.io_cfg.quanta_clk_out = GPIO_NUM_NC;
|
||||
node_config.io_cfg.bus_off_indicator = GPIO_NUM_NC;
|
||||
node_config.bit_timing.bitrate = 50000; //slow bitrate to ensure soft error trigger
|
||||
node_config.tx_queue_depth = 1;
|
||||
node_config.flags.enable_self_test = true;
|
||||
TEST_ESP_OK(twai_new_node_onchip(&node_config, &node_hdl));
|
||||
|
||||
twai_event_callbacks_t user_cbs = {};
|
||||
user_cbs.on_error = test_arb_error_cb;
|
||||
TEST_ESP_OK(twai_node_register_event_callbacks(node_hdl, &user_cbs, NULL));
|
||||
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||
|
||||
twai_node_status_t node_status = {};
|
||||
twai_frame_t tx_frame = {};
|
||||
tx_frame.header.id = 0x7F0; // send high id range to easier trigger arb lost
|
||||
gpio_set_level(TEST_TX_GPIO, 0);
|
||||
while (node_status.state != TWAI_ERROR_BUS_OFF && (tx_frame.header.id > 0x7F0 - 10)) {
|
||||
printf("sending frame %lx last tec %d rec %d\n", tx_frame.header.id --, node_status.tx_error_count, node_status.rx_error_count);
|
||||
TEST_ESP_OK(twai_node_transmit(node_hdl, &tx_frame, 500));
|
||||
if (tx_frame.header.id < 0x7F0 - 2) { // trigger error after 2 frames
|
||||
printf("trigger arb lost now!\n");
|
||||
esp_rom_delay_us(5 * (1000000 / node_config.bit_timing.bitrate)); // trigger error at 30 bits after frame start
|
||||
gpio_matrix_output(TEST_TX_GPIO, SIG_GPIO_OUT_IDX, false, false);
|
||||
esp_rom_delay_us(2 * (1000000 / node_config.bit_timing.bitrate)); // trigger error for 2 bits
|
||||
gpio_matrix_output(TEST_TX_GPIO, twai_periph_signals[0].tx_sig, false, false);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // some time for hardware report errors
|
||||
twai_node_get_info(node_hdl, &node_status, NULL);
|
||||
}
|
||||
|
||||
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||
TEST_ESP_OK(twai_node_delete(node_hdl));
|
||||
}
|
||||
|
||||
static void test_send_wait_task(void *args)
|
||||
{
|
||||
const char *task_name = pcTaskGetName(NULL);
|
||||
|
||||
@@ -280,7 +280,9 @@ twai_error_state_t twai_hal_get_err_state(twai_hal_context_t *hal_ctx);
|
||||
__attribute__((always_inline))
|
||||
static inline twai_error_flags_t twai_hal_get_err_flags(twai_hal_context_t *hal_ctx)
|
||||
{
|
||||
return hal_ctx->errors;
|
||||
twai_error_flags_t error_flags = hal_ctx->errors;
|
||||
hal_ctx->errors.val = 0; // clear ctx for next errors
|
||||
return error_flags;
|
||||
}
|
||||
|
||||
/* ------------------------------- TX and RX -------------------------------- */
|
||||
|
||||
@@ -276,13 +276,10 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
|
||||
twai_ll_err_dir_t dir;
|
||||
twai_ll_err_seg_t seg;
|
||||
twai_ll_parse_err_code_cap(hal_ctx->dev, &type, &dir, &seg); //Decode error interrupt
|
||||
twai_error_flags_t errors = {
|
||||
.bit_err = (type == TWAI_LL_ERR_BIT),
|
||||
.form_err = (type == TWAI_LL_ERR_FORM),
|
||||
.stuff_err = (type == TWAI_LL_ERR_STUFF),
|
||||
.ack_err = (type == TWAI_LL_ERR_OTHER) && (seg == TWAI_LL_ERR_SEG_ACK_SLOT),
|
||||
};
|
||||
hal_ctx->errors = errors;
|
||||
hal_ctx->errors.bit_err = (type == TWAI_LL_ERR_BIT);
|
||||
hal_ctx->errors.form_err = (type == TWAI_LL_ERR_FORM);
|
||||
hal_ctx->errors.stuff_err = (type == TWAI_LL_ERR_STUFF);
|
||||
hal_ctx->errors.ack_err = (type == TWAI_LL_ERR_OTHER) && (seg == TWAI_LL_ERR_SEG_ACK_SLOT);
|
||||
#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 &&
|
||||
@@ -293,6 +290,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
hal_ctx->errors.arb_lost = !!(events & TWAI_HAL_EVENT_ARB_LOST);
|
||||
if (events & TWAI_HAL_EVENT_ARB_LOST) {
|
||||
twai_ll_clear_arb_lost_cap(hal_ctx->dev);
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
|
||||
hal_ctx->errors = twaifd_ll_get_err_reason(hal_ctx->dev);
|
||||
hal_events |= TWAI_HAL_EVENT_BUS_ERR;
|
||||
}
|
||||
hal_ctx->errors.arb_lost = !!(int_stat & TWAIFD_LL_INTR_ARBIT_LOST);
|
||||
if (int_stat & TWAIFD_LL_INTR_ARBIT_LOST) {
|
||||
hal_events |= TWAI_HAL_EVENT_ARB_LOST;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user