Skip to content

Commit 25cd10c

Browse files
committed
Merge branch 'feat/c5_twaifd_new_driver_c5_only' into 'master'
feat(driver_twai): c5 twaifd new driver (part_1, c5 only) Closes IDF-8691 and IDF-8692 See merge request espressif/esp-idf!37271
2 parents 5423825 + 9bdd5e3 commit 25cd10c

File tree

31 files changed

+1953
-135
lines changed

31 files changed

+1953
-135
lines changed

components/driver/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
8181
endif()
8282

8383
# TWAI related source files
84-
if(CONFIG_SOC_TWAI_SUPPORTED)
84+
# TWAIFD is not supported by the legacy driver
85+
if(CONFIG_SOC_TWAI_SUPPORTED AND NOT CONFIG_SOC_TWAI_SUPPORT_FD)
8586
list(APPEND srcs "twai/twai.c")
86-
8787
list(APPEND ldfragments "twai/linker.lf")
8888
endif()
8989

components/driver/test_apps/.build-test-rules.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ components/driver/test_apps/touch_sensor_v2:
8282

8383
components/driver/test_apps/twai:
8484
disable:
85-
- if: SOC_TWAI_SUPPORTED != 1
85+
- if: SOC_TWAI_SUPPORTED != 1 or SOC_TWAI_SUPPORT_FD == 1
86+
reason: legacy driver doesn't support FD
8687
depends_filepatterns:
8788
- components/driver/twai/**/*
8889
depends_components:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
idf_build_get_property(target IDF_TARGET)
2+
3+
if(${target} STREQUAL "linux")
4+
return() # This component is not supported by the POSIX/Linux simulator
5+
endif()
6+
7+
set(srcs "esp_twai.c")
8+
set(public_include "include")
9+
set(priv_req esp_driver_gpio esp_pm)
10+
11+
# Currently support only FD targets
12+
if(CONFIG_SOC_TWAI_SUPPORT_FD)
13+
list(APPEND srcs "onchip/esp_twai_onchip.c")
14+
list(APPEND public_include "onchip/include")
15+
endif()
16+
17+
idf_component_register(
18+
SRCS ${srcs}
19+
INCLUDE_DIRS ${public_include}
20+
PRIV_REQUIRES ${priv_req}
21+
LDFRAGMENTS "linker.lf"
22+
)

