Ver código fonte

Merge branch 'refactor/twai_hal_state' into 'master'

Refactor TWAI HAL to store state information

Closes IDF-1633

See merge request espressif/esp-idf!9789
Michael (XIAO Xufeng) 5 anos atrás
pai
commit
91af5eaf4f

+ 3 - 3
components/driver/include/driver/twai.h

@@ -166,9 +166,9 @@ esp_err_t twai_driver_uninstall(void);
  *
  * This function starts the TWAI driver, putting the TWAI driver into the running
  * state. This allows the TWAI driver to participate in TWAI bus activities such
- * as transmitting/receiving messages. The RX queue is reset in this function,
- * clearing any unread messages. This function can only be called when the TWAI
- * driver is in the stopped state.
+ * as transmitting/receiving messages. The TX and RX queue are reset in this function,
+ * clearing any messages that are unread or pending transmission. This function
+ * can only be called when the TWAI driver is in the stopped state.
  *
  * @return
  *      - ESP_OK: TWAI driver is now running

+ 69 - 160
components/driver/twai.c

@@ -49,14 +49,6 @@
 
 #define DRIVER_DEFAULT_INTERRUPTS   0xE7        //Exclude data overrun (bit[3]) and brp_div (bit[4])
 
-//Control flags
-#define CTRL_FLAG_STOPPED           0x001       //TWAI peripheral in stopped state
-#define CTRL_FLAG_RECOVERING        0x002       //Bus is undergoing bus recovery
-#define CTRL_FLAG_ERR_WARN          0x004       //TEC or REC is >= error warning limit
-#define CTRL_FLAG_ERR_PASSIVE       0x008       //TEC or REC is >= 128
-#define CTRL_FLAG_BUS_OFF           0x010       //Bus-off due to TEC >= 256
-#define CTRL_FLAG_TX_BUFF_OCCUPIED  0x020       //Transmit buffer is occupied
-
 #define ALERT_LOG_LEVEL_WARNING     TWAI_ALERT_ARB_LOST  //Alerts above and including this level use ESP_LOGW
 #define ALERT_LOG_LEVEL_ERROR       TWAI_ALERT_TX_FAILED //Alerts above and including this level use ESP_LOGE
 
@@ -65,7 +57,7 @@
 //Control structure for TWAI driver
 typedef struct {
     //Control and status members
-    uint32_t control_flags;
+    twai_state_t state;
     twai_mode_t mode;
     uint32_t rx_missed_count;
     uint32_t tx_failed_count;
@@ -116,81 +108,6 @@ static void twai_alert_handler(uint32_t alert_code, int *alert_req)
     }
 }
 
-static inline void twai_handle_bus_off(int *alert_req)
-{
-    //Bus-Off condition. TEC should set and held at 127, REC should be 0, reset mode entered
-    TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_BUS_OFF);
-    /* Note: REC is still allowed to increase during bus-off. REC > err_warn
-       can prevent "bus recovery complete" interrupt from occurring. Set to
-       listen only mode to freeze REC. */
-    twai_hal_handle_bus_off(&twai_context);
-    twai_alert_handler(TWAI_ALERT_BUS_OFF, alert_req);
-}
-
-static inline void twai_handle_recovery_complete(int *alert_req)
-{
-    //Bus recovery complete.
-    bool recov_cplt = twai_hal_handle_bus_recov_cplt(&twai_context);
-    assert(recov_cplt);
-
-    //Reset and set flags to the equivalent of the stopped state
-    TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_RECOVERING | CTRL_FLAG_ERR_WARN |
-                                             CTRL_FLAG_ERR_PASSIVE | CTRL_FLAG_BUS_OFF |
-                                             CTRL_FLAG_TX_BUFF_OCCUPIED);
-    TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
-    twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, alert_req);
-}
-
-static inline void twai_handle_recovery_in_progress(int * alert_req)
-{
-    //Bus-recovery in progress. TEC has dropped below error warning limit
-    twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, alert_req);
-}
-
-static inline void twai_handle_above_ewl(int *alert_req)
-{
-    //TEC or REC surpassed error warning limit
-    TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_WARN);
-    twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, alert_req);
-}
-
-static inline void twai_handle_below_ewl(int *alert_req)
-{
-    //TEC and REC are both below error warning
-    TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_WARN);
-    twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, alert_req);
-}
-
-static inline void twai_handle_error_passive(int *alert_req)
-{
-    //Entered error passive
-    TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_PASSIVE);
-    twai_alert_handler(TWAI_ALERT_ERR_PASS, alert_req);
-}
-
-static inline void twai_handle_error_active(int *alert_req)
-{
-    //Returned to error active
-    TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_PASSIVE);
-    twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, alert_req);
-}
-
-static inline void twai_handle_bus_error(int *alert_req)
-{
-    // ECC register is read to re-arm bus error interrupt. ECC is not used
-    twai_hal_handle_bus_error(&twai_context);
-    p_twai_obj->bus_error_count++;
-    twai_alert_handler(TWAI_ALERT_BUS_ERROR, alert_req);
-}
-
-static inline void twai_handle_arb_lost(int *alert_req)
-{
-    //ALC register is read to re-arm arb lost interrupt. ALC is not used
-    twai_hal_handle_arb_lost(&twai_context);
-    p_twai_obj->arb_lost_count++;
-    twai_alert_handler(TWAI_ALERT_ARB_LOST, alert_req);
-}
-
 static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *alert_req)
 {
     uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context);
@@ -206,8 +123,6 @@ static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *ale
             twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
         }
     }
-    //Todo: Add Software Filters
-    //Todo: Check for data overrun of RX FIFO, then trigger alert
 }
 
 static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *alert_req)
@@ -235,7 +150,6 @@ static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *aler
         }
     } else {
         //No more frames to transmit
-        TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
         twai_alert_handler(TWAI_ALERT_TX_IDLE, alert_req);
     }
 }
