diff --git a/components/driver/include/driver/twai.h b/components/driver/include/driver/twai.h index 5313d9532f..383a995648 100644 --- a/components/driver/include/driver/twai.h +++ b/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 diff --git a/components/driver/twai.c b/components/driver/twai.c index bb79ab959a..393bc86971 100644 --- a/components/driver/twai.c +++ b/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); - - if (event & TWAI_HAL_EVENT_BUS_OFF) { - twai_handle_bus_off(&alert_req); - } - if (event & TWAI_HAL_EVENT_BUS_RECOV_CPLT) { - twai_handle_recovery_complete(&alert_req); - } - if (event & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) { - twai_handle_recovery_in_progress(&alert_req); - } - if (event & TWAI_HAL_EVENT_ABOVE_EWL) { - twai_handle_above_ewl(&alert_req); - } - if (event & TWAI_HAL_EVENT_BELOW_EWL) { - twai_handle_below_ewl(&alert_req); - } - if (event & TWAI_HAL_EVENT_ERROR_PASSIVE) { - twai_handle_error_passive(&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); - } - if (event & TWAI_HAL_EVENT_ARB_LOST) { - twai_handle_arb_lost(&alert_req); - } + 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 related handlers should be called last, so that other commands - //do not overwrite the TX command related bits in the command register. + //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) { + 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) { + //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_ERR) { + p_twai_obj->bus_error_count++; + twai_alert_handler(TWAI_ALERT_BUS_ERROR, &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_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) { + //Entered error passive + twai_alert_handler(TWAI_ALERT_ERR_PASS, &alert_req); + } + if (event & TWAI_HAL_EVENT_ERROR_ACTIVE) { + //Returned to error active + twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, &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); + } + 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 + p_twai_obj->tx_msg_count = 0; + twai_hal_start(&twai_context, p_twai_obj->mode); - //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); - - 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(); diff --git a/components/hal/esp32/include/hal/can_hal.h b/components/hal/esp32/include/hal/can_hal.h index 9a1c12464d..fa587681bd 100644 --- a/components/hal/esp32/include/hal/can_hal.h +++ b/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); } +static inline bool can_hal_check_state_flags(can_hal_context_t *hal_ctx, uint32_t check_flags) +{ + return twai_hal_check_state_flags(hal_ctx, check_flags); +} + /* ----------------------------- 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) -{ - return twai_hal_handle_bus_recov_cplt(hal_ctx); -} - -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); -} - -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 -------------------------------- */ diff --git a/components/hal/esp32/include/hal/can_ll.h b/components/hal/esp32/include/hal/can_ll.h index 9fa4817924..5cbd10273d 100644 --- a/components/hal/esp32/include/hal/can_ll.h +++ b/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) diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index c82692af54..4c61140641 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/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_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) -#define TWAI_LL_INTR_TI (0x1 << 1) -#define TWAI_LL_INTR_EI (0x1 << 2) +#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 ------------------------------- */ diff --git a/components/hal/esp32s2/include/hal/twai_ll.h b/components/hal/esp32s2/include/hal/twai_ll.h index 2c05b4f54c..5291dd4ae3 100644 --- a/components/hal/esp32s2/include/hal/twai_ll.h +++ b/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_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) -#define TWAI_LL_INTR_TI (0x1 << 1) -#define TWAI_LL_INTR_EI (0x1 << 2) +#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 ------------------------------- */ diff --git a/components/hal/include/hal/twai_hal.h b/components/hal/include/hal/twai_hal.h index 592c01680d..13d49b95ef 100644 --- a/components/hal/include/hal/twai_hal.h +++ b/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); } +/** + * @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 check_flags Bit mask of flags to check + * @return True if one or more of the flags in check_flags are set + */ + +static inline bool twai_hal_check_state_flags(twai_hal_context_t *hal_ctx, uint32_t check_flags) +{ + return hal_ctx->state_flags & check_flags; +} + /* ----------------------------- 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. + * 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 - * @param bus_recovering Whether the TWAI peripheral was previous undergoing bus recovery * @return Bit mask of events that have occurred */ -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) -{ - return twai_ll_enter_reset_mode((hal_ctx)->dev); -} - -/** - * @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); -} - -/** - * @brief Handle BUS OFF - * - * This function should be called on a BUS OFF event. It simply changes the - * mode to LOM to freeze REC - * - * @param hal_ctx Context of the HAL layer - */ -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 -------------------------------- */ diff --git a/components/hal/twai_hal.c b/components/hal/twai_hal.c index d8944273dd..3cad944731 100644 --- a/components/hal/twai_hal.c +++ b/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 #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; - } - //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; - } 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); - } + TWAI_HAL_RESET_FLAG(hal_ctx->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) { - events |= (tec >= TWAI_ERR_PASS_THRESH || rec >= TWAI_ERR_PASS_THRESH) ? TWAI_HAL_EVENT_ERROR_PASSIVE : TWAI_HAL_EVENT_ERROR_ACTIVE; - } - //Arbitration Lost Interrupt triggered on losing arbitration - if (interrupts & TWAI_LL_INTR_ALI) { - events |= TWAI_HAL_EVENT_ARB_LOST; + 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 { + events |= TWAI_HAL_EVENT_ERROR_ACTIVE; + TWAI_HAL_RESET_FLAG(hal_ctx->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_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; + } 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); }