Skip to content

Commit f523943

Browse files
committed
Merge branch 'feat/twai_driver_add_programming_guide_v5.5' into 'release/v5.5'
feat(driver_twai): new driver add programming guide (v5.5) See merge request espressif/esp-idf!39679
2 parents fc71a86 + 7914e75 commit f523943

File tree

25 files changed

+834
-1164
lines changed

25 files changed

+834
-1164
lines changed

components/driver/twai/twai.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,13 @@ static void twai_intr_handler_main(void *arg)
245245

246246
//Handle events that only require alerting (i.e. no handler)
247247
if (events & TWAI_HAL_EVENT_BUS_OFF) {
248+
twai_ll_set_mode(p_twai_obj->hal->dev, true, false, false); //Freeze TEC/REC by entering LOM
248249
p_twai_obj->state = TWAI_STATE_BUS_OFF;
249250
twai_alert_handler(p_twai_obj, TWAI_ALERT_BUS_OFF, &alert_req);
250251
}
251252
if (events & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
253+
//Back to STOPPED state after recovered, for cautious engineering strategy
254+
twai_ll_enter_reset_mode(p_twai_obj->hal->dev);
252255
p_twai_obj->state = TWAI_STATE_STOPPED;
253256
twai_alert_handler(p_twai_obj, TWAI_ALERT_BUS_RECOVERED, &alert_req);
254257
}

components/esp_driver_twai/esp_twai_onchip.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ static void _node_isr_main(void *arg)
232232
if (twai_ctx->cbs.on_state_change) {
233233
do_yield |= twai_ctx->cbs.on_state_change(&twai_ctx->api_base, &e_data, twai_ctx->user_data);
234234
}
235+
// node recover from busoff, restart remain tx transaction
236+
if ((e_data.old_sta == TWAI_ERROR_BUS_OFF) && (e_data.new_sta == TWAI_ERROR_ACTIVE)) {
237+
if (xQueueReceiveFromISR(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx, &do_yield)) {
238+
atomic_store(&twai_ctx->hw_busy, true);
239+
_node_start_trans(twai_ctx);
240+
} else {
241+
atomic_store(&twai_ctx->hw_busy, false);
242+
}
243+
}
235244
}
236245

237246
// deal RX event, then TX later, TODO: DIG-620
@@ -261,9 +270,9 @@ static void _node_isr_main(void *arg)
261270