@@ -250,43 +164,55 @@ static void twai_intr_handler_main(void *arg)
         TWAI_EXIT_CRITICAL_ISR();
         return;
     }
-    event = twai_hal_decode_interrupt_events(&twai_context, p_twai_obj->control_flags & CTRL_FLAG_RECOVERING);
+    event = twai_hal_decode_interrupt_events(&twai_context);
+    if (event & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
+        twai_handle_rx_buffer_frames(&task_woken, &alert_req);
+    }
+    //TX command should be the last command related handler to be called, so that
+    //other command register bits do not overwrite the TX command bit.
+    if (event & TWAI_HAL_EVENT_TX_BUFF_FREE) {
+        twai_handle_tx_buffer_frame(&task_woken, &alert_req);
+    }
 
+    //Handle events that only require alerting (i.e. no handler)
     if (event & TWAI_HAL_EVENT_BUS_OFF) {
-        twai_handle_bus_off(&alert_req);
+        p_twai_obj->state = TWAI_STATE_BUS_OFF;
+        twai_alert_handler(TWAI_ALERT_BUS_OFF, &alert_req);
     }
     if (event & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
-        twai_handle_recovery_complete(&alert_req);
+        //Reset and set flags to the equivalent of the stopped state
+        p_twai_obj->state = TWAI_STATE_STOPPED;
+        twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, &alert_req);
     }
-    if (event & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) {
-        twai_handle_recovery_in_progress(&alert_req);
+    if (event & TWAI_HAL_EVENT_BUS_ERR) {
+        p_twai_obj->bus_error_count++;
+        twai_alert_handler(TWAI_ALERT_BUS_ERROR, &alert_req);
     }
-    if (event & TWAI_HAL_EVENT_ABOVE_EWL) {
-        twai_handle_above_ewl(&alert_req);
+    if (event & TWAI_HAL_EVENT_ARB_LOST) {
+        p_twai_obj->arb_lost_count++;
+        twai_alert_handler(TWAI_ALERT_ARB_LOST, &alert_req);
     }
-    if (event & TWAI_HAL_EVENT_BELOW_EWL) {
-        twai_handle_below_ewl(&alert_req);
+    if (event & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) {
+        //Bus-recovery in progress. TEC has dropped below error warning limit
+        twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, &alert_req);        
     }
     if (event & TWAI_HAL_EVENT_ERROR_PASSIVE) {
-        twai_handle_error_passive(&alert_req);
+        //Entered error passive
+        twai_alert_handler(TWAI_ALERT_ERR_PASS, &alert_req);
     }
     if (event & TWAI_HAL_EVENT_ERROR_ACTIVE) {
-        twai_handle_error_active(&alert_req);
-    }
-    if (event & TWAI_HAL_EVENT_BUS_ERR) {
-        twai_handle_bus_error(&alert_req);
+        //Returned to error active
+        twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, &alert_req);
     }
-    if (event & TWAI_HAL_EVENT_ARB_LOST) {
-        twai_handle_arb_lost(&alert_req);
-    }
-    if (event & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
-        twai_handle_rx_buffer_frames(&task_woken, &alert_req);
+    if (event & TWAI_HAL_EVENT_ABOVE_EWL) {
+        //TEC or REC surpassed error warning limit
+        twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, &alert_req);
     }
-    //TX command related handlers should be called last, so that other commands
-    //do not overwrite the TX command related bits in the command register.
-    if (event & TWAI_HAL_EVENT_TX_BUFF_FREE) {
-        twai_handle_tx_buffer_frame(&task_woken, &alert_req);
+    if (event & TWAI_HAL_EVENT_BELOW_EWL) {
+        //TEC and REC are both below error warning
+        twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, &alert_req);
     }
+
     TWAI_EXIT_CRITICAL_ISR();
 
     if (p_twai_obj->alert_semphr != NULL && alert_req) {
@@ -371,7 +297,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
 #endif
 
     //Initialize flags and variables. All other members are 0 initialized by calloc()
-    p_twai_obj_dummy->control_flags = CTRL_FLAG_STOPPED;
+    p_twai_obj_dummy->state = TWAI_STATE_STOPPED;
     p_twai_obj_dummy->mode = g_config->mode;
     p_twai_obj_dummy->alerts_enabled = g_config->alerts_enabled;
 
@@ -390,7 +316,6 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
     bool init = twai_hal_init(&twai_context);
     assert(init);
     twai_hal_configure(&twai_context, t_config, f_config, DRIVER_DEFAULT_INTERRUPTS, g_config->clkout_divider);
-    //Todo: Allow interrupt to be registered to specified CPU
     TWAI_EXIT_CRITICAL();
 
     //Allocate GPIO and Interrupts
@@ -434,8 +359,7 @@ esp_err_t twai_driver_uninstall(void)
     TWAI_ENTER_CRITICAL();
     //Check state
     TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
-    TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF), ESP_ERR_INVALID_STATE);
-    //Todo: Add check to see if in reset mode.  //Enter reset mode to stop any TWAI bus activity
+    TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED || p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
     //Clear registers by reading
     twai_hal_deinit(&twai_context);
     periph_module_disable(PERIPH_TWAI_MODULE);               //Disable TWAI peripheral
@@ -466,18 +390,18 @@ esp_err_t twai_start(void)
     //Check state
     TWAI_ENTER_CRITICAL();
     TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
-    TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & CTRL_FLAG_STOPPED, ESP_ERR_INVALID_STATE);
+    TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED, ESP_ERR_INVALID_STATE);
 
-    //Reset RX queue, and RX message count
+    //Reset RX queue, RX message count, amd TX queue
     xQueueReset(p_twai_obj->rx_queue);
+    if (p_twai_obj->tx_queue != NULL) {
+        xQueueReset(p_twai_obj->tx_queue);
+    }
     p_twai_obj->rx_msg_count = 0;
