mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 10:00:57 +02:00
fix(driver_twai): fixed dual_filter with extid, more accurate sample point
Closes https://github.com/espressif/esp-idf/issues/17504 Closes https://github.com/espressif/esp-idf/issues/17522
This commit is contained in:
@@ -43,12 +43,11 @@ uint32_t twai_node_timing_calc_param(const uint32_t source_freq, const twai_timi
|
|||||||
|
|
||||||
uint16_t default_point = (in_param->bitrate >= 800000) ? 750 : ((in_param->bitrate >= 500000) ? 800 : 875);
|
uint16_t default_point = (in_param->bitrate >= 800000) ? 750 : ((in_param->bitrate >= 500000) ? 800 : 875);
|
||||||
uint16_t sample_point = in_param->sp_permill ? in_param->sp_permill : default_point; // default sample point based on bitrate if not configured
|
uint16_t sample_point = in_param->sp_permill ? in_param->sp_permill : default_point; // default sample point based on bitrate if not configured
|
||||||
uint16_t tseg_1 = (tseg * sample_point) / 1000;
|
uint16_t tseg_1 = (tseg * sample_point) / 1000 - 1;
|
||||||
tseg_1 = MAX(hw_limit->tseg1_min, MIN(tseg_1, hw_limit->tseg1_max));
|
tseg_1 = MAX(hw_limit->tseg1_min, MIN(tseg_1, hw_limit->tseg1_max));
|
||||||
uint16_t tseg_2 = tseg - tseg_1 - 1;
|
uint16_t tseg_2 = tseg - tseg_1 - 1;
|
||||||
tseg_2 = MAX(hw_limit->tseg2_min, MIN(tseg_2, hw_limit->tseg2_max));
|
tseg_2 = MAX(hw_limit->tseg2_min, MIN(tseg_2, hw_limit->tseg2_max));
|
||||||
tseg_1 = tseg - tseg_2 - 1;
|
uint16_t prop = MAX(1, tseg_1 / 4); // prop_seg is usually shorter than tseg_1 and at least 1
|
||||||
uint16_t prop = tseg_1 / 2; // distribute tseg1 evenly between prop_seg and tseg_1
|
|
||||||
tseg_1 -= prop;
|
tseg_1 -= prop;
|
||||||
|
|
||||||
out_param->quanta_resolution_hz = 0; // going to deprecated IDF-12725
|
out_param->quanta_resolution_hz = 0; // going to deprecated IDF-12725
|
||||||
|
@@ -444,7 +444,7 @@ static esp_err_t _node_calc_set_bit_timing(twai_node_handle_t node, twai_clock_s
|
|||||||
.sjw_max = TWAI_LL_SJW_MAX,
|
.sjw_max = TWAI_LL_SJW_MAX,
|
||||||
};
|
};
|
||||||
uint32_t real_baud = twai_node_timing_calc_param(source_freq, timing, &hw_const, &timing_adv);
|
uint32_t real_baud = twai_node_timing_calc_param(source_freq, timing, &hw_const, &timing_adv);
|
||||||
ESP_LOGD(TAG, "norm src %ld, param %ld %d %d %d %d %d", source_freq, timing_adv.brp, timing_adv.prop_seg, timing_adv.tseg_1, timing_adv.tseg_2, timing_adv.sjw, timing_adv.ssp_offset);
|
ESP_LOGD(TAG, "timing: src %ld brp %ld prop %d seg1 %d seg2 %d sjw %d ssp %d", source_freq, timing_adv.brp, timing_adv.prop_seg, timing_adv.tseg_1, timing_adv.tseg_2, timing_adv.sjw, timing_adv.ssp_offset);
|
||||||
ESP_RETURN_ON_FALSE(real_baud, ESP_ERR_INVALID_ARG, TAG, "bitrate can't achieve!");
|
ESP_RETURN_ON_FALSE(real_baud, ESP_ERR_INVALID_ARG, TAG, "bitrate can't achieve!");
|
||||||
if (timing->bitrate != real_baud) {
|
if (timing->bitrate != real_baud) {
|
||||||
ESP_LOGW(TAG, "bitrate precision loss, adjust from %ld to %ld", timing->bitrate, real_baud);
|
ESP_LOGW(TAG, "bitrate precision loss, adjust from %ld to %ld", timing->bitrate, real_baud);
|
||||||
@@ -453,7 +453,7 @@ static esp_err_t _node_calc_set_bit_timing(twai_node_handle_t node, twai_clock_s
|
|||||||
twai_timing_advanced_config_t timing_adv_fd = { .clk_src = root_clock_src, };
|
twai_timing_advanced_config_t timing_adv_fd = { .clk_src = root_clock_src, };
|
||||||
if (timing_fd->bitrate) {
|
if (timing_fd->bitrate) {
|
||||||
real_baud = twai_node_timing_calc_param(source_freq, timing_fd, &hw_const, &timing_adv_fd);
|
real_baud = twai_node_timing_calc_param(source_freq, timing_fd, &hw_const, &timing_adv_fd);
|
||||||
ESP_LOGD(TAG, "fd src %ld, param %ld %d %d %d %d %d", source_freq, 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_LOGD(TAG, "timing_fd: src %ld brp %ld prop %d seg1 %d seg2 %d sjw %d ssp %d", source_freq, 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!");
|
ESP_RETURN_ON_FALSE(real_baud, ESP_ERR_INVALID_ARG, TAG, "bitrate can't achieve!");
|
||||||
if (timing_fd->bitrate != real_baud) {
|
if (timing_fd->bitrate != real_baud) {
|
||||||
ESP_LOGW(TAG, "bitrate precision loss, adjust from %ld to %ld", timing_fd->bitrate, real_baud);
|
ESP_LOGW(TAG, "bitrate precision loss, adjust from %ld to %ld", timing_fd->bitrate, real_baud);
|
||||||
|
@@ -57,14 +57,14 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
|||||||
* @brief Helper function to configure a dual 16-bit acceptance filter.
|
* @brief Helper function to configure a dual 16-bit acceptance filter.
|
||||||
* @note For 29bits Extended IDs, ONLY high 16bits id/mask is used for each filter.
|
* @note For 29bits Extended IDs, ONLY high 16bits id/mask is used for each filter.
|
||||||
*
|
*
|
||||||
* @param id1 First ID to filter.
|
* @param id1 First full 11/29 bits ID to filter.
|
||||||
* @param mask1 Mask for first ID.
|
* @param mask1 Mask for first ID.
|
||||||
* @param id2 Second ID to filter.
|
* @param id2 Second full 11/29 bits ID to filter.
|
||||||
* @param mask2 Mask for second ID.
|
* @param mask2 Mask for second ID.
|
||||||
* @param is_ext True if using Extended (29-bit) IDs, false for Standard (11-bit) IDs.
|
* @param is_ext True if using Extended (29-bit) IDs, false for Standard (11-bit) IDs.
|
||||||
* @return twai_mask_filter_config_t A filled filter configuration structure for dual filtering.
|
* @return twai_mask_filter_config_t A filled filter configuration structure for dual filtering.
|
||||||
*/
|
*/
|
||||||
static inline twai_mask_filter_config_t twai_make_dual_filter(uint16_t id1, uint16_t mask1, uint16_t id2, uint16_t mask2, bool is_ext)
|
static inline twai_mask_filter_config_t twai_make_dual_filter(uint32_t id1, uint32_t mask1, uint32_t id2, uint32_t mask2, bool is_ext)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Dual filter is a special mode in hardware,
|
* Dual filter is a special mode in hardware,
|
||||||
@@ -90,6 +90,10 @@ static inline twai_mask_filter_config_t twai_make_dual_filter(uint16_t id1, uint
|
|||||||
.no_fd = false,
|
.no_fd = false,
|
||||||
.dual_filter = true,
|
.dual_filter = true,
|
||||||
};
|
};
|
||||||
|
if ((id1 & mask1 & id2 & mask2) == 0xffffffff) {
|
||||||
|
dual_cfg.id = 0xffffffff; // recover the 'disable' code
|
||||||
|
dual_cfg.mask = 0xffffffff;
|
||||||
|
}
|
||||||
return dual_cfg;
|
return dual_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -246,7 +246,7 @@ static void test_random_trans_generator(twai_node_handle_t node_hdl, uint32_t tr
|
|||||||
|
|
||||||
printf("Sending %ld random trans ...\n", trans_num);
|
printf("Sending %ld random trans ...\n", trans_num);
|
||||||
for (uint32_t tx_cnt = 0; tx_cnt < trans_num; tx_cnt++) {
|
for (uint32_t tx_cnt = 0; tx_cnt < trans_num; tx_cnt++) {
|
||||||
tx_msg.header.id = tx_cnt | 0xf000;
|
tx_msg.header.id = tx_cnt | 0xf000 | (tx_cnt << 16);
|
||||||
tx_msg.header.ide = !!(tx_cnt % 2);
|
tx_msg.header.ide = !!(tx_cnt % 2);
|
||||||
tx_msg.header.rtr = !!(tx_cnt % 3);
|
tx_msg.header.rtr = !!(tx_cnt % 3);
|
||||||
tx_msg.buffer_len = tx_cnt % TWAI_FRAME_MAX_LEN;
|
tx_msg.buffer_len = tx_cnt % TWAI_FRAME_MAX_LEN;
|
||||||
@@ -350,13 +350,17 @@ static IRAM_ATTR bool test_dual_filter_rx_done_cb(twai_node_handle_t handle, con
|
|||||||
rx_frame.buffer_len = TWAI_FRAME_MAX_LEN;
|
rx_frame.buffer_len = TWAI_FRAME_MAX_LEN;
|
||||||
|
|
||||||
if (ESP_OK == twai_node_receive_from_isr(handle, &rx_frame)) {
|
if (ESP_OK == twai_node_receive_from_isr(handle, &rx_frame)) {
|
||||||
ESP_EARLY_LOGI("Recv", "RX id 0x%4x len %2d ext %d rmt %d", rx_frame.header.id, twaifd_dlc2len(rx_frame.header.dlc), rx_frame.header.ide, rx_frame.header.rtr);
|
ESP_EARLY_LOGI("Recv", "id 0x%8x len %2d ext %d rmt %d", rx_frame.header.id, twaifd_dlc2len(rx_frame.header.dlc), rx_frame.header.ide, rx_frame.header.rtr);
|
||||||
switch (test_ctrl[0]) {
|
switch (test_ctrl[0]) {
|
||||||
case 0: // receive something
|
case 0: // receive std id
|
||||||
TEST_ASSERT(!rx_frame.header.ide);
|
TEST_ASSERT(!rx_frame.header.ide);
|
||||||
TEST_ASSERT((rx_frame.header.id >= 0x10) && (rx_frame.header.id <= 0x2f));
|
TEST_ASSERT((rx_frame.header.id >= 0x10) && (rx_frame.header.id <= 0x2f));
|
||||||
break;
|
break;
|
||||||
case 1: break; // receive none
|
case 1: break; // receive none
|
||||||
|
case 2: // receive ext id
|
||||||
|
TEST_ASSERT(rx_frame.header.ide);
|
||||||
|
TEST_ASSERT((rx_frame.header.id >= 0x280000) || (rx_frame.header.id <= 0xfffff));
|
||||||
|
break;
|
||||||
default: TEST_ASSERT(false);
|
default: TEST_ASSERT(false);
|
||||||
}
|
}
|
||||||
test_ctrl[1] ++;
|
test_ctrl[1] ++;
|
||||||
@@ -384,7 +388,7 @@ TEST_CASE("twai dual 16bit mask filter (loopback)", "[twai]")
|
|||||||
user_cbs.on_rx_done = test_dual_filter_rx_done_cb;
|
user_cbs.on_rx_done = test_dual_filter_rx_done_cb;
|
||||||
TEST_ESP_OK(twai_node_register_event_callbacks(node_hdl, &user_cbs, test_ctrl));
|
TEST_ESP_OK(twai_node_register_event_callbacks(node_hdl, &user_cbs, test_ctrl));
|
||||||
|
|
||||||
printf("Testing dual filter: id1 0x%x mask1 0x%x, id2 0x%x mask2 0x%x\n", 0x020, 0x7f0, 0x013, 0x7f8);
|
printf("Testing dual filter: std id1 0x%x mask1 0x%x, id2 0x%x mask2 0x%x\n", 0x020, 0x7f0, 0x013, 0x7f8);
|
||||||
test_ctrl[0] = 0;
|
test_ctrl[0] = 0;
|
||||||
test_ctrl[1] = 0;
|
test_ctrl[1] = 0;
|
||||||
// filter 1 receive only std id 0x02x
|
// filter 1 receive only std id 0x02x
|
||||||
@@ -395,17 +399,31 @@ TEST_CASE("twai dual 16bit mask filter (loopback)", "[twai]")
|
|||||||
test_random_trans_generator(node_hdl, 50);
|
test_random_trans_generator(node_hdl, 50);
|
||||||
TEST_ASSERT_EQUAL(12, test_ctrl[1]); // must receive 12 of 50 frames under filter config
|
TEST_ASSERT_EQUAL(12, test_ctrl[1]); // must receive 12 of 50 frames under filter config
|
||||||
|
|
||||||
printf("Disable filter\n");
|
dual_config = twai_make_dual_filter(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, false);
|
||||||
|
printf("Testing disable filter by dual_maker, result: id %lx mask %lx\n", dual_config.id, dual_config.mask);
|
||||||
|
TEST_ASSERT_EQUAL(0xffffffff, dual_config.id & dual_config.mask);
|
||||||
|
|
||||||
|
printf("Testing disable filter\n");
|
||||||
test_ctrl[0] = 1;
|
test_ctrl[0] = 1;
|
||||||
test_ctrl[1] = 0;
|
test_ctrl[1] = 0;
|
||||||
dual_config.id = 0xFFFFFFFF;
|
|
||||||
dual_config.mask = 0xFFFFFFFF;
|
|
||||||
TEST_ESP_OK(twai_node_disable(node_hdl));
|
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||||
TEST_ESP_OK(twai_node_config_mask_filter(node_hdl, 0, &dual_config));
|
TEST_ESP_OK(twai_node_config_mask_filter(node_hdl, 0, &dual_config));
|
||||||
TEST_ESP_OK(twai_node_enable(node_hdl));
|
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||||
test_random_trans_generator(node_hdl, 40);
|
test_random_trans_generator(node_hdl, 40);
|
||||||
TEST_ASSERT_EQUAL(0, test_ctrl[1]);
|
TEST_ASSERT_EQUAL(0, test_ctrl[1]);
|
||||||
|
|
||||||
|
printf("Testing dual filter: ext id1 0x%x mask1 0x%x, id2 0x%x mask2 0x%x\n", 0x0280000, 0x1ff80000, 0x0000000, 0x1ff00000);
|
||||||
|
test_ctrl[0] = 2;
|
||||||
|
test_ctrl[1] = 0;
|
||||||
|
// filter 1 receive only ext id 0x028xxxxx~0x02fxxxxx
|
||||||
|
// filter 2 receive only ext id 0x000xxxxx
|
||||||
|
dual_config = twai_make_dual_filter(0x0280000, 0x1ff80000, 0x0000000, 0x1ff00000, true);
|
||||||
|
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||||
|
TEST_ESP_OK(twai_node_config_mask_filter(node_hdl, 0, &dual_config));
|
||||||
|
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||||
|
test_random_trans_generator(node_hdl, 50);
|
||||||
|
TEST_ASSERT_EQUAL(12, test_ctrl[1]); // must receive 12 of 50 frames
|
||||||
|
|
||||||
TEST_ESP_OK(twai_node_disable(node_hdl));
|
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||||
TEST_ESP_OK(twai_node_delete(node_hdl));
|
TEST_ESP_OK(twai_node_delete(node_hdl));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user