262271
// deal TX event
263272
if (events & TWAI_HAL_EVENT_TX_BUFF_FREE) {
264-
// only call tx_done_cb when tx without error, otherwise on_error_cb should triggered if it is registered
265-
if (twai_ctx->cbs.on_tx_done && (events & TWAI_HAL_EVENT_TX_SUCCESS)) {
273+
if (twai_ctx->cbs.on_tx_done) {
266274
twai_tx_done_event_data_t tx_ev = {
275+
.is_tx_success = (events & TWAI_HAL_EVENT_TX_SUCCESS), // find 'on_error_cb' if not success
267276
.done_tx_frame = twai_ctx->p_curr_tx,
268277
};
269278
do_yield |= twai_ctx->cbs.on_tx_done(&twai_ctx->api_base, &tx_ev, twai_ctx->user_data);
@@ -478,6 +487,9 @@ static esp_err_t _node_config_mask_filter(twai_node_handle_t node, uint8_t filte
478487
twai_onchip_ctx_t *twai_ctx = __containerof(node, twai_onchip_ctx_t, api_base);
479488
ESP_RETURN_ON_FALSE(filter_id < SOC_TWAI_MASK_FILTER_NUM, ESP_ERR_INVALID_ARG, TAG, "Invalid mask filter id %d", filter_id);
480489
ESP_RETURN_ON_FALSE(mask_cfg->num_of_ids <= 1, ESP_ERR_INVALID_ARG, TAG, "Invalid num_of_ids");
490+
uint32_t id = mask_cfg->num_of_ids ? mask_cfg->id_list[0] : mask_cfg->id;
491+
bool full_close = (mask_cfg->mask == UINT32_MAX) && (id == UINT32_MAX);
492+
ESP_RETURN_ON_FALSE(full_close || mask_cfg->dual_filter || mask_cfg->is_ext || !((mask_cfg->mask | id) & ~TWAI_STD_ID_MASK), ESP_ERR_INVALID_ARG, TAG, "std_id only (is_ext=0) but valid id/mask larger than 11 bits");
481493
#if SOC_TWAI_SUPPORT_FD
482494
// FD targets don't support Dual filter
483495
ESP_RETURN_ON_FALSE(!mask_cfg->dual_filter, ESP_ERR_NOT_SUPPORTED, TAG, "The target don't support Dual Filter");
@@ -493,6 +505,8 @@ static esp_err_t _node_config_range_filter(twai_node_handle_t node, uint8_t filt
493505
{
494506
twai_onchip_ctx_t *twai_ctx = __containerof(node, twai_onchip_ctx_t, api_base);
495507
ESP_RETURN_ON_FALSE(filter_id < SOC_TWAI_RANGE_FILTER_NUM, ESP_ERR_INVALID_ARG, TAG, "Invalid range filter id %d", filter_id);
508+
ESP_RETURN_ON_FALSE((range_cfg->range_low > range_cfg->range_high) || range_cfg->is_ext || !(range_cfg->range_high & ~TWAI_STD_ID_MASK), \
509+
ESP_ERR_INVALID_ARG, TAG, "std_id only (is_ext=0) but valid low/high id larger than 11 bits");
496510
ESP_RETURN_ON_FALSE(atomic_load(&twai_ctx->state) == TWAI_ERROR_BUS_OFF, ESP_ERR_INVALID_STATE, TAG, "config filter must when node stopped");
497511

498512
twai_hal_configure_range_filter(twai_ctx->hal, filter_id, range_cfg);

components/esp_driver_twai/include/esp_twai_onchip.h

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,6 @@
1313
extern "C" {
1414
#endif
1515

16-
/**
17-
* @brief Helper function to configure a dual 16-bit acceptance filter.
18-
* @note For 29bits Extended IDs, ONLY high 16bits id/mask is used for eache filter.
19-
*
20-
* @param id1 First ID to filter.
21-
* @param mask1 Mask for first ID.
22-
* @param id2 Second ID to filter.
23-
* @param mask2 Mask for second ID.
24-
* @param is_ext True if using Extended (29-bit) IDs, false for Standard (11-bit) IDs.
25-
* @return twai_mask_filter_config_t A filled filter configuration structure for dual filtering.
26-
*/
27-
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)
28-
{
29-
/**
30-
* Dual filter is a special mode in hardware,
31-
* which allow split general 32bits filter register to 2 unit of 16 bits id/mask pairs then using as 2 filter
32-
* below code do bit shifting to reach hardware requirement in this mode, for detail please refer to `Dual Filter Mode` of TRM
33-
*
34-
* 31 16 15 0
35-
* ▼ ▼ ▼ ▼
36-
* xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
37-
* ◄─11 bits─► ◄─11 bits─►
38-
* std filter 2 std filter 1
39-
* ─────────────────────────────────
40-
* ◄───16─bits────► ◄───16─bits────►
41-
* ext filter 2 etx filter 1
42-
*/
43-
twai_mask_filter_config_t dual_cfg = {
44-
.id = is_ext ? (((id1 & TWAI_EXT_ID_MASK) >> 13) << 16) | ((id2 & TWAI_EXT_ID_MASK) >> 13) : \
45-
((id1 & TWAI_STD_ID_MASK) << 21) | ((id2 & TWAI_STD_ID_MASK) << 5),
46-
.mask = is_ext ? (((mask1 & TWAI_EXT_ID_MASK) >> 13) << 16) | ((mask2 & TWAI_EXT_ID_MASK) >> 13) : \
47-
((mask1 & TWAI_STD_ID_MASK) << 21) | ((mask2 & TWAI_STD_ID_MASK) << 5),
48-
.is_ext = is_ext,
49-
.dual_filter = true,
50-
};
51-
return dual_cfg;
52-
}
53-
5416
/**
5517
* @brief TWAI on-chip node initialization configuration structure
5618
*/
@@ -72,7 +34,7 @@ typedef struct {
7234
uint32_t enable_loopback: 1; /**< The TWAI controller receive back frames what it send out */
7335
uint32_t enable_listen_only: 1; /**< The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages */
7436
uint32_t no_receive_rtr: 1; /**< Don't receive remote frames */
75-
} flags;
37+
} flags; /**< Misc configuration flags */
7638
} twai_onchip_node_config_t;
7739

7840
/**
@@ -91,6 +53,44 @@ typedef struct {
9153
*/
9254
esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twai_node_handle_t *node_ret);
9355

56+
/**
57+
* @brief Helper function to configure a dual 16-bit acceptance filter.
58+
* @note For 29bits Extended IDs, ONLY high 16bits id/mask is used for eache filter.
59+
*
60+
* @param id1 First ID to filter.
61+
* @param mask1 Mask for first ID.
62+
* @param id2 Second ID to filter.
63+
* @param mask2 Mask for second ID.
64+
* @param is_ext True if using Extended (29-bit) IDs, false for Standard (11-bit) IDs.
65+
* @return twai_mask_filter_config_t A filled filter configuration structure for dual filtering.
66+
*/
67+
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)
68+
{
69+
/**
70+
* Dual filter is a special mode in hardware,
71+
* which allow split general 32bits filter register to 2 unit of 16 bits id/mask pairs then using as 2 filter
72+
* below code do bit shifting to reach hardware requirement in this mode, for detail please refer to `Dual Filter Mode` of TRM
73+
*
74+
* 31 16 15 0
75+
* ▼ ▼ ▼ ▼
76+
* xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
77+
* ◄─11 bits─► ◄─11 bits─►
78+
* std filter 2 std filter 1
79+
* ─────────────────────────────────
80+
* ◄───16─bits────► ◄───16─bits────►
81+
* ext filter 2 etx filter 1
82+
*/
83+
twai_mask_filter_config_t dual_cfg = {
84+
.id = is_ext ? (((id1 & TWAI_EXT_ID_MASK) >> 13) << 16) | ((id2 & TWAI_EXT_ID_MASK) >> 13) : \
85+
((id1 & TWAI_STD_ID_MASK) << 21) | ((id2 & TWAI_STD_ID_MASK) << 5),
86+
.mask = is_ext ? (((mask1 & TWAI_EXT_ID_MASK) >> 13) << 16) | ((mask2 & TWAI_EXT_ID_MASK) >> 13) : \
87+
((mask1 & TWAI_STD_ID_MASK) << 21) | ((mask2 & TWAI_STD_ID_MASK) << 5),
88+
.is_ext = is_ext,
89+
.dual_filter = true,
90+
};
91+
return dual_cfg;
92+
}
93+
9494
#ifdef __cplusplus
9595
}
9696
#endif

components/esp_driver_twai/include/esp_twai_types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ typedef struct {
2929
/**
3030
* @brief TWAI transaction frame param type
3131
*/
32-
typedef struct twai_frame_t {
32+
typedef struct {
3333
twai_frame_header_t header; /**< message attribute/metadata, exclude data buffer*/
3434
uint8_t *buffer; /**< buffer address for tx and rx message data*/
3535
size_t buffer_len; /**< buffer length of provided data buffer pointer, in bytes.*/
@@ -57,6 +57,7 @@ typedef struct {
5757
* @brief TWAI "TX done" event data
5858
*/
5959
typedef struct {
60+
bool is_tx_success; /**< Indicate if frame send successful, refer `on_error` callback for fail reason if send failed */
6061
const twai_frame_t *done_tx_frame; /**< Pointer to the frame that has been transmitted */
6162
} twai_tx_done_event_data_t;
6263

components/hal/include/hal/twai_types.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ extern "C" {
1717
#endif
1818

1919
/* valid bits in TWAI ID for frame formats */
20-
#define TWAI_STD_ID_MASK 0x000007FFU /* Mask of the ID fields in a standard frame */
21-
#define TWAI_EXT_ID_MASK 0x1FFFFFFFU /* Mask of the ID fields in an extended frame */
20+
#define TWAI_STD_ID_MASK 0x000007FFU /**< Mask of the ID fields in a standard frame */
21+
#define TWAI_EXT_ID_MASK 0x1FFFFFFFU /**< Mask of the ID fields in an extended frame */
2222

2323
/* TWAI payload length and DLC definitions */
2424
#define TWAI_FRAME_MAX_DLC 8
@@ -32,10 +32,10 @@ extern "C" {
3232
* @brief TWAI node error fsm states
3333
*/
3434
typedef enum {
35-
TWAI_ERROR_ACTIVE, /**< Error active state: TEC/REC < 96 */
36-
TWAI_ERROR_WARNING, /**< Error warning state: TEC/REC >= 96 and < 128 */
37-
TWAI_ERROR_PASSIVE, /**< Error passive state: TEC/REC >= 128 and < 256 */
38-
TWAI_ERROR_BUS_OFF, /**< Bus-off state: TEC >= 256 (node offline) */
35+
TWAI_ERROR_ACTIVE, /**< Error active state: TEC/REC < 96 */
36+
TWAI_ERROR_WARNING, /**< Error warning state: TEC/REC >= 96 and < 128 */
37+
TWAI_ERROR_PASSIVE, /**< Error passive state: TEC/REC >= 128 and < 256 */
38+
TWAI_ERROR_BUS_OFF, /**< Bus-off state: TEC >= 256 (node offline) */
3939
} twai_error_state_t;
4040

4141
/**

components/hal/twai_hal_sja1000.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ static inline uint32_t twai_hal_decode_interrupt(twai_hal_context_t *hal_ctx)
216216
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_ERROR_WARNING);
217217
TWAI_HAL_SET_BITS(state_flags, TWAI_HAL_STATE_FLAG_ERR_WARN);
218218
} else if (hal_ctx->state_flags & TWAI_HAL_STATE_FLAG_RECOVERING) {
219-
//Previously undergoing bus recovery. Thus means bus recovery complete
220-
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BUS_RECOV_CPLT);
219+
//Previously undergoing bus recovery. Thus means bus recovery complete, hardware back to error_active
220+
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BUS_RECOV_CPLT | TWAI_HAL_EVENT_ERROR_ACTIVE);
221221
TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_RECOVERING | TWAI_HAL_STATE_FLAG_BUS_OFF);
222222
} else { //Just went below EWL
223223
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BELOW_EWL);
@@ -269,17 +269,13 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
269269

270270
//Handle low latency events
271271
if (events & TWAI_HAL_EVENT_BUS_OFF) {
272-
twai_ll_set_mode(hal_ctx->dev, true, false, false); //Freeze TEC/REC by entering LOM
273272
#ifdef CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC
274273
//Errata workaround: Force REC to 0 by re-triggering bus-off (by setting TEC to 0 then 255)
275274
twai_ll_set_tec(hal_ctx->dev, 0);
276275
twai_ll_set_tec(hal_ctx->dev, 255);
277276
(void) twai_ll_get_and_clear_intrs(hal_ctx->dev); //Clear the re-triggered bus-off interrupt
278277
#endif
279278
}
280-
if (events & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
281-
twai_ll_enter_reset_mode(hal_ctx->dev); //Enter reset mode to stop the controller
282-
}
283279
if (events & TWAI_HAL_EVENT_BUS_ERR) {
284280
twai_ll_err_type_t type;
285281
twai_ll_err_dir_t dir;

docs/_static/diagrams/twai/acceptance_filter_dual.diag

Lines changed: 0 additions & 19 deletions
This file was deleted.

docs/_static/diagrams/twai/acceptance_filter_single.diag

Lines changed: 0 additions & 21 deletions
This file was deleted.

docs/_static/diagrams/twai/base_flow.drawio.svg

Lines changed: 4 additions & 0 deletions
Loading

docs/_static/diagrams/twai/bit_timing.diag

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)