-    //Todo: Add assert to see if in reset mode. //Should already be in bus-off mode, set again to make sure
-
-    //Currently in listen only mode, need to set to mode specified by configuration
-    bool started = twai_hal_start(&twai_context, p_twai_obj->mode);
-    assert(started);
+    p_twai_obj->tx_msg_count = 0;
+    twai_hal_start(&twai_context, p_twai_obj->mode);
 
-    TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
+    p_twai_obj->state = TWAI_STATE_RUNNING;
     TWAI_EXIT_CRITICAL();
     return ESP_OK;
 }
@@ -487,19 +411,16 @@ esp_err_t twai_stop(void)
     //Check state
     TWAI_ENTER_CRITICAL();
     TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
-    TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)), ESP_ERR_INVALID_STATE);
+    TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_RUNNING, ESP_ERR_INVALID_STATE);
 
-    bool stopped = twai_hal_stop(&twai_context);
-    assert(stopped);
-
-    TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
-    TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
+    twai_hal_stop(&twai_context);
 
     //Reset TX Queue and message count
     if (p_twai_obj->tx_queue != NULL) {
         xQueueReset(p_twai_obj->tx_queue);
     }
     p_twai_obj->tx_msg_count = 0;
+    p_twai_obj->state = TWAI_STATE_STOPPED;
 
     TWAI_EXIT_CRITICAL();
 
@@ -516,18 +437,17 @@ esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait)
     TWAI_ENTER_CRITICAL();
     //Check State
     TWAI_CHECK_FROM_CRIT(!(p_twai_obj->mode == TWAI_MODE_LISTEN_ONLY), ESP_ERR_NOT_SUPPORTED);
-    TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)), ESP_ERR_INVALID_STATE);
+    TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_RUNNING, ESP_ERR_INVALID_STATE);
     //Format frame
     esp_err_t ret = ESP_FAIL;
     twai_hal_frame_t tx_frame;
     twai_hal_format_frame(message, &tx_frame);
 
     //Check if frame can be sent immediately
-    if ((p_twai_obj->tx_msg_count == 0) && !(p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED)) {
+    if (p_twai_obj->tx_msg_count == 0) {
         //No other frames waiting to transmit. Bypass queue and transmit immediately
         twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
         p_twai_obj->tx_msg_count++;
-        TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
         ret = ESP_OK;
     }
     TWAI_EXIT_CRITICAL();
@@ -539,19 +459,19 @@ esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait)
         } else if (xQueueSend(p_twai_obj->tx_queue, &tx_frame, ticks_to_wait) == pdTRUE) {
             //Copied to TX Queue
             TWAI_ENTER_CRITICAL();
-            if (p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)) {
-                //TX queue was reset (due to stop/bus_off), remove copied frame from queue to prevent transmission
-                int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
-                assert(res == pdTRUE);
-                ret = ESP_ERR_INVALID_STATE;
-            } else if ((p_twai_obj->tx_msg_count == 0) && !(p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED)) {
-                //TX buffer was freed during copy, manually trigger transmission
-                int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
-                assert(res == pdTRUE);
-                twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
-                p_twai_obj->tx_msg_count++;
-                TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
-                ret = ESP_OK;
+            if ((!twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED)) && uxQueueMessagesWaiting(p_twai_obj->tx_queue) > 0) {
+                //If the TX buffer is free but the TX queue is not empty. Check if we need to manually start a transmission
+                if (twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_BUS_OFF) || !twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_RUNNING)) {
+                    //TX buffer became free due to bus-off or is no longer running. No need to start a transmission
+                    ret = ESP_ERR_INVALID_STATE;
+                } else {
+                    //Manually start a transmission
+                    int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
+                    assert(res == pdTRUE);
+                    twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
+                    p_twai_obj->tx_msg_count++;
+                    ret = ESP_OK;
+                }
             } else {
                 //Frame was copied to queue, waiting to be transmitted
                 p_twai_obj->tx_msg_count++;
@@ -627,20 +547,17 @@ esp_err_t twai_initiate_recovery(void)
     TWAI_ENTER_CRITICAL();
     //Check state
     TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
-    TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & CTRL_FLAG_BUS_OFF, ESP_ERR_INVALID_STATE);
-    TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & CTRL_FLAG_RECOVERING), ESP_ERR_INVALID_STATE);
+    TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
 
     //Reset TX Queue/Counters
     if (p_twai_obj->tx_queue != NULL) {
         xQueueReset(p_twai_obj->tx_queue);
     }
     p_twai_obj->tx_msg_count = 0;
-    TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
-    TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_RECOVERING);
 
     //Trigger start of recovery process
-    bool started = twai_hal_start_bus_recovery(&twai_context);
-    assert(started);
+    twai_hal_start_bus_recovery(&twai_context);
+    p_twai_obj->state = TWAI_STATE_RECOVERING;
     TWAI_EXIT_CRITICAL();
 
     return ESP_OK;
@@ -661,15 +578,7 @@ esp_err_t twai_get_status_info(twai_status_info_t *status_info)
     status_info->rx_missed_count = p_twai_obj->rx_missed_count;
     status_info->arb_lost_count = p_twai_obj->arb_lost_count;
     status_info->bus_error_count = p_twai_obj->bus_error_count;
-    if (p_twai_obj->control_flags & CTRL_FLAG_RECOVERING) {
-        status_info->state = TWAI_STATE_RECOVERING;
-    } else if (p_twai_obj->control_flags & CTRL_FLAG_BUS_OFF) {
-        status_info->state = TWAI_STATE_BUS_OFF;
-    } else if (p_twai_obj->control_flags & CTRL_FLAG_STOPPED) {
-        status_info->state = TWAI_STATE_STOPPED;
-    } else {
-        status_info->state = TWAI_STATE_RUNNING;
-    }
+    status_info->state = p_twai_obj->state;
     TWAI_EXIT_CRITICAL();
 
     return ESP_OK;
