|
12 | 12 | // See the License for the specific language governing permissions and
|
13 | 13 | // limitations under the License.
|
14 | 14 |
|
15 |
| -#include "soc/soc_caps.h" |
16 | 15 |
|
17 | 16 | #include "sdkconfig.h"
|
18 | 17 | #include "freertos/FreeRTOS.h"
|
|
28 | 27 | #include "driver/gpio.h"
|
29 | 28 | #include "driver/periph_ctrl.h"
|
30 | 29 | #include "driver/twai.h"
|
| 30 | +#include "soc/soc_caps.h" |
31 | 31 | #include "soc/twai_periph.h"
|
32 | 32 | #include "hal/twai_hal.h"
|
33 | 33 | #include "esp_rom_gpio.h"
|
@@ -69,6 +69,7 @@ typedef struct {
|
69 | 69 | twai_state_t state;
|
70 | 70 | twai_mode_t mode;
|
71 | 71 | uint32_t rx_missed_count;
|
| 72 | + uint32_t rx_overrun_count; |
72 | 73 | uint32_t tx_failed_count;
|
73 | 74 | uint32_t arb_lost_count;
|
74 | 75 | uint32_t bus_error_count;
|
@@ -128,19 +129,49 @@ TWAI_ISR_ATTR static void twai_alert_handler(uint32_t alert_code, int *alert_req
|
128 | 129 |
|
129 | 130 | static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *alert_req)
|
130 | 131 | {
|
| 132 | +#ifdef SOC_TWAI_SUPPORTS_RX_STATUS |
131 | 133 | uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context);
|
132 | 134 |
|
133 | 135 | for (uint32_t i = 0; i < msg_count; i++) {
|
134 | 136 | twai_hal_frame_t frame;
|
135 |
| - twai_hal_read_rx_buffer_and_clear(&twai_context, &frame); |
136 |
| - //Copy frame into RX Queue |
137 |
| - if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { |
138 |
| - p_twai_obj->rx_msg_count++; |
| 137 | + if (twai_hal_read_rx_buffer_and_clear(&twai_context, &frame)) { |
| 138 | + //Valid frame copied from RX buffer |
| 139 | + if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { |
| 140 | + p_twai_obj->rx_msg_count++; |
| 141 | + } else { //Failed to send to queue |
| 142 | + p_twai_obj->rx_missed_count++; |
| 143 | + twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); |
| 144 | + } |
| 145 | + } else { //Failed to read from RX buffer because message is overrun |
| 146 | + p_twai_obj->rx_overrun_count++; |
| 147 | + twai_alert_handler(TWAI_ALERT_RX_FIFO_OVERRUN, alert_req); |
| 148 | + } |
| 149 | + } |
| 150 | +#else //SOC_TWAI_SUPPORTS_RX_STATUS |
| 151 | + uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context); |
| 152 | + bool overrun = false; |
| 153 | + //Clear all valid RX frames |
| 154 | + for (int i = 0; i < msg_count; i++) { |
| 155 | + twai_hal_frame_t frame; |
| 156 | + if (twai_hal_read_rx_buffer_and_clear(&twai_context, &frame)) { |
| 157 | + //Valid frame copied from RX buffer |
| 158 | + if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { |
| 159 | + p_twai_obj->rx_msg_count++; |
| 160 | + } else { |
| 161 | + p_twai_obj->rx_missed_count++; |
| 162 | + twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); |
| 163 | + } |
139 | 164 | } else {
|
140 |
| - p_twai_obj->rx_missed_count++; |
141 |
| - twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); |
| 165 | + overrun = true; |
| 166 | + break; |
142 | 167 | }
|
143 | 168 | }
|
| 169 | + //All remaining frames are treated as overrun. Clear them all |
| 170 | + if (overrun) { |
| 171 | + p_twai_obj->rx_overrun_count += twai_hal_clear_rx_fifo_overrun(&twai_context); |
| 172 | + twai_alert_handler(TWAI_ALERT_RX_FIFO_OVERRUN, alert_req); |
| 173 | + } |
| 174 | +#endif //SOC_TWAI_SUPPORTS_RX_STATUS |
144 | 175 | }
|
145 | 176 |
|
146 | 177 | static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *alert_req)
|
@@ -176,56 +207,65 @@ TWAI_ISR_ATTR static void twai_intr_handler_main(void *arg)
|
176 | 207 | {
|
177 | 208 | BaseType_t task_woken = pdFALSE;
|
178 | 209 | int alert_req = 0;
|
179 |
| - uint32_t event; |
| 210 | + uint32_t events; |
180 | 211 | TWAI_ENTER_CRITICAL_ISR();
|
181 |
| - if (p_twai_obj == NULL) { //Incase intr occurs whilst driver is being uninstalled |
| 212 | + if (p_twai_obj == NULL) { //In case intr occurs whilst driver is being uninstalled |
182 | 213 | TWAI_EXIT_CRITICAL_ISR();
|
183 | 214 | return;
|
184 | 215 | }
|
185 |
| - event = twai_hal_decode_interrupt_events(&twai_context); |
186 |
| - if (event & TWAI_HAL_EVENT_RX_BUFF_FRAME) { |
| 216 | + events = twai_hal_get_events(&twai_context); //Get the events that triggered the interrupt |
| 217 | + |
| 218 | +#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) |
| 219 | + if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { |
| 220 | + twai_hal_prepare_for_reset(&twai_context); |
| 221 | + periph_module_reset(PERIPH_TWAI_MODULE); |
| 222 | + twai_hal_recover_from_reset(&twai_context); |
| 223 | + p_twai_obj->rx_missed_count += twai_hal_get_reset_lost_rx_cnt(&twai_context); |
| 224 | + twai_alert_handler(TWAI_ALERT_PERIPH_RESET, &alert_req); |
| 225 | + } |
| 226 | +#endif |
| 227 | + if (events & TWAI_HAL_EVENT_RX_BUFF_FRAME) { |
| 228 | + //Note: This event will never occur if there is a periph reset event |
187 | 229 | twai_handle_rx_buffer_frames(&task_woken, &alert_req);
|
188 | 230 | }
|
189 |
| - //TX command should be the last command related handler to be called, so that |
190 |
| - //other command register bits do not overwrite the TX command bit. |
191 |
| - if (event & TWAI_HAL_EVENT_TX_BUFF_FREE) { |
| 231 | + if (events & TWAI_HAL_EVENT_TX_BUFF_FREE) { |
192 | 232 | twai_handle_tx_buffer_frame(&task_woken, &alert_req);
|
193 | 233 | }
|
194 | 234 |
|
195 | 235 | //Handle events that only require alerting (i.e. no handler)
|
196 |
| - if (event & TWAI_HAL_EVENT_BUS_OFF) { |
| 236 | + if (events & TWAI_HAL_EVENT_BUS_OFF) { |
197 | 237 | p_twai_obj->state = TWAI_STATE_BUS_OFF;
|
198 | 238 | twai_alert_handler(TWAI_ALERT_BUS_OFF, &alert_req);
|
199 | 239 | }
|
200 |
| - if (event & TWAI_HAL_EVENT_BUS_RECOV_CPLT) { |
| 240 | + if (events & TWAI_HAL_EVENT_BUS_RECOV_CPLT) { |
201 | 241 | p_twai_obj->state = TWAI_STATE_STOPPED;
|
202 | 242 | twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, &alert_req);
|
203 | 243 | }
|
204 |
| - if (event & TWAI_HAL_EVENT_BUS_ERR) { |
| 244 | + if (events & TWAI_HAL_EVENT_BUS_ERR) { |
205 | 245 | p_twai_obj->bus_error_count++;
|
206 | 246 | twai_alert_handler(TWAI_ALERT_BUS_ERROR, &alert_req);
|
207 | 247 | }
|
208 |
| - if (event & TWAI_HAL_EVENT_ARB_LOST) { |
| 248 | + if (events & TWAI_HAL_EVENT_ARB_LOST) { |
209 | 249 | p_twai_obj->arb_lost_count++;
|
210 | 250 | twai_alert_handler(TWAI_ALERT_ARB_LOST, &alert_req);
|
211 | 251 | }
|
212 |
| - if (event & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) { |
| 252 | + if (events & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) { |
213 | 253 | //Bus-recovery in progress. TEC has dropped below error warning limit
|
214 | 254 | twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, &alert_req);
|
215 | 255 | }
|
216 |
| - if (event & TWAI_HAL_EVENT_ERROR_PASSIVE) { |
| 256 | + if (events & TWAI_HAL_EVENT_ERROR_PASSIVE) { |
217 | 257 | //Entered error passive
|
218 | 258 | twai_alert_handler(TWAI_ALERT_ERR_PASS, &alert_req);
|
219 | 259 | }
|
220 |
| - if (event & TWAI_HAL_EVENT_ERROR_ACTIVE) { |
| 260 | + if (events & TWAI_HAL_EVENT_ERROR_ACTIVE) { |
221 | 261 | //Returned to error active
|
222 | 262 | twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, &alert_req);
|
223 | 263 | }
|
224 |
| - if (event & TWAI_HAL_EVENT_ABOVE_EWL) { |
| 264 | + if (events & TWAI_HAL_EVENT_ABOVE_EWL) { |
225 | 265 | //TEC or REC surpassed error warning limit
|
226 | 266 | twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, &alert_req);
|
227 | 267 | }
|
228 |
| - if (event & TWAI_HAL_EVENT_BELOW_EWL) { |
| 268 | + if (events & TWAI_HAL_EVENT_BELOW_EWL) { |
229 | 269 | //TEC and REC are both below error warning
|
230 | 270 | twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, &alert_req);
|
231 | 271 | }
|
@@ -646,6 +686,7 @@ esp_err_t twai_get_status_info(twai_status_info_t *status_info)
|
646 | 686 | status_info->msgs_to_rx = p_twai_obj->rx_msg_count;
|
647 | 687 | status_info->tx_failed_count = p_twai_obj->tx_failed_count;
|
648 | 688 | status_info->rx_missed_count = p_twai_obj->rx_missed_count;
|
| 689 | + status_info->rx_overrun_count = p_twai_obj->rx_overrun_count; |
649 | 690 | status_info->arb_lost_count = p_twai_obj->arb_lost_count;
|
650 | 691 | status_info->bus_error_count = p_twai_obj->bus_error_count;
|
651 | 692 | status_info->state = p_twai_obj->state;
|
|
0 commit comments