From 7e7f0c5e14e561a255202b78eee3e54df921eb08 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 21 Aug 2025 16:13:29 +0800 Subject: [PATCH] fix(twai): twai legacy driver fixed zero dlc transmit Closes https://github.com/espressif/esp-idf/issues/17467 --- .../legacy_twai/main/test_twai_loop_back.c | 22 ++++--- components/driver/twai/twai.c | 2 +- components/esp_driver_twai/esp_twai_onchip.c | 3 +- .../test_twai/main/test_twai_common.cpp | 61 +++++++++++++++++++ 4 files changed, 76 insertions(+), 12 deletions(-) diff --git a/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c b/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c index c4d4fa2de7..8f2fe4e109 100644 --- a/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c +++ b/components/driver/test_apps/legacy_twai/main/test_twai_loop_back.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -68,19 +68,21 @@ TEST_CASE("twai_mode_std_no_ack_25kbps", "[twai-loop-back]") twai_message_t tx_msg = { .identifier = 0x123, - .data_length_code = 8, .data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, .self = true, // Transmitted message will also received by the same node }; - printf("transmit message\r\n"); - TEST_ESP_OK(twai_transmit(&tx_msg, pdMS_TO_TICKS(1000))); + for (int len = 0; len <= 8; len++) { + tx_msg.data_length_code = len; + printf("TX id %lx len %d\r\n", tx_msg.identifier, tx_msg.data_length_code); + TEST_ESP_OK(twai_transmit(&tx_msg, pdMS_TO_TICKS(1000))); - printf("receive message\r\n"); - twai_message_t rx_msg; - TEST_ESP_OK(twai_receive(&rx_msg, pdMS_TO_TICKS(1000))); - TEST_ASSERT_TRUE(rx_msg.data_length_code == 8); - for (int i = 0; i < 8; i++) { - TEST_ASSERT_EQUAL(tx_msg.data[i], rx_msg.data[i]); + twai_message_t rx_msg = {}; + TEST_ESP_OK(twai_receive(&rx_msg, pdMS_TO_TICKS(1000))); + printf("RX id %lx len %d\r\n", rx_msg.identifier, rx_msg.data_length_code); + TEST_ASSERT_EQUAL(rx_msg.data_length_code, tx_msg.data_length_code); + for (int i = 0; i < rx_msg.data_length_code; i++) { + TEST_ASSERT_EQUAL(tx_msg.data[i], rx_msg.data[i]); + } } TEST_ESP_OK(twai_stop()); diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index 9ccbc7510e..ce23be6b89 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -738,7 +738,7 @@ esp_err_t twai_transmit_v2(twai_handle_t handle, const twai_message_t *message, .frame = { .header = &header, .buffer = (uint8_t *)message->data, - .buffer_len = TWAI_FRAME_MAX_LEN, + .buffer_len = message->data_length_code, }, .config.retry_cnt = message->ss ? 0 : -1, .config.loopback = message->self, diff --git a/components/esp_driver_twai/esp_twai_onchip.c b/components/esp_driver_twai/esp_twai_onchip.c index 9674230bf4..fa3407fe8b 100644 --- a/components/esp_driver_twai/esp_twai_onchip.c +++ b/components/esp_driver_twai/esp_twai_onchip.c @@ -587,7 +587,8 @@ static esp_err_t _node_queue_tx(twai_node_handle_t node, const twai_frame_t *fra #if !SOC_TWAI_SUPPORT_FD ESP_RETURN_ON_FALSE_ISR(!frame->header.fdf || frame->buffer_len <= TWAI_FRAME_MAX_LEN, ESP_ERR_INVALID_ARG, TAG, "fdf flag or buffer_len not supported"); #endif - ESP_RETURN_ON_FALSE_ISR(frame->buffer_len <= (frame->header.fdf ? TWAIFD_FRAME_MAX_LEN : TWAI_FRAME_MAX_LEN), ESP_ERR_INVALID_ARG, TAG, "illegal transfer length (buffer_len %ld)", frame->buffer_len); + ESP_RETURN_ON_FALSE_ISR((frame->header.dlc <= TWAIFD_FRAME_MAX_DLC) && \ + (frame->buffer_len <= (frame->header.fdf ? TWAIFD_FRAME_MAX_LEN : TWAI_FRAME_MAX_LEN)), ESP_ERR_INVALID_ARG, TAG, "illegal transfer length (buffer_len %ld)", frame->buffer_len); ESP_RETURN_ON_FALSE_ISR((!frame->header.brs) || (twai_ctx->valid_fd_timing), ESP_ERR_INVALID_ARG, TAG, "brs can't be used without config data_timing"); ESP_RETURN_ON_FALSE_ISR(!twai_ctx->hal->enable_listen_only, ESP_ERR_NOT_SUPPORTED, TAG, "node is config as listen only"); ESP_RETURN_ON_FALSE_ISR(atomic_load(&twai_ctx->state) != TWAI_ERROR_BUS_OFF, ESP_ERR_INVALID_STATE, TAG, "node is bus off"); diff --git a/components/esp_driver_twai/test_apps/test_twai/main/test_twai_common.cpp b/components/esp_driver_twai/test_apps/test_twai/main/test_twai_common.cpp index f9faa08136..85b83260af 100644 --- a/components/esp_driver_twai/test_apps/test_twai/main/test_twai_common.cpp +++ b/components/esp_driver_twai/test_apps/test_twai/main/test_twai_common.cpp @@ -714,3 +714,64 @@ TEST_CASE("twai send from ISR context (loopback)", "[twai]") printf("ISR send test passed!\n"); } + +static IRAM_ATTR bool test_dlc_range_cb(twai_node_handle_t handle, const twai_rx_done_event_data_t *edata, void *user_ctx) +{ + twai_frame_t *rx_frame = (twai_frame_t *)user_ctx; + if (ESP_OK == twai_node_receive_from_isr(handle, rx_frame)) { + esp_rom_printf(DRAM_STR("RX len %d %s\n"), rx_frame->header.dlc, rx_frame->buffer); + } + return false; +} + +TEST_CASE("twai dlc range test", "[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.bit_timing.bitrate = 800000; + node_config.tx_queue_depth = TEST_FRAME_NUM; + node_config.flags.enable_loopback = true; + node_config.flags.enable_self_test = true; + + TEST_ESP_OK(twai_new_node_onchip(&node_config, &node_hdl)); + + uint8_t rx_buffer[TWAI_FRAME_MAX_LEN] = {0}; + twai_frame_t rx_frame = {}; + rx_frame.buffer = rx_buffer; + rx_frame.buffer_len = sizeof(rx_buffer); + + twai_event_callbacks_t user_cbs = {}; + user_cbs.on_rx_done = test_dlc_range_cb; + TEST_ESP_OK(twai_node_register_event_callbacks(node_hdl, &user_cbs, &rx_frame)); + TEST_ESP_OK(twai_node_enable(node_hdl)); + + twai_frame_t tx_frame = {}; + tx_frame.header.id = TWAI_STD_ID_MASK; + tx_frame.buffer = (uint8_t *)"hi esp32"; + for (int len = 0; len < 2 * 9; len++) { // [0:8] is 9 times + if (len < 9) { + tx_frame.buffer_len = len; + tx_frame.header.dlc = 0; + } else { + tx_frame.buffer_len = 0; + tx_frame.header.dlc = len % 9; + } + TEST_ESP_OK(twai_node_transmit(node_hdl, &tx_frame, 100)); + TEST_ESP_OK(twai_node_transmit_wait_all_done(node_hdl, -1)); + TEST_ASSERT_EQUAL(len % 9, rx_frame.header.dlc); + memset(rx_buffer, 0, sizeof(rx_buffer)); + } + + tx_frame.buffer_len = 9; + tx_frame.header.dlc = 0; + TEST_ESP_ERR(twai_node_transmit(node_hdl, &tx_frame, 0), ESP_ERR_INVALID_ARG); + + tx_frame.buffer_len = 0; + tx_frame.header.dlc = TWAIFD_FRAME_MAX_DLC + 1; + TEST_ESP_ERR(twai_node_transmit(node_hdl, &tx_frame, 0), ESP_ERR_INVALID_ARG); + + TEST_ESP_OK(twai_node_disable(node_hdl)); + TEST_ESP_OK(twai_node_delete(node_hdl)); +}