@@ -683,7 +592,7 @@ esp_err_t twai_clear_transmit_queue(void)
 
     TWAI_ENTER_CRITICAL();
     //If a message is currently undergoing transmission, the tx interrupt handler will decrement tx_msg_count
-    p_twai_obj->tx_msg_count = (p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED) ? 1 : 0;
+    p_twai_obj->tx_msg_count = twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED) ? 1 : 0;
     xQueueReset(p_twai_obj->tx_queue);
     TWAI_EXIT_CRITICAL();
 

+ 11 - 26
components/hal/esp32/include/hal/can_hal.h

@@ -66,19 +66,19 @@ static inline void can_hal_configure(can_hal_context_t *hal_ctx, const can_timin
 
 /* -------------------------------- Actions --------------------------------- */
 
-static inline bool can_hal_start(can_hal_context_t *hal_ctx, can_mode_t mode)
+static inline void can_hal_start(can_hal_context_t *hal_ctx, can_mode_t mode)
 {
-    return twai_hal_start(hal_ctx, mode);
+    twai_hal_start(hal_ctx, mode);
 }
 
-static inline bool can_hal_stop(can_hal_context_t *hal_ctx)
+static inline void can_hal_stop(can_hal_context_t *hal_ctx)
 {
-    return twai_hal_stop(hal_ctx);
+    twai_hal_stop(hal_ctx);
 }
 
-static inline bool can_hal_start_bus_recovery(can_hal_context_t *hal_ctx)
+static inline void can_hal_start_bus_recovery(can_hal_context_t *hal_ctx)
 {
-    return twai_hal_start_bus_recovery(hal_ctx);
+    twai_hal_start_bus_recovery(hal_ctx);
 }
 
 static inline uint32_t can_hal_get_tec(can_hal_context_t *hal_ctx)
@@ -101,30 +101,15 @@ static inline bool can_hal_check_last_tx_successful(can_hal_context_t *hal_ctx)
     return twai_hal_check_last_tx_successful(hal_ctx);
 }
 
-/* ----------------------------- Event Handling ----------------------------- */
-
-static inline uint32_t can_hal_decode_interrupt_events(can_hal_context_t *hal_ctx, bool bus_recovering) {
-    return twai_hal_decode_interrupt_events(hal_ctx, bus_recovering);
-}
-
-static inline bool can_hal_handle_bus_recov_cplt(can_hal_context_t *hal_ctx)
+static inline bool can_hal_check_state_flags(can_hal_context_t *hal_ctx, uint32_t check_flags)
 {
-    return twai_hal_handle_bus_recov_cplt(hal_ctx);
+    return twai_hal_check_state_flags(hal_ctx, check_flags);
 }
 
-static inline void can_hal_handle_arb_lost(can_hal_context_t *hal_ctx)
-{
-    twai_hal_handle_arb_lost(hal_ctx);
-}
-
-static inline void can_hal_handle_bus_error(can_hal_context_t *hal_ctx)
-{
-    twai_hal_handle_bus_error(hal_ctx);
-}
+/* ----------------------------- Event Handling ----------------------------- */
 
