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
This commit is contained in:
Michael (XIAO Xufeng) 2020-09-03 23:22:30 +08:00
commit 91af5eaf4f
8 changed files with 249 additions and 362 deletions

View File

@ -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

View File

@ -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();

View File

@ -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 -------------------------------- */

View File

@ -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)

View File

@ -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 ------------------------------- */

View File

@ -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 ------------------------------- */

View File

@ -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 -------------------------------- */

View File

@ -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;
}
//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);
}