mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
TWAI: Track HW state in HAL
This commit refactors the TWAI HAL such that it now tracks harwdare state instead of the driver layer. Some HAL and LL cleanup was also done.
This commit is contained in:
@@ -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
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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 -------------------------------- */
|
||||
|
@@ -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)
|
||||
|
@@ -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 ------------------------------- */
|
||||
|
@@ -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 ------------------------------- */
|
||||
|
@@ -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 -------------------------------- */
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user