Select one of the symbols to view example projects that use it.
 
Outline
#include <stddef.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_compiler.h"
#include "hal/twai_hal.h"
#define TWAI_RX_FIFO_CORRUPT_THRESH
twai_hal_decode_interrupt(twai_hal_context_t *)
twai_hal_get_events(twai_hal_context_t *)
twai_hal_prepare_for_reset(twai_hal_context_t *)
twai_hal_recover_from_reset(twai_hal_context_t *)
twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *, twai_hal_frame_t *)
Files
loading (3/5)...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/hal/twai_hal_iram.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */ #include <stddef.h> #include <string.h> #include "sdkconfig.h" #include "esp_compiler.h" #include "hal/twai_hal.h"5 includes #ifdef CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT //Errata condition occurs at 64 messages. Threshold set to 62 to prevent the chance of failing to detect errata condition. #define TWAI_RX_FIFO_CORRUPT_THRESH 62/* ... */ #endif /* ----------------------------- Event Handling ----------------------------- */ /** * Helper functions that can decode what events have been triggered based on * the values of the interrupt, status, TEC and REC registers. The HAL context's * state flags are also updated based on the events that have triggered. *//* ... */ static inline uint32_t twai_hal_decode_interrupt(twai_hal_context_t *hal_ctx) { uint32_t events = 0; uint32_t interrupts = twai_ll_get_and_clear_intrs(hal_ctx->dev); uint32_t status = twai_ll_get_status(hal_ctx->dev); uint32_t tec = twai_ll_get_tec(hal_ctx->dev); uint32_t rec = twai_ll_get_rec(hal_ctx->dev); uint32_t state_flags = hal_ctx->state_flags; //Error Warning Interrupt set whenever Error or Bus Status bit changes if (interrupts & TWAI_LL_INTR_EI) { if (status & TWAI_LL_STATUS_BS) { //Currently in BUS OFF state if (status & TWAI_LL_STATUS_ES) { //EWL is exceeded, thus must have entered BUS OFF TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BUS_OFF); TWAI_HAL_SET_BITS(state_flags, TWAI_HAL_STATE_FLAG_BUS_OFF); //Any TX would have been halted by entering bus off. Reset its flag TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_RUNNING | TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED); }{...} else { //Below EWL. Therefore TEC is counting down in bus recovery TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BUS_RECOV_PROGRESS); }{...} }{...} else { //Not in BUS OFF if (status & TWAI_LL_STATUS_ES) { //Just Exceeded EWL TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_ABOVE_EWL); TWAI_HAL_SET_BITS(state_flags, TWAI_HAL_STATE_FLAG_ERR_WARN); }{...} else if (hal_ctx->state_flags & TWAI_HAL_STATE_FLAG_RECOVERING) { //Previously undergoing bus recovery. Thus means bus recovery complete TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BUS_RECOV_CPLT); TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_RECOVERING | TWAI_HAL_STATE_FLAG_BUS_OFF); }{...} else { //Just went below EWL TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BELOW_EWL); TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_ERR_WARN); }{...} }{...} }{...} //Receive Interrupt set whenever RX FIFO is not empty if (interrupts & TWAI_LL_INTR_RI) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_RX_BUFF_FRAME); }{...} //Transmit interrupt set whenever TX buffer becomes free #ifdef CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST if ((interrupts & TWAI_LL_INTR_TI || hal_ctx->state_flags & TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED) && status & TWAI_LL_STATUS_TBS) { #else if (interrupts & TWAI_LL_INTR_TI) { #endif TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_TX_BUFF_FREE); TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED); }{...} //Error Passive Interrupt on transition from error active to passive or vice versa if (interrupts & TWAI_LL_INTR_EPI) { if (tec >= TWAI_ERR_PASS_THRESH || rec >= TWAI_ERR_PASS_THRESH) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_ERROR_PASSIVE); TWAI_HAL_SET_BITS(state_flags, TWAI_HAL_STATE_FLAG_ERR_PASSIVE); }{...} else { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_ERROR_ACTIVE); TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_ERR_PASSIVE); }{...} }{...} //Bus error interrupt triggered on a bus error (e.g. bit, ACK, stuff etc) if (interrupts & TWAI_LL_INTR_BEI) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_BUS_ERR); }{...} //Arbitration Lost Interrupt triggered on losing arbitration if (interrupts & TWAI_LL_INTR_ALI) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_ARB_LOST); }{...} hal_ctx->state_flags = state_flags; return events; }{ ... } uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) { uint32_t events = twai_hal_decode_interrupt(hal_ctx); //Handle low latency events if (events & TWAI_HAL_EVENT_BUS_OFF) { twai_ll_set_mode(hal_ctx->dev, TWAI_MODE_LISTEN_ONLY); //Freeze TEC/REC by entering LOM #ifdef CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC //Errata workaround: Force REC to 0 by re-triggering bus-off (by setting TEC to 0 then 255) twai_ll_set_tec(hal_ctx->dev, 0); twai_ll_set_tec(hal_ctx->dev, 255); (void) twai_ll_get_and_clear_intrs(hal_ctx->dev); //Clear the re-triggered bus-off interrupt/* ... */ #endif }{...} if (events & TWAI_HAL_EVENT_BUS_RECOV_CPLT) { twai_ll_enter_reset_mode(hal_ctx->dev); //Enter reset mode to stop the controller }{...} if (events & TWAI_HAL_EVENT_BUS_ERR) { #ifdef CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID twai_ll_err_type_t type; twai_ll_err_dir_t dir; twai_ll_err_seg_t seg; twai_ll_parse_err_code_cap(hal_ctx->dev, &type, &dir, &seg); //Decode error interrupt //Check for errata condition (RX message has bus error at particular segments) if (dir == TWAI_LL_ERR_DIR_RX && ((seg == TWAI_LL_ERR_SEG_DATA || seg == TWAI_LL_ERR_SEG_CRC_SEQ) || (seg == TWAI_LL_ERR_SEG_ACK_DELIM && type == TWAI_LL_ERR_OTHER))) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_NEED_PERIPH_RESET); }{...} /* ... */#endif twai_ll_clear_err_code_cap(hal_ctx->dev); }{...} if (events & TWAI_HAL_EVENT_ARB_LOST) { twai_ll_clear_arb_lost_cap(hal_ctx->dev); }{...} #ifdef CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT //Check for errata condition (rx_msg_count >= corruption_threshold) if (events & TWAI_HAL_EVENT_RX_BUFF_FRAME && twai_ll_get_rx_msg_count(hal_ctx->dev) >= TWAI_RX_FIFO_CORRUPT_THRESH) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_NEED_PERIPH_RESET); }{...} #endif/* ... */ #if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { //A peripheral reset will invalidate an RX event; TWAI_HAL_CLEAR_BITS(events, (TWAI_HAL_EVENT_RX_BUFF_FRAME)); }{...} #endif/* ... */ return events; }{ ... } #if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) void twai_hal_prepare_for_reset(twai_hal_context_t *hal_ctx) { uint32_t status = twai_ll_get_status(hal_ctx->dev); if (!(status & TWAI_LL_STATUS_TBS)) { //Transmit buffer is NOT free, indicating an Ongoing TX will be cancelled by the HW reset TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_NEED_RETRY); //Note: Even if the TX completes right after this, we still consider it will be retried. //Worst case the same message will get sent twice. }{...} //Some register must saved before entering reset mode hal_ctx->rx_msg_cnt_save = (uint8_t) twai_ll_get_rx_msg_count(hal_ctx->dev); twai_ll_enter_reset_mode(hal_ctx->dev); //Enter reset mode to stop the controller twai_ll_save_reg(hal_ctx->dev, &hal_ctx->reg_save); //Save remaining registers after entering reset mode }{ ... } void twai_hal_recover_from_reset(twai_hal_context_t *hal_ctx) { twai_ll_enter_reset_mode(hal_ctx->dev); twai_ll_enable_extended_reg_layout(hal_ctx->dev); twai_ll_restore_reg(hal_ctx->dev, &hal_ctx->reg_save); twai_ll_exit_reset_mode(hal_ctx->dev); (void) twai_ll_get_and_clear_intrs(hal_ctx->dev); if (hal_ctx->state_flags & TWAI_HAL_STATE_FLAG_TX_NEED_RETRY) { //HW reset has cancelled a TX. Re-transmit here twai_hal_set_tx_buffer_and_transmit(hal_ctx, &hal_ctx->tx_frame_save); TWAI_HAL_CLEAR_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_NEED_RETRY); }{...} }{ ... } #endif/* ... */ //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_frame_t *tx_frame) { //Copy frame into tx buffer twai_ll_set_tx_buffer(hal_ctx->dev, tx_frame); //Hit the send command if (tx_frame->self_reception) { if (tx_frame->single_shot) { twai_ll_set_cmd_self_rx_single_shot(hal_ctx->dev); }{...} else { twai_ll_set_cmd_self_rx_request(hal_ctx->dev); }{...} }{...} else if (tx_frame->single_shot){ twai_ll_set_cmd_tx_single_shot(hal_ctx->dev); }{...} else { twai_ll_set_cmd_tx(hal_ctx->dev); }{...} TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED); #if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) if (&hal_ctx->tx_frame_save == tx_frame) { return; }{...} //Save transmitted frame in case we need to retry ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-overlapping-buffers") // TODO IDF-11085 memcpy(&hal_ctx->tx_frame_save, tx_frame, sizeof(twai_hal_frame_t)); ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-overlapping-buffers")/* ... */ #endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) }{ ... }
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.