components/esp_driver_twai/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
menu "ESP-Driver:TWAI Configurations"
2+
depends on SOC_TWAI_SUPPORTED
3+
4+
config TWAI_ISR_INTO_IRAM
5+
bool "Place TWAI ISR in IRAM to reduce latency"
6+
default n
7+
help
8+
Place ISR functions to IRAM to increase performance
9+
10+
config TWAI_ISR_CACHE_SAFE
11+
bool "Allow TWAI ISR to execute when cache is disabled"
12+
select TWAI_ISR_INTO_IRAM
13+
default n
14+
help
15+
Allow TWAI works under Cache disabled, to enabled this config,
16+
all callbacks and user_ctx should also place in IRAM
17+
18+
endmenu # TWAI Configuration
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <sys/param.h>
8+
#include "esp_check.h"
9+
#include "esp_twai.h"
10+
#include "esp_private/twai_interface.h"
11+
#include "esp_private/twai_priv.h"
12+
13+
static const char *TAG = "esp_twai";
14+
15+
/**
16+
* @brief Calculate twai timing param by giving bitrate and hardware limit.
17+
*
18+
* +---------------------------------------------------+
19+
* | bit time in time quanta (total_tq) |
20+
* +--------------+----------+------------+------------+
21+
* | sync_seg | prop_seg | phase_seg1 | phase_seg2 |
22+
* +--------------+----------+------------+------------+
23+
* | 1 | tseg1 | tseg2 |
24+
* +--------------+----------+------------+------------+
25+
* | tseg2/2 ^ ^
26+
* sjw sample_point
27+
*/
28+
uint32_t twai_node_timing_calc_param(const uint32_t source_freq, const twai_timing_basic_config_t *in_param, const twai_timing_constraint_t *hw_limit, twai_timing_advanced_config_t *out_param)
29+
{
30+
uint32_t total_div = (source_freq + in_param->bitrate / 2) / in_param->bitrate;
31+
uint32_t pre_div = hw_limit->brp_min;
32+
uint16_t tseg = 0;
33+
for (; pre_div <= hw_limit->brp_max; pre_div ++) {
34+
tseg = total_div / pre_div;
35+
if (total_div != tseg * pre_div) {
36+
continue; // no integer tseg
37+
}
38+
if ((tseg < (hw_limit->tseg1_max + hw_limit->tseg2_max)) && (tseg >= (hw_limit->tseg1_min + hw_limit->tseg2_min))) {
39+
break;
40+
}
41+
}
42+
if (pre_div > hw_limit->brp_max) { // no valid pre_div
43+
return 0;
44+
}
45+
46+
uint16_t default_point = (in_param->bitrate >= 800000) ? 750 : ((in_param->bitrate >= 500000) ? 800 : 875);
47+
uint16_t sample_point = in_param->sample_point ? in_param->sample_point : default_point; // default sample point based on bitrate if not configured
48+
uint16_t tseg_1 = (tseg * sample_point) / 1000;
49+
tseg_1 = MAX(hw_limit->tseg1_min, MIN(tseg_1, hw_limit->tseg1_max));
50+
uint16_t tseg_2 = tseg - tseg_1 - 1;
51+
tseg_2 = MAX(hw_limit->tseg2_min, MIN(tseg_2, hw_limit->tseg2_max));
52+
tseg_1 = tseg - tseg_2 - 1;
53+
uint16_t prop = tseg_1 / 2; // distribute tseg1 evenly between prop_seg and tseg_1
54+
tseg_1 -= prop;
55+
56+
out_param->quanta_resolution_hz = 0; // going to deprecated IDF-12725
57+
out_param->brp = pre_div;
58+
out_param->prop_seg = prop;
59+
out_param->tseg_1 = tseg_1;
60+
out_param->tseg_2 = tseg_2;
61+
out_param->sjw = MAX(1, MIN(tseg_2 >> 1, hw_limit->sjw_max));
62+
out_param->ssp_offset = (tseg * in_param->ssp_permill) / 1000; // ssp is optional, default 0 if not configured
63+
64+
return source_freq / (pre_div * (prop + tseg_1 + tseg_2 + 1));
65+
}
66+
67+
esp_err_t twai_node_enable(twai_node_handle_t node)
68+
{
69+
ESP_RETURN_ON_FALSE(node, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null handle");
70+
ESP_RETURN_ON_FALSE(node->enable, ESP_ERR_NOT_SUPPORTED, TAG, "enable func null");
71+
72+
return node->enable(node);
73+
}
74+
75+
esp_err_t twai_node_disable(twai_node_handle_t node)
76+
{
77+
ESP_RETURN_ON_FALSE(node, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null handle");
78+
ESP_RETURN_ON_FALSE(node->disable, ESP_ERR_NOT_SUPPORTED, TAG, "disable func null");
79+
80+
return node->disable(node);
81+
}
82+
83+
esp_err_t twai_node_delete(twai_node_handle_t node)
84+
{
85+
ESP_RETURN_ON_FALSE(node, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null handle");
86+
ESP_RETURN_ON_FALSE(node->del, ESP_ERR_NOT_SUPPORTED, TAG, "delete func null");
87+
88+
return node->del(node);
89+
}
90+
91+
esp_err_t twai_node_config_mask_filter(twai_node_handle_t node, uint8_t filter_id, const twai_mask_filter_config_t *mask_cfg)
92+
{
93+
ESP_RETURN_ON_FALSE(node && mask_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null");
94+
ESP_RETURN_ON_FALSE(node->config_mask_filter, ESP_ERR_NOT_SUPPORTED, TAG, "config_mask_filter func null");
95+
96+
return node->config_mask_filter(node, filter_id, mask_cfg);
97+
}
98+
99+
esp_err_t twai_node_config_range_filter(twai_node_handle_t node, uint8_t filter_id, const twai_range_filter_config_t *range_cfg)
100+
{
101+
ESP_RETURN_ON_FALSE(node && range_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null");
102+
ESP_RETURN_ON_FALSE(node->config_range_filter, ESP_ERR_NOT_SUPPORTED, TAG, "config_range_filter func null");
103+
104+
return node->config_range_filter(node, filter_id, range_cfg);
105+
}
106+
107+
esp_err_t twai_node_reconfig_timing(twai_node_handle_t node, const twai_timing_advanced_config_t *bit_timing, const twai_timing_advanced_config_t *data_timing)
108+
{
109+
ESP_RETURN_ON_FALSE(node && (bit_timing || data_timing), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null");
110+
ESP_RETURN_ON_FALSE(node->timing_reconfig, ESP_ERR_NOT_SUPPORTED, TAG, "timing_reconfig func null");
111+
112+
return node->timing_reconfig(node, bit_timing, data_timing);
113+
}
114+
115+
esp_err_t twai_node_register_event_callbacks(twai_node_handle_t node, const twai_event_callbacks_t *cbs, void *user_data)
116+
{
117+
ESP_RETURN_ON_FALSE(node && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null");
118+
ESP_RETURN_ON_FALSE(node->register_cbs, ESP_ERR_NOT_SUPPORTED, TAG, "register_cbs func null");
119+
120+
return node->register_cbs(node, cbs, user_data);
121+
}
122+
123+
esp_err_t twai_node_recover(twai_node_handle_t node)
124+
{
125+
ESP_RETURN_ON_FALSE(node, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null handle");
126+
ESP_RETURN_ON_FALSE(node->recover, ESP_ERR_NOT_SUPPORTED, TAG, "recover func null");
127+
128+
return node->recover(node);
129+
}
130+
131+
esp_err_t twai_node_get_info(twai_node_handle_t node, twai_node_status_t *status_ret, twai_node_record_t *statistics_ret)
132+
{
133+
ESP_RETURN_ON_FALSE(node, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null handle");
134+
ESP_RETURN_ON_FALSE(node->get_info, ESP_ERR_NOT_SUPPORTED, TAG, "get_info func null");
135+
136+
return node->get_info(node, status_ret, statistics_ret);
137+
}
138+
139+
esp_err_t twai_node_transmit(twai_node_handle_t node, const twai_frame_t *frame, int timeout_ms)
140+
{
141+
ESP_RETURN_ON_FALSE(node && frame, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null");
142+
ESP_RETURN_ON_FALSE(node->transmit, ESP_ERR_NOT_SUPPORTED, TAG, "transmit func null");
143+
144+
return node->transmit(node, frame, timeout_ms);
145+
}
146+
147+
esp_err_t twai_node_receive_from_isr(twai_node_handle_t node, twai_frame_header_t *header, uint8_t *rx_buffer, size_t buf_sz, size_t *received_len)
148+
{
149+
ESP_RETURN_ON_FALSE_ISR(node && header, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null");
150+
ESP_RETURN_ON_FALSE_ISR(node->receive_isr, ESP_ERR_NOT_SUPPORTED, TAG, "receive func null");
151+
152+
return node->receive_isr(node, header, rx_buffer, buf_sz, received_len);
153+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#pragma once
7+
8+
#include <stdbool.h>
9+
#include "esp_err.h"
10+
#include "esp_twai_types.h"
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
/**
17+
* @brief ESP TWAI driver API set definition
18+
*/
19+
struct twai_node_base {
20+
/**
21+
* @brief Enable the TWAI node
22+
*
23+
* @param[in] node Pointer to the TWAI node base
24+
* @return esp_err_t
25+
* - ESP_OK: Success
26+
* - ESP_FAIL: Failed to enable the node
27+
*/
28+
esp_err_t (*enable)(struct twai_node_base *node);
29+
30+
/**
31+
* @brief Disable the TWAI node
32+
*
33+
* @param[in] node Pointer to the TWAI node base
34+
* @return esp_err_t
35+
* - ESP_OK: Success
36+
* - ESP_FAIL: Failed to disable the node
37+
*/
38+
esp_err_t (*disable)(struct twai_node_base *node);
39+
40+
/**
41+
* @brief Delete the TWAI node and free its resources
42+
*
43+
* @param[in] node Pointer to the TWAI node base
44+
* @return esp_err_t
45+
* - ESP_OK: Success
46+
* - ESP_FAIL: Failed to delete the node
47+
*/
48+
esp_err_t (*del)(struct twai_node_base *node);
49+
50+
/**
51+
* @brief Configure the mask filter of the TWAI node
52+
*
53+
* @param node Pointer to the TWAI node base
54+
* @param filter_id Index of the filter to configure
55+
* @param mask_cfg Pointer to the mask filter configuration
56+
* @return ESP_OK on success, error code otherwise
57+
*/
58+
esp_err_t (*config_mask_filter)(struct twai_node_base *node, uint8_t filter_id, const twai_mask_filter_config_t *mask_cfg);
59+
60+
/**
61+
* @brief Configure the range filter of the TWAI node
62+
*
63+
* @param node Pointer to the TWAI node base
64+
* @param filter_id Index of the filter to configure
65+
* @param range_cfg Pointer to the range filter configuration
66+
* @return ESP_OK on success, error code otherwise
67+
*/
68+
esp_err_t (*config_range_filter)(struct twai_node_base *node, uint8_t filter_id, const twai_range_filter_config_t *range_cfg);
69+
70+
/**
71+
* @brief Reconfigure the timing parameters for the TWAI node
72+
*
73+
* @param[in] node Pointer to the TWAI node base
74+
* @param bit_timing Pointer to new twai cc(classic) or arbitration phase of twai fd timing configuration
75+
* @param data_timing Pointer to new twai fd timing configuration
76+
* @return esp_err_t
77+
* - ESP_OK: Success
78+
* - ESP_ERR_INVALID_ARG: Invalid timing configuration
79+
*/
80+
esp_err_t (*timing_reconfig)(struct twai_node_base *node, const twai_timing_advanced_config_t *bit_timing, const twai_timing_advanced_config_t *data_timing);
81+
82+
/**
83+
* @brief Transmit a TWAI frame through the TWAI node
84+
*
85+
* @param[in] node Pointer to the TWAI node base
86+
* @param[in] frame Pointer to the frame to transmit
87+
* @param[in] timeout Timeout in milliseconds
88+
* @return esp_err_t
89+
* - ESP_OK: Success
90+
* - ESP_FAIL: Failed to transmit frame
91+
*/
92+
esp_err_t (*transmit)(struct twai_node_base *node, const twai_frame_t *frame, int timeout);
93+
94+
/**
95+
* @brief Receive a TWAI frame through the ISR callback
96+
*
97+
* @param[in] node Pointer to the TWAI node base
98+
* @param[out] header Where to store frame header
99+
* @param[out] rx_buffer Where to store frame data
100+
* @param[in] buf_sz Bytes length of rx_buffer
101+
* @param[out] received_len Optional, the real data length of rx frame comes from 'header->dlc'
102+
* @return esp_err_t
103+
* - ESP_OK: Success
104+
* - ESP_ERR_TIMEOUT: Reception timeout
105+
*/
106+
esp_err_t (*receive_isr)(struct twai_node_base *node, twai_frame_header_t *header, uint8_t *rx_buffer, size_t buf_sz, size_t *received_len);
107+
108+
/**
109+
* @brief Recover the TWAI node from a bus-off state
110+
*
111+
* @param[in] node Pointer to the TWAI node base
112+
* @return esp_err_t
113+
* - ESP_OK: Success
114+
* - ESP_FAIL: Failed to recover node
115+
*/
116+
esp_err_t (*recover)(struct twai_node_base *node);
117+
118+
/**
119+
* @brief Register event callbacks for the TWAI node
120+
*
121+
* @param[in] node Pointer to the TWAI node base
122+
* @param[in] cbs Pointer to the event callback configuration
123+
* @param[in] user_data User data to pass to the callbacks
124+
* @return esp_err_t
125+
* - ESP_OK: Success
126+
* - ESP_ERR_INVALID_ARG: Invalid callback configuration
127+
*/
128+
esp_err_t (*register_cbs)(struct twai_node_base *node, const twai_event_callbacks_t *cbs, void *user_data);
129+
130+
/**
131+
* @brief Get the status and statistics of the TWAI node
132+
*
133+
* @param[in] node Pointer to the TWAI node base
134+
* @param[out] status_ret Pointer to return the node status
135+
* @param[out] record_ret Pointer to return the node statistics
136+
* @return esp_err_t
137+
* - ESP_OK: Success
138+
* - ESP_FAIL: Failed to retrieve information
139+
*/
140+
esp_err_t (*get_info)(struct twai_node_base *node, twai_node_status_t *status_ret, twai_node_record_t *record_ret);
141+
};
142+
143+
#ifdef __cplusplus
144+
}
145+
#endif

0 commit comments

Comments
 (0)