-static inline void can_hal_handle_bus_off(can_hal_context_t *hal_ctx)
-{
-    twai_hal_handle_bus_off(hal_ctx);
+static inline uint32_t can_hal_decode_interrupt_events(can_hal_context_t *hal_ctx) {
+    return twai_hal_decode_interrupt_events(hal_ctx);
 }
 
 /* ------------------------------- TX and RX -------------------------------- */

+ 4 - 4
components/hal/esp32/include/hal/can_ll.h

@@ -54,14 +54,14 @@ typedef twai_ll_frame_buffer_t can_ll_frame_buffer_t;
 
 /* ---------------------------- Mode Register ------------------------------- */
 
-static inline bool can_ll_enter_reset_mode(can_dev_t *hw)
+static inline void can_ll_enter_reset_mode(can_dev_t *hw)
 {
-    return twai_ll_enter_reset_mode(hw);
+    twai_ll_enter_reset_mode(hw);
 }
 
-static inline bool can_ll_exit_reset_mode(can_dev_t *hw)
+static inline void can_ll_exit_reset_mode(can_dev_t *hw)
 {
-    return twai_ll_exit_reset_mode(hw);
+    twai_ll_exit_reset_mode(hw);
 }
 
 static inline bool can_ll_is_in_reset_mode(can_dev_t *hw)

+ 17 - 25
components/hal/esp32/include/hal/twai_ll.h

@@ -34,22 +34,22 @@ extern "C" {
 
 /* ------------------------- Defines and Typedefs --------------------------- */
 
-#define TWAI_LL_STATUS_RBS      (0x1 << 0)
-#define TWAI_LL_STATUS_DOS      (0x1 << 1)
-#define TWAI_LL_STATUS_TBS      (0x1 << 2)
-#define TWAI_LL_STATUS_TCS      (0x1 << 3)
-#define TWAI_LL_STATUS_RS       (0x1 << 4)
-#define TWAI_LL_STATUS_TS       (0x1 << 5)
-#define TWAI_LL_STATUS_ES       (0x1 << 6)
-#define TWAI_LL_STATUS_BS       (0x1 << 7)
-
-#define TWAI_LL_INTR_RI         (0x1 << 0)
-#define TWAI_LL_INTR_TI         (0x1 << 1)
-#define TWAI_LL_INTR_EI         (0x1 << 2)
+#define TWAI_LL_STATUS_RBS      (0x1 << 0)      //Receive Buffer Status 
+#define TWAI_LL_STATUS_DOS      (0x1 << 1)      //Data Overrun Status
+#define TWAI_LL_STATUS_TBS      (0x1 << 2)      //Transmit Buffer Status
+#define TWAI_LL_STATUS_TCS      (0x1 << 3)      //Transmission Complete Status
+#define TWAI_LL_STATUS_RS       (0x1 << 4)      //Receive Status
+#define TWAI_LL_STATUS_TS       (0x1 << 5)      //Transmit Status
+#define TWAI_LL_STATUS_ES       (0x1 << 6)      //Error Status
+#define TWAI_LL_STATUS_BS       (0x1 << 7)      //Bus Status
+
+#define TWAI_LL_INTR_RI         (0x1 << 0)      //Receive Interrupt
+#define TWAI_LL_INTR_TI         (0x1 << 1)      //Transmit Interrupt
+#define TWAI_LL_INTR_EI         (0x1 << 2)      //Error Interrupt
 //Data overrun interrupt not supported in SW due to HW peculiarities
-#define TWAI_LL_INTR_EPI        (0x1 << 5)
-#define TWAI_LL_INTR_ALI        (0x1 << 6)
-#define TWAI_LL_INTR_BEI        (0x1 << 7)
+#define TWAI_LL_INTR_EPI        (0x1 << 5)      //Error Passive Interrupt
+#define TWAI_LL_INTR_ALI        (0x1 << 6)      //Arbitration Lost Interrupt
+#define TWAI_LL_INTR_BEI        (0x1 << 7)      //Bus Error Interrupt
 
 /*
  * The following frame structure has an NEARLY identical bit field layout to
@@ -95,14 +95,12 @@ _Static_assert(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should b
  * in order to write the majority of configuration registers.
  *
  * @param hw Start address of the TWAI registers
- * @return true if reset mode was entered successfully
  *
  * @note Reset mode is automatically entered on BUS OFF condition
  */
-static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
+static inline void twai_ll_enter_reset_mode(twai_dev_t *hw)
 {
     hw->mode_reg.rm = 1;
-    return hw->mode_reg.rm;
 }
 
 /**
@@ -113,14 +111,12 @@ static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
  * operating mode.
  *
  * @param hw Start address of the TWAI registers
- * @return true if reset mode was exit successfully
  *
  * @note Reset mode must be exit to initiate BUS OFF recovery
  */
-static inline bool twai_ll_exit_reset_mode(twai_dev_t *hw)
+static inline void twai_ll_exit_reset_mode(twai_dev_t *hw)
 {
     hw->mode_reg.rm = 0;
-    return !(hw->mode_reg.rm);
 }
 
 /**
@@ -307,8 +303,6 @@ static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
     return hw->status_reg.tcs;
 }
 
-//Todo: Add stand alone status bit check functions when necessary
-
 /* -------------------------- Interrupt Register ---------------------------- */
 
 /**
@@ -391,7 +385,6 @@ static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t
 static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
 {
     (void)hw->arbitration_lost_captue_reg.val;
-    //Todo: Decode ALC register
 }
 
 /* ----------------------------- ECC Register ------------------------------- */
@@ -406,7 +399,6 @@ static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
 static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
 {
     (void)hw->error_code_capture_reg.val;
-    //Todo: Decode error code capture
 }
 
 /* ----------------------------- EWL Register ------------------------------- */

+ 17 - 26
components/hal/esp32s2/include/hal/twai_ll.h

@@ -33,23 +33,22 @@ extern "C" {
 
 /* ------------------------- Defines and Typedefs --------------------------- */
 
-#define TWAI_LL_STATUS_RBS       (0x1 << 0)
-#define TWAI_LL_STATUS_DOS       (0x1 << 1)
-#define TWAI_LL_STATUS_TBS       (0x1 << 2)
-#define TWAI_LL_STATUS_TCS       (0x1 << 3)
-#define TWAI_LL_STATUS_RS        (0x1 << 4)
-#define TWAI_LL_STATUS_TS        (0x1 << 5)
-#define TWAI_LL_STATUS_ES        (0x1 << 6)
-#define TWAI_LL_STATUS_BS        (0x1 << 7)
-//Todo: Add Miss status support
-
-#define TWAI_LL_INTR_RI          (0x1 << 0)
-#define TWAI_LL_INTR_TI          (0x1 << 1)
-#define TWAI_LL_INTR_EI          (0x1 << 2)
+#define TWAI_LL_STATUS_RBS      (0x1 << 0)      //Receive Buffer Status 
+#define TWAI_LL_STATUS_DOS      (0x1 << 1)      //Data Overrun Status
+#define TWAI_LL_STATUS_TBS      (0x1 << 2)      //Transmit Buffer Status
+#define TWAI_LL_STATUS_TCS      (0x1 << 3)      //Transmission Complete Status
+#define TWAI_LL_STATUS_RS       (0x1 << 4)      //Receive Status
+#define TWAI_LL_STATUS_TS       (0x1 << 5)      //Transmit Status
+#define TWAI_LL_STATUS_ES       (0x1 << 6)      //Error Status
+#define TWAI_LL_STATUS_BS       (0x1 << 7)      //Bus Status
+
+#define TWAI_LL_INTR_RI         (0x1 << 0)      //Receive Interrupt
+#define TWAI_LL_INTR_TI         (0x1 << 1)      //Transmit Interrupt
+#define TWAI_LL_INTR_EI         (0x1 << 2)      //Error Interrupt
 //Data overrun interrupt not supported in SW due to HW peculiarities
-#define TWAI_LL_INTR_EPI         (0x1 << 5)
-#define TWAI_LL_INTR_ALI         (0x1 << 6)
-#define TWAI_LL_INTR_BEI         (0x1 << 7)
+#define TWAI_LL_INTR_EPI        (0x1 << 5)      //Error Passive Interrupt
+#define TWAI_LL_INTR_ALI        (0x1 << 6)      //Arbitration Lost Interrupt
+#define TWAI_LL_INTR_BEI        (0x1 << 7)      //Bus Error Interrupt
 
 /*
  * The following frame structure has an NEARLY identical bit field layout to
@@ -95,14 +94,12 @@ _Static_assert(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should b
  * in order to write the majority of configuration registers.
  *
  * @param hw Start address of the TWAI registers
- * @return true if reset mode was entered successfully
  *
  * @note Reset mode is automatically entered on BUS OFF condition
  */
-static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
+static inline void twai_ll_enter_reset_mode(twai_dev_t *hw)
 {
     hw->mode_reg.rm = 1;
-    return hw->mode_reg.rm;
 }
 
 /**
@@ -113,14 +110,12 @@ static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
  * operating mode.
  *
  * @param hw Start address of the TWAI registers
- * @return true if reset mode was exit successfully
  *
  * @note Reset mode must be exit to initiate BUS OFF recovery
  */
-static inline bool twai_ll_exit_reset_mode(twai_dev_t *hw)
+static inline void twai_ll_exit_reset_mode(twai_dev_t *hw)
 {
     hw->mode_reg.rm = 0;
-    return !(hw->mode_reg.rm);
 }
 
 /**
@@ -307,8 +302,6 @@ static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
     return hw->status_reg.tcs;
 }
 
-//Todo: Add stand alone status bit check functions when necessary
-
 /* -------------------------- Interrupt Register ---------------------------- */
 
 /**
@@ -376,7 +369,6 @@ static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t
 static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
 {
     (void)hw->arbitration_lost_captue_reg.val;
-    //Todo: Decode ALC register
 }
 
 /* ----------------------------- ECC Register ------------------------------- */
@@ -391,7 +383,6 @@ static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
 static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
 {
     (void)hw->error_code_capture_reg.val;
-    //Todo: Decode error code capture
 }
 
 /* ----------------------------- EWL Register ------------------------------- */

+ 51 - 72
components/hal/include/hal/twai_hal.h

@@ -31,21 +31,33 @@ extern "C" {
 
 /* ------------------------- Defines and Typedefs --------------------------- */
 
+#define TWAI_HAL_SET_FLAG(var, flag)            ((var) |= (flag))
+#define TWAI_HAL_RESET_FLAG(var, flag)          ((var) &= ~(flag))
+
+//HAL state flags
+#define TWAI_HAL_STATE_FLAG_RUNNING             (1 << 0)    //Controller is active (not in reset mode)
+#define TWAI_HAL_STATE_FLAG_RECOVERING          (1 << 1)    //Bus is undergoing bus recovery
+#define TWAI_HAL_STATE_FLAG_ERR_WARN            (1 << 2)    //TEC or REC is >= error warning limit
+#define TWAI_HAL_STATE_FLAG_ERR_PASSIVE         (1 << 3)    //TEC or REC is >= 128
+#define TWAI_HAL_STATE_FLAG_BUS_OFF             (1 << 4)    //Bus-off due to TEC >= 256
+#define TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED    (1 << 5)    //Transmit buffer is occupied
+
 //Error active interrupt related
-#define TWAI_HAL_EVENT_BUS_OFF               (1 << 0)
-#define TWAI_HAL_EVENT_BUS_RECOV_CPLT        (1 << 1)
-#define TWAI_HAL_EVENT_BUS_RECOV_PROGRESS    (1 << 2)
-#define TWAI_HAL_EVENT_ABOVE_EWL             (1 << 3)
-#define TWAI_HAL_EVENT_BELOW_EWL             (1 << 4)
-#define TWAI_HAL_EVENT_ERROR_PASSIVE         (1 << 5)
-#define TWAI_HAL_EVENT_ERROR_ACTIVE          (1 << 6)
-#define TWAI_HAL_EVENT_BUS_ERR               (1 << 7)
-#define TWAI_HAL_EVENT_ARB_LOST              (1 << 8)
-#define TWAI_HAL_EVENT_RX_BUFF_FRAME         (1 << 9)
-#define TWAI_HAL_EVENT_TX_BUFF_FREE          (1 << 10)
+#define TWAI_HAL_EVENT_BUS_OFF                  (1 << 0)
+#define TWAI_HAL_EVENT_BUS_RECOV_CPLT           (1 << 1)
+#define TWAI_HAL_EVENT_BUS_RECOV_PROGRESS       (1 << 2)
+#define TWAI_HAL_EVENT_ABOVE_EWL                (1 << 3)
+#define TWAI_HAL_EVENT_BELOW_EWL                (1 << 4)
+#define TWAI_HAL_EVENT_ERROR_PASSIVE            (1 << 5)
+#define TWAI_HAL_EVENT_ERROR_ACTIVE             (1 << 6)
+#define TWAI_HAL_EVENT_BUS_ERR                  (1 << 7)
+#define TWAI_HAL_EVENT_ARB_LOST                 (1 << 8)
+#define TWAI_HAL_EVENT_RX_BUFF_FRAME            (1 << 9)
+#define TWAI_HAL_EVENT_TX_BUFF_FREE             (1 << 10)
 
 typedef struct {
     twai_dev_t *dev;
+    uint32_t state_flags;
 } twai_hal_context_t;
 
 typedef twai_ll_frame_buffer_t twai_hal_frame_t;
@@ -93,9 +105,8 @@ void twai_hal_configure(twai_hal_context_t *hal_ctx, const twai_timing_config_t
  *
  * @param hal_ctx Context of the HAL layer
  * @param mode Operating mode
- * @return True if successfully started, false otherwise.
  */
-bool twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode);
+void twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode);
 
 /**
  * @brief Stop the TWAI peripheral
@@ -104,19 +115,18 @@ bool twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode);
  * setting the operating mode to Listen Only so that REC is frozen.
  *
  * @param hal_ctx Context of the HAL layer
- * @return True if successfully stopped, false otherwise.
  */
-bool twai_hal_stop(twai_hal_context_t *hal_ctx);
+void twai_hal_stop(twai_hal_context_t *hal_ctx);
 
 /**
  * @brief Start bus recovery
  *
  * @param hal_ctx Context of the HAL layer
- * @return True if successfully started bus recovery, false otherwise.
  */
-static inline bool twai_hal_start_bus_recovery(twai_hal_context_t *hal_ctx)
+static inline void twai_hal_start_bus_recovery(twai_hal_context_t *hal_ctx)
 {
-    return twai_ll_exit_reset_mode(hal_ctx->dev);
+    TWAI_HAL_SET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RECOVERING);
+    twai_ll_exit_reset_mode(hal_ctx->dev);
 }
 
 /**
@@ -163,73 +173,42 @@ static inline bool twai_hal_check_last_tx_successful(twai_hal_context_t *hal_ctx
     return twai_ll_is_last_tx_successful((hal_ctx)->dev);
 }
 
-/* ----------------------------- Event Handling ----------------------------- */
-
 /**
- * @brief Decode current events that triggered an interrupt
- *
- * This function should be called on every TWAI interrupt. It will read (and
- * thereby clear) the interrupt register, then determine what events have
- * occurred to trigger the interrupt.
- *
+ * @brief Check if certain HAL state flags are set
+ * 
+ * The HAL will maintain a record of the controller's state via a set of flags.
+ * These flags are automatically maintained (i.e., set and reset) inside various
+ * HAL function calls. This function checks if certain flags are currently set.
+ * 
  * @param hal_ctx Context of the HAL layer
- * @param bus_recovering Whether the TWAI peripheral was previous undergoing bus recovery
- * @return Bit mask of events that have occurred
+ * @param check_flags Bit mask of flags to check
+ * @return True if one or more of the flags in check_flags are set
  */
-uint32_t twai_hal_decode_interrupt_events(twai_hal_context_t *hal_ctx, bool bus_recovering);
 
-/**
- * @brief Handle bus recovery complete
- *
- * This function should be called on an bus recovery complete event. It simply
- * enters reset mode to stop bus activity.
- *
- * @param hal_ctx Context of the HAL layer
- * @return True if successfully handled bus recovery completion, false otherwise.
- */
-static inline bool twai_hal_handle_bus_recov_cplt(twai_hal_context_t *hal_ctx)
+static inline bool twai_hal_check_state_flags(twai_hal_context_t *hal_ctx, uint32_t check_flags)
 {
-    return twai_ll_enter_reset_mode((hal_ctx)->dev);
+    return hal_ctx->state_flags & check_flags;
 }
 
-/**
- * @brief Handle arbitration lost
- *
- * This function should be called on an arbitration lost event. It simply clears
- * the clears the ALC register.
- *
- * @param hal_ctx Context of the HAL layer
- */
-static inline void twai_hal_handle_arb_lost(twai_hal_context_t *hal_ctx)
-{
-    twai_ll_clear_arb_lost_cap((hal_ctx)->dev);
-}
-
-/**
- * @brief Handle bus error
- *
- * This function should be called on an bus error event. It simply clears
- * the clears the ECC register.
- *
- * @param hal_ctx Context of the HAL layer
- */
-static inline void twai_hal_handle_bus_error(twai_hal_context_t *hal_ctx)
-{
-    twai_ll_clear_err_code_cap((hal_ctx)->dev);
-}
+/* ----------------------------- Event Handling ----------------------------- */
 
 /**
- * @brief Handle BUS OFF
+ * @brief Decode current events that triggered an interrupt
  *
- * This function should be called on a BUS OFF event. It simply changes the
- * mode to LOM to freeze REC
+ * This function should be the called at the beginning of an ISR. This
+ * function will do the following:
+ * - Read and clear interrupts
+ * - Decode current events that triggered an interrupt
+ * - Respond to low latency interrupt events
+ *      - Bus off: Change to LOM to free TEC/REC
+ *      - Recovery complete: Enter reset mode
+ *      - Clear ECC and ALC
+ * - Update state flags based on events that have occurred.
  *
  * @param hal_ctx Context of the HAL layer
+ * @return Bit mask of events that have occurred
  */
-static inline void twai_hal_handle_bus_off(twai_hal_context_t *hal_ctx)
-{
-    twai_ll_set_mode((hal_ctx)->dev, TWAI_MODE_LISTEN_ONLY);
-}
+uint32_t twai_hal_decode_interrupt_events(twai_hal_context_t *hal_ctx);
 
 /* ------------------------------- TX and RX -------------------------------- */
 

+ 64 - 33
components/hal/twai_hal.c

@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//Todo: Place the implementation of all common HAL functions here
-
 #include <stddef.h>
 #include "hal/twai_hal.h"
 
@@ -22,12 +20,16 @@
 #define TWAI_HAL_INIT_REC    0
 #define TWAI_HAL_INIT_EWL    96
 
+/* ---------------------------- Init and Config ----------------------------- */
+
 bool twai_hal_init(twai_hal_context_t *hal_ctx)
 {
     //Initialize HAL context
     hal_ctx->dev = &TWAI;
+    hal_ctx->state_flags = 0;
     //Initialize TWAI controller, and set default values to registers
-    if (!twai_ll_enter_reset_mode(hal_ctx->dev)) {    //Must enter reset mode to write to config registers
+    twai_ll_enter_reset_mode(hal_ctx->dev);
+    if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) {    //Must enter reset mode to write to config registers
         return false;
     }
 #ifdef TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT
@@ -61,26 +63,29 @@ void twai_hal_configure(twai_hal_context_t *hal_ctx, const twai_timing_config_t
     (void) twai_ll_get_and_clear_intrs(hal_ctx->dev);    //Clear any latched interrupts
 }
 
-bool twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode)
+/* -------------------------------- Actions --------------------------------- */
+
+void twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode)
 {
     twai_ll_set_mode(hal_ctx->dev, mode);                //Set operating mode
-    //Todo: Check if this can be removed
     (void) twai_ll_get_and_clear_intrs(hal_ctx->dev);    //Clear any latched interrupts
-    return twai_ll_exit_reset_mode(hal_ctx->dev);        //Return false if failed to exit reset mode
+    TWAI_HAL_SET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RUNNING);
+    twai_ll_exit_reset_mode(hal_ctx->dev); 
 }
 
