mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(driver_twai): fixed fd data bitrate error on slow bitrate
This commit is contained in:
@@ -371,23 +371,12 @@ static esp_err_t _node_register_callbacks(twai_node_handle_t node, const twai_ev
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _node_check_timing_valid(twai_onchip_ctx_t *twai_ctx, const twai_timing_advanced_config_t *timing)
|
||||
{
|
||||
if (timing) {
|
||||
ESP_RETURN_ON_FALSE(twai_hal_check_brp_validation(twai_ctx->hal, timing->brp), ESP_ERR_INVALID_ARG, TAG, "invalid brp");
|
||||
ESP_RETURN_ON_FALSE((timing->tseg_1 >= TWAI_LL_TSEG1_MIN) && (timing->tseg_1 <= TWAI_LL_TSEG1_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid tseg1");
|
||||
ESP_RETURN_ON_FALSE((timing->tseg_2 >= TWAI_LL_TSEG2_MIN) && (timing->tseg_2 <= TWAI_LL_TSEG2_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid tseg_2");
|
||||
ESP_RETURN_ON_FALSE((timing->sjw >= 1) && (timing->sjw <= TWAI_LL_SJW_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid swj");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _node_set_bit_timing(twai_node_handle_t node, const twai_timing_advanced_config_t *timing, const twai_timing_advanced_config_t *timing_fd)
|
||||
{
|
||||
twai_onchip_ctx_t *twai_ctx = __containerof(node, twai_onchip_ctx_t, api_base);
|
||||
ESP_RETURN_ON_FALSE(atomic_load(&twai_ctx->state) == TWAI_ERROR_BUS_OFF, ESP_ERR_INVALID_STATE, TAG, "config timing must when node stopped");
|
||||
ESP_RETURN_ON_ERROR(_node_check_timing_valid(twai_ctx, timing), TAG, "invalid param");
|
||||
ESP_RETURN_ON_ERROR(_node_check_timing_valid(twai_ctx, timing_fd), TAG, "invalid fd param");
|
||||
ESP_RETURN_ON_FALSE(twai_hal_check_timing_valid(twai_ctx->hal, timing, false), ESP_ERR_INVALID_ARG, TAG, "invalid param");
|
||||
ESP_RETURN_ON_FALSE(twai_hal_check_timing_valid(twai_ctx->hal, timing_fd, true), ESP_ERR_INVALID_ARG, TAG, "invalid fd param");
|
||||
|
||||
if (timing) {
|
||||
twai_hal_configure_timing(twai_ctx->hal, timing);
|
||||
@@ -429,6 +418,10 @@ static esp_err_t _node_calc_set_bit_timing(twai_node_handle_t node, const twai_t
|
||||
#if SOC_TWAI_SUPPORT_FD
|
||||
twai_timing_advanced_config_t timing_adv_fd = {};
|
||||
if (timing_fd->bitrate) {
|
||||
hw_const.brp_max = TWAI_LL_BRP_MAX_FD;
|
||||
hw_const.tseg1_max = TWAI_LL_TSEG1_MAX_FD;
|
||||
hw_const.tseg2_max = TWAI_LL_TSEG2_MAX_FD;
|
||||
hw_const.sjw_max = TWAI_LL_SJW_MAX_FD;
|
||||
real_baud = twai_node_timing_calc_param(twai_ctx->src_freq_hz, timing_fd, &hw_const, &timing_adv_fd);
|
||||
ESP_LOGD(TAG, "timing_fd: src %ld brp %ld prop %d seg1 %d seg2 %d sjw %d ssp %d", twai_ctx->src_freq_hz, timing_adv_fd.brp, timing_adv_fd.prop_seg, timing_adv_fd.tseg_1, timing_adv_fd.tseg_2, timing_adv_fd.sjw, timing_adv_fd.ssp_offset);
|
||||
ESP_RETURN_ON_FALSE(real_baud, ESP_ERR_INVALID_ARG, TAG, "bitrate can't achieve!");
|
||||
|
||||
@@ -164,9 +164,9 @@ TEST_CASE("twai baudrate measurement", "[twai]")
|
||||
uint32_t source_freq = 0;
|
||||
for (size_t i = 0; i < sizeof(twai_available_clk_srcs) / sizeof(twai_available_clk_srcs[0]); i++) {
|
||||
TEST_ESP_OK(esp_clk_tree_src_get_freq_hz(twai_available_clk_srcs[i], ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &source_freq));
|
||||
printf("Test clock source %d frequency: %ld Hz\n", twai_available_clk_srcs[i], source_freq);
|
||||
test_twai_baudrate_correctness(twai_available_clk_srcs[i], 200000);
|
||||
printf("\nTest clock source %d frequency: %ld Hz\n", twai_available_clk_srcs[i], source_freq);
|
||||
|
||||
test_twai_baudrate_correctness(twai_available_clk_srcs[i], 200000);
|
||||
test_twai_baudrate_correctness(twai_available_clk_srcs[i], 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -161,8 +161,8 @@ TEST_CASE("twai fd transmit time (loopback)", "[twai]")
|
||||
};
|
||||
TEST_ESP_OK(twai_node_register_event_callbacks(node_hdl, &user_cbs, &rx_frame));
|
||||
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||
printf("%-12s %-14s %-14s %-7s %-15s %s\n", "pkg_len", "frame_len", "frame_num", "brs", "trans_time/ms", "result");
|
||||
printf("-------------------------------------------------------------------------\n");
|
||||
printf("%-12s %-14s %-14s %-7s %-15s %-15s %s\n", "pkg_len", "frame_len", "frame_num", "brs", "trans_time/ms", "predict/ms", "result");
|
||||
printf("-----------------------------------------------------------------------------------------\n");
|
||||
|
||||
uint64_t time1, time2;
|
||||
for (uint8_t test_mode = 0; test_mode < 3; test_mode ++) {
|
||||
@@ -184,22 +184,38 @@ TEST_CASE("twai fd transmit time (loopback)", "[twai]")
|
||||
TEST_ESP_OK(twai_node_transmit(node_hdl, &tx_msgs[tx_cnt], 1000));
|
||||
}
|
||||
|
||||
// roughly estimate frame time with fixed frame overhead, ignoring dynamic bit stuffing
|
||||
// 47: classic standard data frame overhead;
|
||||
// 70: FD standard data frame overhead with CRC21
|
||||
uint32_t arb_bits = frame_len * 8 + ((frame_len == 64) ? 70 : 47);
|
||||
uint32_t data_bits = 0;
|
||||
if (test_mode == 2) {
|
||||
// BRS roughly splits the frame into 30 arbitration bits and payload + 40 FD data phase bits
|
||||
arb_bits = 30;
|
||||
data_bits = frame_len * 8 + 40;
|
||||
}
|
||||
uint64_t predict_time_ms = (uint64_t)trans_num * arb_bits * 1000 / node_config.bit_timing.bitrate;
|
||||
predict_time_ms += (uint64_t)trans_num * data_bits * 1000 / node_config.data_timing.bitrate;
|
||||
predict_time_ms += (trans_num * 10) / 1000; // add about 10 us interrupt overhead per frame
|
||||
|
||||
//waiting pkg receive finish
|
||||
TEST_ESP_OK(twai_node_transmit_wait_all_done(node_hdl, -1));
|
||||
time2 = esp_timer_get_time();
|
||||
free(tx_msgs);
|
||||
|
||||
// check if pkg receive correct
|
||||
printf("%-12d %-14d %-14d %-7d %-15.2f %-s\n",
|
||||
printf("%-12d %-14d %-14d %-7d %-15.2f %-15llu %-s\n",
|
||||
TEST_TRANS_TIME_BUF_LEN,
|
||||
frame_len,
|
||||
trans_num,
|
||||
(test_mode == 2),
|
||||
(time2 - time1) / 1000.f,
|
||||
(unsigned long long)predict_time_ms,
|
||||
memcmp(recv_pkg_ptr, send_pkg_ptr, TEST_TRANS_TIME_BUF_LEN) ? "failed" : "ok");
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(send_pkg_ptr, recv_pkg_ptr, TEST_TRANS_TIME_BUF_LEN);
|
||||
TEST_ASSERT_LESS_THAN((predict_time_ms / 5), abs((int)((time2 - time1) / 1000 - predict_time_ms)));
|
||||
}
|
||||
printf("-------------------------------------------------------------------------\n");
|
||||
printf("-----------------------------------------------------------------------------------------\n");
|
||||
|
||||
free(send_pkg_ptr);
|
||||
free(recv_pkg_ptr);
|
||||
|
||||
Reference in New Issue
Block a user