mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
91af5eaf4f
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user