-bool twai_hal_stop(twai_hal_context_t *hal_ctx)
+void twai_hal_stop(twai_hal_context_t *hal_ctx)
 {
-    if (!twai_ll_enter_reset_mode(hal_ctx->dev)) {
-        return false;
-    }
-    //Todo: Check if this can be removed
+    twai_ll_enter_reset_mode(hal_ctx->dev);
     (void) twai_ll_get_and_clear_intrs(hal_ctx->dev);
     twai_ll_set_mode(hal_ctx->dev, TWAI_MODE_LISTEN_ONLY);    //Freeze REC by changing to LOM mode
-    return true;
+    //Any TX is immediately halted on entering reset mode
+    TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED);
+    TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RUNNING);
 }
 
-uint32_t twai_hal_decode_interrupt_events(twai_hal_context_t *hal_ctx, bool bus_recovering)
+/* ----------------------------- Event Handling ----------------------------- */
+
+uint32_t twai_hal_decode_interrupt_events(twai_hal_context_t *hal_ctx)
 {
     uint32_t events = 0;
     //Read interrupt, status
@@ -89,6 +94,38 @@ uint32_t twai_hal_decode_interrupt_events(twai_hal_context_t *hal_ctx, bool bus_
     uint32_t tec = twai_ll_get_tec(hal_ctx->dev);
     uint32_t rec = twai_ll_get_rec(hal_ctx->dev);
 
+    //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_ll_set_mode(hal_ctx->dev, TWAI_MODE_LISTEN_ONLY);  //Set to listen only to freeze tec and rec
+                events |= TWAI_HAL_EVENT_BUS_OFF;
+                TWAI_HAL_SET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_BUS_OFF);
+                TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RUNNING);
+                //Any TX would have been halted by entering bus off. Reset its flag
+                TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED);
+            } else {
+                //Below EWL. Therefore TEC is counting down in bus recovery
+                events |= TWAI_HAL_EVENT_BUS_RECOV_PROGRESS;
+            }
+        } else {
+            //Not in BUS OFF
+            if (status & TWAI_LL_STATUS_ES) {       //Just Exceeded EWL
+                events |= TWAI_HAL_EVENT_ABOVE_EWL;  
+                TWAI_HAL_SET_FLAG(hal_ctx->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_ll_enter_reset_mode(hal_ctx->dev);     //Enter reset mode to stop the peripheral
+                events |= TWAI_HAL_EVENT_BUS_RECOV_CPLT;
+                TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RECOVERING);
+                TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_BUS_OFF);
+            } else {        //Just went below EWL
+                events |= TWAI_HAL_EVENT_BELOW_EWL;
+                TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_ERR_WARN);
+            }
+        }
+    }
     //Receive Interrupt set whenever RX FIFO  is not empty
     if (interrupts & TWAI_LL_INTR_RI) {
         events |= TWAI_HAL_EVENT_RX_BUFF_FRAME;
@@ -96,35 +133,28 @@ uint32_t twai_hal_decode_interrupt_events(twai_hal_context_t *hal_ctx, bool bus_
     //Transmit interrupt set whenever TX buffer becomes free
     if (interrupts & TWAI_LL_INTR_TI) {
         events |= TWAI_HAL_EVENT_TX_BUFF_FREE;
+        TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED);
     }
-    //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
-            //EWL is exceeded, thus must have entered BUS OFF
-            //Below EWL. Therefore TEC is counting down in bus recovery
-            //Todo: Check if BUS Recov can be removed for esp32s2
-            events |= (status & TWAI_LL_STATUS_ES) ? TWAI_HAL_EVENT_BUS_OFF : TWAI_HAL_EVENT_BUS_RECOV_PROGRESS;
+    //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) {
+            events |= TWAI_HAL_EVENT_ERROR_PASSIVE;
+            TWAI_HAL_SET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_ERR_PASSIVE);
         } else {
-            //Not in BUS OFF
-            events |= (status & TWAI_LL_STATUS_ES) ? TWAI_HAL_EVENT_ABOVE_EWL :   //Just Exceeded EWL
-                      ((bus_recovering) ?  //If previously undergoing bus recovery
-                      TWAI_HAL_EVENT_BUS_RECOV_CPLT :
-                      TWAI_HAL_EVENT_BELOW_EWL);
+            events |= TWAI_HAL_EVENT_ERROR_ACTIVE;
+            TWAI_HAL_RESET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_ERR_PASSIVE);
         }
     }
