mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(driver_twai): support using all 4 hardware tx buffer
This commit is contained in:
@@ -231,8 +231,8 @@ static void twai_intr_handler_main(void *arg)
|
|||||||
//Note: This event will never occur if there is a periph reset event
|
//Note: This event will never occur if there is a periph reset event
|
||||||
twai_handle_rx_buffer_frames(p_twai_obj, &task_woken, &alert_req);
|
twai_handle_rx_buffer_frames(p_twai_obj, &task_woken, &alert_req);
|
||||||
}
|
}
|
||||||
if (events & TWAI_HAL_EVENT_TX_BUFF_FREE) {
|
if (events & TWAI_HAL_EVENT_TX0_DONE) {
|
||||||
twai_handle_tx_buffer_frame(p_twai_obj, (events & TWAI_HAL_EVENT_TX_SUCCESS), &task_woken, &alert_req);
|
twai_handle_tx_buffer_frame(p_twai_obj, (events & TWAI_HAL_EVENT_TX0_SUCCESS), &task_woken, &alert_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Handle events that only require alerting (i.e. no handler)
|
//Handle events that only require alerting (i.e. no handler)
|
||||||
|
|||||||
@@ -60,10 +60,11 @@ typedef struct {
|
|||||||
|
|
||||||
_Atomic twai_error_state_t state;
|
_Atomic twai_error_state_t state;
|
||||||
twai_node_record_t history;
|
twai_node_record_t history;
|
||||||
|
uint8_t tx_slot_num;
|
||||||
|
|
||||||
atomic_bool hw_busy;
|
atomic_bool hw_busy;
|
||||||
atomic_bool rx_isr;
|
atomic_bool rx_isr;
|
||||||
const twai_frame_t *p_curr_tx;
|
const twai_frame_t *p_curr_tx[TWAI_HAL_TX_BUFFER_SLOT_NUM];
|
||||||
twai_hal_frame_t rcv_buff;
|
twai_hal_frame_t rcv_buff;
|
||||||
} twai_onchip_ctx_t;
|
} twai_onchip_ctx_t;
|
||||||
|
|
||||||
@@ -154,9 +155,9 @@ static void _node_release_io(twai_onchip_ctx_t *node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _node_start_trans(twai_onchip_ctx_t *node)
|
static void _node_start_trans(twai_onchip_ctx_t *node, uint8_t buffer_idx)
|
||||||
{
|
{
|
||||||
const twai_frame_t *frame = node->p_curr_tx;
|
const twai_frame_t *frame = node->p_curr_tx[buffer_idx];
|
||||||
twai_hal_context_t *hal = node->hal;
|
twai_hal_context_t *hal = node->hal;
|
||||||
|
|
||||||
twai_hal_frame_t hal_buf = {};
|
twai_hal_frame_t hal_buf = {};
|
||||||
@@ -172,8 +173,40 @@ static void _node_start_trans(twai_onchip_ctx_t *node)
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
twai_hal_format_frame(&hal_trans, &hal_buf);
|
twai_hal_format_frame(&hal_trans, &hal_buf);
|
||||||
//TODO: utilize all txt buffers
|
twai_hal_set_tx_buffer_and_transmit(hal, &hal_buf, buffer_idx);
|
||||||
twai_hal_set_tx_buffer_and_transmit(hal, &hal_buf, 0);
|
}
|
||||||
|
|
||||||
|
static uint8_t _node_start_tx_batch_from_isr(twai_onchip_ctx_t *node, BaseType_t *yield_required)
|
||||||
|
{
|
||||||
|
uint8_t tx_idx = 0;
|
||||||
|
// Note: hardware slot has default priority (like 0>1>2...),
|
||||||
|
// we should fill slot with same order to avoid data inverse
|
||||||
|
while (tx_idx < node->tx_slot_num) { // try best to fill all tx slots
|
||||||
|
const twai_frame_t *frame = NULL;
|
||||||
|
if (xQueueReceiveFromISR(node->tx_mount_queue, &frame, yield_required) != pdTRUE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node->p_curr_tx[tx_idx] = frame;
|
||||||
|
_node_start_trans(node, tx_idx);
|
||||||
|
tx_idx++;
|
||||||
|
}
|
||||||
|
return tx_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _node_mark_tx_idle(twai_onchip_ctx_t *node)
|
||||||
|
{
|
||||||
|
memset(node->p_curr_tx, 0, sizeof(node->p_curr_tx));
|
||||||
|
atomic_store(&node->hw_busy, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _node_is_tx_all_done(twai_onchip_ctx_t *node)
|
||||||
|
{
|
||||||
|
for (uint8_t tx_idx = 0; tx_idx < node->tx_slot_num; tx_idx++) {
|
||||||
|
if (node->p_curr_tx[tx_idx]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _node_isr_main(void *arg)
|
static void _node_isr_main(void *arg)
|
||||||
@@ -221,11 +254,10 @@ static void _node_isr_main(void *arg)
|
|||||||
}
|
}
|
||||||
// node recover from busoff, restart remain tx transaction
|
// node recover from busoff, restart remain tx transaction
|
||||||
if ((e_data.old_sta == TWAI_ERROR_BUS_OFF) && (e_data.new_sta == TWAI_ERROR_ACTIVE)) {
|
if ((e_data.old_sta == TWAI_ERROR_BUS_OFF) && (e_data.new_sta == TWAI_ERROR_ACTIVE)) {
|
||||||
if (xQueueReceiveFromISR(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx, &do_yield)) {
|
if (_node_start_tx_batch_from_isr(twai_ctx, &do_yield)) {
|
||||||
atomic_store(&twai_ctx->hw_busy, true);
|
atomic_store(&twai_ctx->hw_busy, true);
|
||||||
_node_start_trans(twai_ctx);
|
|
||||||
} else {
|
} else {
|
||||||
atomic_store(&twai_ctx->hw_busy, false);
|
_node_mark_tx_idle(twai_ctx);
|
||||||
xEventGroupSetBitsFromISR(twai_ctx->event_group, TWAI_IDLE_EVENT_BIT, &do_yield);
|
xEventGroupSetBitsFromISR(twai_ctx->event_group, TWAI_IDLE_EVENT_BIT, &do_yield);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,21 +289,27 @@ static void _node_isr_main(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deal TX event
|
// deal TX event
|
||||||
if (events & TWAI_HAL_EVENT_TX_BUFF_FREE) {
|
if (events & TWAI_HAL_EVENT_TX_DONE_MASK) {
|
||||||
if (twai_ctx->cbs.on_tx_done) {
|
uint32_t tx_done_events = (events & TWAI_HAL_EVENT_TX_DONE_MASK) >> __builtin_ctz(TWAI_HAL_EVENT_TX0_DONE);
|
||||||
twai_tx_done_event_data_t tx_ev = {
|
while (tx_done_events) {
|
||||||
.is_tx_success = (events & TWAI_HAL_EVENT_TX_SUCCESS), // find 'on_error_cb' if not success
|
uint32_t slot_event = tx_done_events & -tx_done_events; // get the lowest event bit
|
||||||
.done_tx_frame = twai_ctx->p_curr_tx,
|
uint8_t tx_idx = __builtin_ctz(slot_event) / 2;
|
||||||
};
|
assert((tx_idx < twai_ctx->tx_slot_num) && twai_ctx->p_curr_tx[tx_idx]);
|
||||||
do_yield |= twai_ctx->cbs.on_tx_done(&twai_ctx->api_base, &tx_ev, twai_ctx->user_data);
|
if (twai_ctx->cbs.on_tx_done) {
|
||||||
|
twai_tx_done_event_data_t tx_ev = {
|
||||||
|
.is_tx_success = (events & TWAI_HAL_EVENT_TX_SUCC_SLOT(tx_idx)), // find 'on_error_cb' if not success
|
||||||
|
.done_tx_frame = twai_ctx->p_curr_tx[tx_idx],
|
||||||
|
};
|
||||||
|
do_yield |= twai_ctx->cbs.on_tx_done(&twai_ctx->api_base, &tx_ev, twai_ctx->user_data);
|
||||||
|
}
|
||||||
|
twai_ctx->p_curr_tx[tx_idx] = NULL;
|
||||||
|
tx_done_events &= ~slot_event;
|
||||||
}
|
}
|
||||||
// start a new TX
|
|
||||||
if ((atomic_load(&twai_ctx->state) != TWAI_ERROR_BUS_OFF) && xQueueReceiveFromISR(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx, &do_yield)) {
|
// start a new TX batch only when all hardware TX buffers from this batch are done
|
||||||
_node_start_trans(twai_ctx);
|
if (_node_is_tx_all_done(twai_ctx) && (atomic_load(&twai_ctx->state) != TWAI_ERROR_BUS_OFF)) {
|
||||||
} else {
|
if (!_node_start_tx_batch_from_isr(twai_ctx, &do_yield)) {
|
||||||
atomic_store(&twai_ctx->hw_busy, false);
|
_node_mark_tx_idle(twai_ctx);
|
||||||
if (atomic_load(&twai_ctx->state) != TWAI_ERROR_BUS_OFF) {
|
|
||||||
// only when node is not in busoff here, means tx is finished
|
|
||||||
xEventGroupSetBitsFromISR(twai_ctx->event_group, TWAI_IDLE_EVENT_BIT, &do_yield);
|
xEventGroupSetBitsFromISR(twai_ctx->event_group, TWAI_IDLE_EVENT_BIT, &do_yield);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -447,7 +485,11 @@ static esp_err_t _node_enable(twai_node_handle_t node)
|
|||||||
atomic_store(&twai_ctx->state, hw_state);
|
atomic_store(&twai_ctx->state, hw_state);
|
||||||
// continuing the transaction if there be
|
// continuing the transaction if there be
|
||||||
if (atomic_load(&twai_ctx->hw_busy) && hw_state != TWAI_ERROR_BUS_OFF) {
|
if (atomic_load(&twai_ctx->hw_busy) && hw_state != TWAI_ERROR_BUS_OFF) {
|
||||||
_node_start_trans(twai_ctx);
|
for (uint8_t tx_idx = 0; tx_idx < twai_ctx->tx_slot_num; tx_idx++) {
|
||||||
|
if (twai_ctx->p_curr_tx[tx_idx]) {
|
||||||
|
_node_start_trans(twai_ctx, tx_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_enable(twai_ctx->intr_hdl), TAG, "enable interrupt failed");
|
ESP_RETURN_ON_ERROR(esp_intr_enable(twai_ctx->intr_hdl), TAG, "enable interrupt failed");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -567,8 +609,8 @@ static esp_err_t _node_queue_tx(twai_node_handle_t node, const twai_frame_t *fra
|
|||||||
xEventGroupClearBits(twai_ctx->event_group, TWAI_IDLE_EVENT_BIT); //going to send, clear the idle event
|
xEventGroupClearBits(twai_ctx->event_group, TWAI_IDLE_EVENT_BIT); //going to send, clear the idle event
|
||||||
bool false_var = false;
|
bool false_var = false;
|
||||||
if (atomic_compare_exchange_strong(&twai_ctx->hw_busy, &false_var, true)) {
|
if (atomic_compare_exchange_strong(&twai_ctx->hw_busy, &false_var, true)) {
|
||||||
twai_ctx->p_curr_tx = frame;
|
twai_ctx->p_curr_tx[0] = frame; // here only has one frame, using slot 0
|
||||||
_node_start_trans(twai_ctx);
|
_node_start_trans(twai_ctx, 0);
|
||||||
} else {
|
} else {
|
||||||
// Hardware busy, need to queue the frame
|
// Hardware busy, need to queue the frame
|
||||||
BaseType_t is_isr_context = xPortInIsrContext();
|
BaseType_t is_isr_context = xPortInIsrContext();
|
||||||
@@ -587,13 +629,12 @@ static esp_err_t _node_queue_tx(twai_node_handle_t node, const twai_frame_t *fra
|
|||||||
if (atomic_compare_exchange_strong(&twai_ctx->hw_busy, &false_var, true)) {
|
if (atomic_compare_exchange_strong(&twai_ctx->hw_busy, &false_var, true)) {
|
||||||
BaseType_t dequeue_result;
|
BaseType_t dequeue_result;
|
||||||
if (is_isr_context) {
|
if (is_isr_context) {
|
||||||
dequeue_result = xQueueReceiveFromISR(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx, &yield_required);
|
dequeue_result = xQueueReceiveFromISR(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx[0], &yield_required);
|
||||||
} else {
|
} else {
|
||||||
dequeue_result = xQueueReceive(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx, 0);
|
dequeue_result = xQueueReceive(twai_ctx->tx_mount_queue, &twai_ctx->p_curr_tx[0], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dequeue_result == pdTRUE) {
|
if (dequeue_result == pdTRUE) {
|
||||||
_node_start_trans(twai_ctx);
|
_node_start_trans(twai_ctx, 0);
|
||||||
} else {
|
} else {
|
||||||
// any reason here means frame already taken and maybe finished by fast hardware, so back `hw_busy` to false
|
// any reason here means frame already taken and maybe finished by fast hardware, so back `hw_busy` to false
|
||||||
atomic_store(&twai_ctx->hw_busy, false);
|
atomic_store(&twai_ctx->hw_busy, false);
|
||||||
@@ -755,6 +796,11 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
|||||||
.enable_loopback = node_config->flags.enable_loopback,
|
.enable_loopback = node_config->flags.enable_loopback,
|
||||||
};
|
};
|
||||||
ESP_GOTO_ON_FALSE(twai_hal_init(node->hal, &hal_config), ESP_ERR_INVALID_STATE, err, TAG, "hardware not in reset state");
|
ESP_GOTO_ON_FALSE(twai_hal_init(node->hal, &hal_config), ESP_ERR_INVALID_STATE, err, TAG, "hardware not in reset state");
|
||||||
|
node->tx_slot_num = twai_hal_get_tx_slot_num(node->hal);
|
||||||
|
if (node->tx_slot_num > TWAI_HAL_TX_BUFFER_SLOT_NUM) {
|
||||||
|
ESP_LOGW(TAG, "HW TX slot num (%d) is greater than supported, only using %d slots", node->tx_slot_num, TWAI_HAL_TX_BUFFER_SLOT_NUM);
|
||||||
|
node->tx_slot_num = TWAI_HAL_TX_BUFFER_SLOT_NUM;
|
||||||
|
}
|
||||||
// Configure bus timing
|
// Configure bus timing
|
||||||
ESP_GOTO_ON_ERROR(_node_calc_set_bit_timing(&node->api_base, &node_config->bit_timing, &node_config->data_timing), err, TAG, "bitrate error");
|
ESP_GOTO_ON_ERROR(_node_calc_set_bit_timing(&node->api_base, &node_config->bit_timing, &node_config->data_timing), err, TAG, "bitrate error");
|
||||||
// Configure GPIO
|
// Configure GPIO
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ entries:
|
|||||||
esp_twai_onchip: _node_isr_main (noflash)
|
esp_twai_onchip: _node_isr_main (noflash)
|
||||||
esp_twai_onchip: _node_start_trans (noflash)
|
esp_twai_onchip: _node_start_trans (noflash)
|
||||||
esp_twai_onchip: _node_parse_rx (noflash)
|
esp_twai_onchip: _node_parse_rx (noflash)
|
||||||
|
esp_twai_onchip: _node_start_tx_batch_from_isr (noflash)
|
||||||
|
esp_twai_onchip: _node_mark_tx_idle (noflash)
|
||||||
|
esp_twai_onchip: _node_is_tx_all_done (noflash)
|
||||||
|
|
||||||
if TWAI_IO_FUNC_IN_IRAM = y:
|
if TWAI_IO_FUNC_IN_IRAM = y:
|
||||||
esp_twai_onchip: _node_queue_tx (noflash)
|
esp_twai_onchip: _node_queue_tx (noflash)
|
||||||
|
|||||||
@@ -194,12 +194,12 @@ TEST_CASE("twai fd transmit time (loopback)", "[twai]")
|
|||||||
}
|
}
|
||||||
uint64_t predict_time_ms = (uint64_t)trans_num * arb_bits * 1000 / node_config.bit_timing.bitrate;
|
uint64_t predict_time_ms = (uint64_t)trans_num * arb_bits * 1000 / node_config.bit_timing.bitrate;
|
||||||
predict_time_ms += (uint64_t)trans_num * data_bits * 1000 / node_config.data_timing.bitrate;
|
predict_time_ms += (uint64_t)trans_num * data_bits * 1000 / node_config.data_timing.bitrate;
|
||||||
predict_time_ms += (trans_num * 20) / 1000; // add about 20 us interrupt overhead per frame
|
predict_time_ms += (trans_num * 10) / 1000; // add about 10 us interrupt overhead per frame
|
||||||
#if CONFIG_COMPILER_OPTIMIZATION_NONE
|
#if CONFIG_COMPILER_OPTIMIZATION_NONE
|
||||||
predict_time_ms += (trans_num * 10) / 1000; // non optimized slow code
|
predict_time_ms += (trans_num * 5) / 1000; // non optimized slow code
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_PM_DFS_INIT_AUTO
|
#if CONFIG_PM_DFS_INIT_AUTO
|
||||||
predict_time_ms += (trans_num * 35) / 1000; // slow cpu
|
predict_time_ms += (trans_num * 10) / 1000; // slow cpu
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//waiting pkg receive finish
|
//waiting pkg receive finish
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -700,6 +700,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -626,6 +626,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -48,6 +48,10 @@
|
|||||||
#define TWAIFD_LL_TX_CMD_READY TWAIFD_TXCR // Set tx buffer to "Ready" state
|
#define TWAIFD_LL_TX_CMD_READY TWAIFD_TXCR // Set tx buffer to "Ready" state
|
||||||
#define TWAIFD_LL_TX_CMD_ABORT TWAIFD_TXCA // Set tx buffer to "Aborted" state
|
#define TWAIFD_LL_TX_CMD_ABORT TWAIFD_TXCA // Set tx buffer to "Aborted" state
|
||||||
|
|
||||||
|
#define TWAIFD_LL_TX_STATUS_SUCCESS 0x4 // TX buffer transmitted successfully
|
||||||
|
#define TWAIFD_LL_TX_STATUS_FAILED 0x6 // TX buffer transmission failed
|
||||||
|
#define TWAIFD_LL_TX_STATUS_ABORTED 0x7 // TX buffer transmission aborted
|
||||||
|
|
||||||
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
|
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
|
||||||
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
|
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
|
||||||
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
|
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
|
||||||
@@ -665,11 +669,10 @@ static inline uint32_t twaifd_ll_get_tx_buffer_total(twaifd_dev_t *hw)
|
|||||||
* @param buffer_idx Index of the TX buffer (0-7).
|
* @param buffer_idx Index of the TX buffer (0-7).
|
||||||
* @return The status of the selected TX buffer.
|
* @return The status of the selected TX buffer.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
|
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
|
||||||
{
|
{
|
||||||
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
|
return (hw->tx_status.val >> (TWAIFD_TX2S_S * buffer_idx)) & TWAIFD_TX2S_V;
|
||||||
uint32_t reg_val = hw->tx_status.val;
|
|
||||||
return reg_val & (TWAIFD_TX2S_V << (TWAIFD_TX2S_S * buffer_idx)); // Get status for buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -700,7 +703,6 @@ static inline void twaifd_ll_set_tx_buffer_cmd(twaifd_dev_t *hw, uint8_t buffer_
|
|||||||
*/
|
*/
|
||||||
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
|
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
|
||||||
{
|
{
|
||||||
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
|
|
||||||
uint32_t reg_val = hw->tx_priority.val;
|
uint32_t reg_val = hw->tx_priority.val;
|
||||||
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
|
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
|
||||||
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
|
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -636,6 +636,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -614,6 +614,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -614,6 +614,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -48,6 +48,10 @@
|
|||||||
#define TWAIFD_LL_TX_CMD_READY TWAIFD_TXCR // Set tx buffer to "Ready" state
|
#define TWAIFD_LL_TX_CMD_READY TWAIFD_TXCR // Set tx buffer to "Ready" state
|
||||||
#define TWAIFD_LL_TX_CMD_ABORT TWAIFD_TXCA // Set tx buffer to "Aborted" state
|
#define TWAIFD_LL_TX_CMD_ABORT TWAIFD_TXCA // Set tx buffer to "Aborted" state
|
||||||
|
|
||||||
|
#define TWAIFD_LL_TX_STATUS_SUCCESS 0x4 // TX buffer transmitted successfully
|
||||||
|
#define TWAIFD_LL_TX_STATUS_FAILED 0x6 // TX buffer transmission failed
|
||||||
|
#define TWAIFD_LL_TX_STATUS_ABORTED 0x7 // TX buffer transmission aborted
|
||||||
|
|
||||||
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
|
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
|
||||||
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
|
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
|
||||||
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
|
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
|
||||||
@@ -664,11 +668,10 @@ static inline uint32_t twaifd_ll_get_tx_buffer_total(twaifd_dev_t *hw)
|
|||||||
* @param buffer_idx Index of the TX buffer (0-7).
|
* @param buffer_idx Index of the TX buffer (0-7).
|
||||||
* @return The status of the selected TX buffer.
|
* @return The status of the selected TX buffer.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
|
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
|
||||||
{
|
{
|
||||||
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
|
return (hw->tx_status.val >> (TWAIFD_TX2S_S * buffer_idx)) & TWAIFD_TX2S_V;
|
||||||
uint32_t reg_val = hw->tx_status.val;
|
|
||||||
return reg_val & (TWAIFD_TX2S_V << (TWAIFD_TX2S_S * buffer_idx)); // Get status for buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -699,7 +702,6 @@ static inline void twaifd_ll_set_tx_buffer_cmd(twaifd_dev_t *hw, uint8_t buffer_
|
|||||||
*/
|
*/
|
||||||
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
|
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
|
||||||
{
|
{
|
||||||
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
|
|
||||||
uint32_t reg_val = hw->tx_priority.val;
|
uint32_t reg_val = hw->tx_priority.val;
|
||||||
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
|
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
|
||||||
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
|
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -679,6 +679,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -629,6 +629,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -626,6 +626,17 @@ static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_
|
|||||||
|
|
||||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers that are preset in the hardware.
|
||||||
|
*
|
||||||
|
* @param hw Pointer to the TWAI-FD device hardware.
|
||||||
|
* @return The number of TX buffers available.
|
||||||
|
*/
|
||||||
|
static inline uint32_t twai_ll_get_tx_buffer_total(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return 1; // only one TX buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -46,6 +46,10 @@
|
|||||||
#define TWAIFD_LL_TX_CMD_READY TWAIFD_TXCR // Set tx buffer to "Ready" state
|
#define TWAIFD_LL_TX_CMD_READY TWAIFD_TXCR // Set tx buffer to "Ready" state
|
||||||
#define TWAIFD_LL_TX_CMD_ABORT TWAIFD_TXCA // Set tx buffer to "Aborted" state
|
#define TWAIFD_LL_TX_CMD_ABORT TWAIFD_TXCA // Set tx buffer to "Aborted" state
|
||||||
|
|
||||||
|
#define TWAIFD_LL_TX_STATUS_SUCCESS 0x4 // TX buffer transmitted successfully
|
||||||
|
#define TWAIFD_LL_TX_STATUS_FAILED 0x6 // TX buffer transmission failed
|
||||||
|
#define TWAIFD_LL_TX_STATUS_ABORTED 0x7 // TX buffer transmission aborted
|
||||||
|
|
||||||
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
|
#define TWAIFD_LL_HW_CMD_RST_ERR_CNT TWAIFD_ERCRST // Error Counters Reset
|
||||||
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
|
#define TWAIFD_LL_HW_CMD_RST_RX_CNT TWAIFD_RXFCRST // Clear RX bus traffic counter
|
||||||
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
|
#define TWAIFD_LL_HW_CMD_RST_TX_CNT TWAIFD_TXFCRST // Clear TX bus traffic counter
|
||||||
@@ -662,11 +666,10 @@ static inline uint32_t twaifd_ll_get_tx_buffer_total(twaifd_dev_t *hw)
|
|||||||
* @param buffer_idx Index of the TX buffer (0-7).
|
* @param buffer_idx Index of the TX buffer (0-7).
|
||||||
* @return The status of the selected TX buffer.
|
* @return The status of the selected TX buffer.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
|
static inline uint32_t twaifd_ll_get_tx_buffer_status(twaifd_dev_t *hw, uint8_t buffer_idx)
|
||||||
{
|
{
|
||||||
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
|
return (hw->tx_status.val >> (TWAIFD_TX2S_S * buffer_idx)) & TWAIFD_TX2S_V;
|
||||||
uint32_t reg_val = hw->tx_status.val;
|
|
||||||
return reg_val & (TWAIFD_TX2S_V << (TWAIFD_TX2S_S * buffer_idx)); // Get status for buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -697,7 +700,6 @@ static inline void twaifd_ll_set_tx_buffer_cmd(twaifd_dev_t *hw, uint8_t buffer_
|
|||||||
*/
|
*/
|
||||||
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
|
static inline void twaifd_ll_set_tx_buffer_priority(twaifd_dev_t *hw, uint8_t buffer_idx, uint32_t priority)
|
||||||
{
|
{
|
||||||
HAL_ASSERT(buffer_idx < twaifd_ll_get_tx_buffer_total(hw)); // Ensure buffer index is valid
|
|
||||||
uint32_t reg_val = hw->tx_priority.val;
|
uint32_t reg_val = hw->tx_priority.val;
|
||||||
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
|
reg_val &= ~(TWAIFD_TXT1P_V << (TWAIFD_TXT2P_S * buffer_idx)); // Clear old priority
|
||||||
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
|
reg_val |= priority << (TWAIFD_TXT2P_S * buffer_idx); // Set new priority
|
||||||
|
|||||||
@@ -50,9 +50,29 @@ typedef union twai_ll_frame_buffer_t twai_hal_frame_t;
|
|||||||
#define TWAI_HAL_EVENT_BUS_ERR (1 << 7)
|
#define TWAI_HAL_EVENT_BUS_ERR (1 << 7)
|
||||||
#define TWAI_HAL_EVENT_ARB_LOST (1 << 8)
|
#define TWAI_HAL_EVENT_ARB_LOST (1 << 8)
|
||||||
#define TWAI_HAL_EVENT_RX_BUFF_FRAME (1 << 9)
|
#define TWAI_HAL_EVENT_RX_BUFF_FRAME (1 << 9)
|
||||||
#define TWAI_HAL_EVENT_TX_BUFF_FREE (1 << 10)
|
#define TWAI_HAL_EVENT_NEED_PERIPH_RESET (1 << 10)
|
||||||
#define TWAI_HAL_EVENT_NEED_PERIPH_RESET (1 << 11)
|
#define TWAI_HAL_EVENT_TX0_DONE (1 << 11)
|
||||||
#define TWAI_HAL_EVENT_TX_SUCCESS (1 << 12)
|
#define TWAI_HAL_EVENT_TX0_SUCCESS (1 << 12)
|
||||||
|
#define TWAI_HAL_EVENT_TX1_DONE (1 << 13)
|
||||||
|
#define TWAI_HAL_EVENT_TX1_SUCCESS (1 << 14)
|
||||||
|
#define TWAI_HAL_EVENT_TX2_DONE (1 << 15)
|
||||||
|
#define TWAI_HAL_EVENT_TX2_SUCCESS (1 << 16)
|
||||||
|
#define TWAI_HAL_EVENT_TX3_DONE (1 << 17)
|
||||||
|
#define TWAI_HAL_EVENT_TX3_SUCCESS (1 << 18)
|
||||||
|
#define TWAI_HAL_EVENT_TX4_DONE (1 << 19)
|
||||||
|
#define TWAI_HAL_EVENT_TX4_SUCCESS (1 << 20)
|
||||||
|
#define TWAI_HAL_EVENT_TX5_DONE (1 << 21)
|
||||||
|
#define TWAI_HAL_EVENT_TX5_SUCCESS (1 << 22)
|
||||||
|
#define TWAI_HAL_EVENT_TX6_DONE (1 << 23)
|
||||||
|
#define TWAI_HAL_EVENT_TX6_SUCCESS (1 << 24)
|
||||||
|
#define TWAI_HAL_EVENT_TX7_DONE (1 << 25)
|
||||||
|
#define TWAI_HAL_EVENT_TX7_SUCCESS (1 << 26)
|
||||||
|
#define TWAI_HAL_TX_BUFFER_SLOT_NUM 8 // support up to 8 TX slots in hal layer
|
||||||
|
|
||||||
|
#define TWAI_HAL_EVENT_TX_DONE_MASK (TWAI_HAL_EVENT_TX0_DONE | TWAI_HAL_EVENT_TX1_DONE | TWAI_HAL_EVENT_TX2_DONE | TWAI_HAL_EVENT_TX3_DONE | \
|
||||||
|
TWAI_HAL_EVENT_TX4_DONE | TWAI_HAL_EVENT_TX5_DONE | TWAI_HAL_EVENT_TX6_DONE | TWAI_HAL_EVENT_TX7_DONE)
|
||||||
|
#define TWAI_HAL_EVENT_TX_DONE_SLOT(buffer_idx) (TWAI_HAL_EVENT_TX0_DONE << ((buffer_idx) * 2))
|
||||||
|
#define TWAI_HAL_EVENT_TX_SUCC_SLOT(buffer_idx) (TWAI_HAL_EVENT_TX0_SUCCESS << ((buffer_idx) * 2))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
twai_soc_handle_t dev; // TWAI SOC layer handle (i.e. register base address)
|
twai_soc_handle_t dev; // TWAI SOC layer handle (i.e. register base address)
|
||||||
@@ -61,6 +81,7 @@ typedef struct {
|
|||||||
uint32_t timer_overflow_cnt;
|
uint32_t timer_overflow_cnt;
|
||||||
twai_error_flags_t errors;
|
twai_error_flags_t errors;
|
||||||
uint8_t sja1000_filter_id_type; // hardware don't check id type, check in software, 0:no_filter, 1: std_id_only, 2: ext_id_only
|
uint8_t sja1000_filter_id_type; // hardware don't check id type, check in software, 0:no_filter, 1: std_id_only, 2: ext_id_only
|
||||||
|
uint8_t tx_buffer_num;
|
||||||
int8_t retry_cnt;
|
int8_t retry_cnt;
|
||||||
bool enable_self_test;
|
bool enable_self_test;
|
||||||
bool enable_loopback;
|
bool enable_loopback;
|
||||||
@@ -296,6 +317,14 @@ static inline twai_error_flags_t twai_hal_get_err_flags(twai_hal_context_t *hal_
|
|||||||
*/
|
*/
|
||||||
uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx);
|
uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of TX buffers supported by the hardware
|
||||||
|
*
|
||||||
|
* @param hal_ctx Context of the HAL layer
|
||||||
|
* @return TX buffer count
|
||||||
|
*/
|
||||||
|
#define twai_hal_get_tx_slot_num(hal_ctx) (hal_ctx->tx_buffer_num)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief TWAI hal transaction description type
|
* @brief TWAI hal transaction description type
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config)
|
|||||||
if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers
|
if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
hal_ctx->tx_buffer_num = twai_ll_get_tx_buffer_total(hal_ctx->dev);
|
||||||
#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE
|
#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE
|
||||||
hal_ctx->errata_ctx = (twai_hal_errata_ctx_t *)(hal_ctx + 1); //errata context is place at end of hal_ctx
|
hal_ctx->errata_ctx = (twai_hal_errata_ctx_t *)(hal_ctx + 1); //errata context is place at end of hal_ctx
|
||||||
#endif
|
#endif
|
||||||
@@ -238,10 +239,10 @@ static inline uint32_t twai_hal_decode_interrupt(twai_hal_context_t *hal_ctx)
|
|||||||
#else
|
#else
|
||||||
if (interrupts & TWAI_LL_INTR_TI) {
|
if (interrupts & TWAI_LL_INTR_TI) {
|
||||||
#endif
|
#endif
|
||||||
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_TX_BUFF_FREE);
|
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_TX0_DONE);
|
||||||
TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED);
|
TWAI_HAL_CLEAR_BITS(state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED);
|
||||||
if (status & TWAI_LL_STATUS_TCS) {
|
if (status & TWAI_LL_STATUS_TCS) {
|
||||||
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_TX_SUCCESS);
|
TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_TX0_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Error Passive Interrupt on transition from error active to passive or vice versa
|
//Error Passive Interrupt on transition from error active to passive or vice versa
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config)
|
|||||||
hal_ctx->enable_listen_only = config->enable_listen_only;
|
hal_ctx->enable_listen_only = config->enable_listen_only;
|
||||||
|
|
||||||
twaifd_ll_reset(hal_ctx->dev);
|
twaifd_ll_reset(hal_ctx->dev);
|
||||||
|
hal_ctx->tx_buffer_num = twaifd_ll_get_tx_buffer_total(hal_ctx->dev);
|
||||||
twaifd_ll_enable_hw(hal_ctx->dev, false); //mode should be changed under disabled
|
twaifd_ll_enable_hw(hal_ctx->dev, false); //mode should be changed under disabled
|
||||||
twaifd_ll_set_mode(hal_ctx->dev, config->enable_listen_only, config->enable_self_test, config->enable_loopback);
|
twaifd_ll_set_mode(hal_ctx->dev, config->enable_listen_only, config->enable_self_test, config->enable_loopback);
|
||||||
twaifd_ll_set_tx_retrans_limit(hal_ctx->dev, config->retry_cnt);
|
twaifd_ll_set_tx_retrans_limit(hal_ctx->dev, config->retry_cnt);
|
||||||
@@ -222,9 +223,20 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx)
|
|||||||
hal_ctx->timer_overflow_cnt ++;
|
hal_ctx->timer_overflow_cnt ++;
|
||||||
}
|
}
|
||||||
if (int_stat & (TWAIFD_LL_INTR_TX_DONE)) {
|
if (int_stat & (TWAIFD_LL_INTR_TX_DONE)) {
|
||||||
hal_events |= TWAI_HAL_EVENT_TX_BUFF_FREE;
|
for (uint32_t i = 0; i < MIN(hal_ctx->tx_buffer_num, TWAI_HAL_TX_BUFFER_SLOT_NUM); i++) {
|
||||||
if (int_stat & TWAIFD_LL_INTR_TX_FRAME) {
|
uint32_t tx_status = twaifd_ll_get_tx_buffer_status(hal_ctx->dev, i);
|
||||||
hal_events |= TWAI_HAL_EVENT_TX_SUCCESS;
|
switch (tx_status) {
|
||||||
|
case TWAIFD_LL_TX_STATUS_SUCCESS:
|
||||||
|
hal_events |= TWAI_HAL_EVENT_TX_SUCC_SLOT(i);
|
||||||
|
__attribute__((fallthrough)); // success event must be a done event, just fallthrough
|
||||||
|
case TWAIFD_LL_TX_STATUS_FAILED:
|
||||||
|
case TWAIFD_LL_TX_STATUS_ABORTED:
|
||||||
|
hal_events |= TWAI_HAL_EVENT_TX_DONE_SLOT(i);
|
||||||
|
twaifd_ll_set_tx_buffer_cmd(hal_ctx->dev, i, TWAIFD_LL_TX_CMD_EMPTY); // clear buffer to empty state
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (int_stat & TWAIFD_LL_INTR_RX_NOT_EMPTY) {
|
if (int_stat & TWAIFD_LL_INTR_RX_NOT_EMPTY) {
|
||||||
|
|||||||
Reference in New Issue
Block a user