-    //Error Passive Interrupt on transition from error active to passive or vice versa
-    if (interrupts & TWAI_LL_INTR_EPI) {
-        events |= (tec >= TWAI_ERR_PASS_THRESH || rec >= TWAI_ERR_PASS_THRESH) ? TWAI_HAL_EVENT_ERROR_PASSIVE : TWAI_HAL_EVENT_ERROR_ACTIVE;
+    //Bus error interrupt triggered on a bus error (e.g. bit, ACK, stuff etc)
+    if (interrupts & TWAI_LL_INTR_BEI) {
+        twai_ll_clear_err_code_cap(hal_ctx->dev);
+        events |= TWAI_HAL_EVENT_BUS_ERR;
     }
     //Arbitration Lost Interrupt triggered on losing arbitration
     if (interrupts & TWAI_LL_INTR_ALI) {
+        twai_ll_clear_arb_lost_cap(hal_ctx->dev);
         events |= TWAI_HAL_EVENT_ARB_LOST;
     }
-    //Bus error interrupt triggered on a bus error (e.g. bit, ACK, stuff etc)
-    if (interrupts & TWAI_LL_INTR_BEI) {
-        events |= TWAI_HAL_EVENT_BUS_ERR;
-    }
     return events;
 }
 
@@ -144,4 +174,5 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f
     } else {
         twai_ll_set_cmd_tx(hal_ctx->dev);
     }
+    TWAI_HAL_SET_FLAG(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED);
 }