fix(driver_twai): update example using wait_tx_done api

This commit is contained in:
wanckl
2025-08-15 16:28:59 +08:00
parent 6288067296
commit a690789dcf
4 changed files with 18 additions and 98 deletions

View File

@@ -45,17 +45,17 @@ idf.py -p PORT flash monitor
install twai success install twai success
node started node started
sending frame 0 sending frame 0, please trigger error during sending
sending frame 1 sending frame 1, please trigger error during sending
... ...
sending frame 4 sending frame 4, please trigger error during sending
// Manually trigger error here (disconnect TX/RX or short H/L) // Manually trigger error here (disconnect TX/RX or short H/L)
bus error: 0x2 bus error: 0x2
state changed: error_active -> error_warning state changed: error_active -> error_warning
... ...
sending frame 9 sending frame 9, please trigger error during sending
// Trigger error again // Trigger error again
bus error: 0x2 bus error: 0x2
state changed: error_passive -> bus_off state changed: error_passive -> bus_off
@@ -66,7 +66,7 @@ waiting ... 0
state changed: bus_off -> error_active state changed: bus_off -> error_active
node recovered! continue node recovered! continue
sending frame 0 sending frame 0, please trigger error during sending
``` ```
## Troubleshooting ## Troubleshooting

View File

@@ -89,7 +89,7 @@ void app_main(void)
} }
} }
} else { } else {
ESP_LOGI(TAG, "sending frame %d", i); ESP_LOGI(TAG, "sending frame %d, please trigger error during sending", i);
tx_frame.header.id = i; tx_frame.header.id = i;
ESP_ERROR_CHECK(twai_node_transmit(node_hdl, &tx_frame, 500)); ESP_ERROR_CHECK(twai_node_transmit(node_hdl, &tx_frame, 500));
} }

View File

@@ -34,13 +34,10 @@ typedef struct {
// Transmission completion callback // Transmission completion callback
static IRAM_ATTR bool twai_sender_tx_done_callback(twai_node_handle_t handle, const twai_tx_done_event_data_t *edata, void *user_ctx) static IRAM_ATTR bool twai_sender_tx_done_callback(twai_node_handle_t handle, const twai_tx_done_event_data_t *edata, void *user_ctx)
{ {
BaseType_t woken;
SemaphoreHandle_t *tx_semaphore = (SemaphoreHandle_t *)user_ctx;
if (!edata->is_tx_success) { if (!edata->is_tx_success) {
ESP_EARLY_LOGW(TAG, "Failed to transmit message, ID: 0x%X", edata->done_tx_frame->header.id); ESP_EARLY_LOGW(TAG, "Failed to transmit message, ID: 0x%X", edata->done_tx_frame->header.id);
} }
xSemaphoreGiveFromISR(*tx_semaphore, &woken); return false; // No task wake required
return (woken == pdTRUE);
} }
// Bus error callback // Bus error callback
@@ -53,7 +50,6 @@ static IRAM_ATTR bool twai_sender_on_error_callback(twai_node_handle_t handle, c
void app_main(void) void app_main(void)
{ {
twai_node_handle_t sender_node = NULL; twai_node_handle_t sender_node = NULL;
SemaphoreHandle_t tx_semaphore = NULL;
printf("===================TWAI Sender Example Starting...===================\n"); printf("===================TWAI Sender Example Starting...===================\n");
// Configure TWAI node // Configure TWAI node
@@ -79,15 +75,10 @@ void app_main(void)
.on_tx_done = twai_sender_tx_done_callback, .on_tx_done = twai_sender_tx_done_callback,
.on_error = twai_sender_on_error_callback, .on_error = twai_sender_on_error_callback,
}; };
ESP_ERROR_CHECK(twai_node_register_event_callbacks(sender_node, &callbacks, &tx_semaphore)); ESP_ERROR_CHECK(twai_node_register_event_callbacks(sender_node, &callbacks, NULL));
// Enable TWAI node // Enable TWAI node
ESP_ERROR_CHECK(twai_node_enable(sender_node)); ESP_ERROR_CHECK(twai_node_enable(sender_node));
// Create semaphore for transmission completion
tx_semaphore = xSemaphoreCreateCounting(howmany(TWAI_DATA_LEN, TWAI_FRAME_MAX_LEN), 0);
assert(tx_semaphore != NULL);
ESP_LOGI(TAG, "TWAI Sender started successfully"); ESP_LOGI(TAG, "TWAI Sender started successfully");
ESP_LOGI(TAG, "Sending messages with IDs: 0x%03X (data), 0x%03X (heartbeat)", TWAI_DATA_ID, TWAI_HEARTBEAT_ID); ESP_LOGI(TAG, "Sending messages with IDs: 0x%03X (data), 0x%03X (heartbeat)", TWAI_DATA_ID, TWAI_HEARTBEAT_ID);
@@ -101,7 +92,7 @@ void app_main(void)
}; };
ESP_ERROR_CHECK(twai_node_transmit(sender_node, &tx_frame, 500)); ESP_ERROR_CHECK(twai_node_transmit(sender_node, &tx_frame, 500));
ESP_LOGI(TAG, "Sending heartbeat message: %lld", timestamp); ESP_LOGI(TAG, "Sending heartbeat message: %lld", timestamp);
xSemaphoreTake(tx_semaphore, portMAX_DELAY); ESP_ERROR_CHECK(twai_node_transmit_wait_all_done(sender_node, -1)); // -1 means wait forever
// Send burst data messages every 10 seconds // Send burst data messages every 10 seconds
if ((timestamp / 1000000) % 10 == 0) { if ((timestamp / 1000000) % 10 == 0) {
@@ -118,9 +109,7 @@ void app_main(void)
} }
// Frames mounted, wait for all frames to be transmitted // Frames mounted, wait for all frames to be transmitted
for (int i = 0; i < num_frames; i++) { ESP_ERROR_CHECK(twai_node_transmit_wait_all_done(sender_node, -1));
xSemaphoreTake(tx_semaphore, portMAX_DELAY);
}
free(data); free(data);
} }
@@ -133,7 +122,6 @@ void app_main(void)
} }
} }
vSemaphoreDelete(tx_semaphore);
ESP_ERROR_CHECK(twai_node_disable(sender_node)); ESP_ERROR_CHECK(twai_node_disable(sender_node));
ESP_ERROR_CHECK(twai_node_delete(sender_node)); ESP_ERROR_CHECK(twai_node_delete(sender_node));
} }

View File

@@ -42,66 +42,13 @@ static struct {
static bool twai_send_tx_done_cb(twai_node_handle_t handle, const twai_tx_done_event_data_t *event_data, void *user_ctx) static bool twai_send_tx_done_cb(twai_node_handle_t handle, const twai_tx_done_event_data_t *event_data, void *user_ctx)
{ {
ESP_UNUSED(handle); ESP_UNUSED(handle);
ESP_UNUSED(event_data);
twai_controller_ctx_t *controller = (twai_controller_ctx_t *)user_ctx; twai_controller_ctx_t *controller = (twai_controller_ctx_t *)user_ctx;
/* Signal TX completion */
if (atomic_load(&controller->send_ctx.is_tx_pending)) {
atomic_store(&controller->send_ctx.is_tx_pending, false);
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(controller->send_ctx.tx_done_sem, &xHigherPriorityTaskWoken);
return xHigherPriorityTaskWoken == pdTRUE;
}
return false;
}
/**
* @brief Initialize the send module for a controller
*
* @param[in] controller Pointer to the controller context
*
* @return @c ESP_OK on success, error code on failure
*/
static esp_err_t twai_send_init_controller(twai_controller_ctx_t *controller)
{
int controller_id = controller - &g_twai_controller_ctx[0]; int controller_id = controller - &g_twai_controller_ctx[0];
/* Create TX completion semaphore */ if (!event_data->is_tx_success) {
controller->send_ctx.tx_done_sem = xSemaphoreCreateBinary(); ESP_EARLY_LOGW(TAG, "Node %d: Bus error when sending frame with ID: 0x%X", controller_id, event_data->done_tx_frame->header.id);
if (controller->send_ctx.tx_done_sem == NULL) {
ESP_LOGE(TAG, "Failed to create TX semaphore for controller %d", controller_id);
return ESP_ERR_NO_MEM;
} }
return false;
/* Initialize TX pending flag */
atomic_init(&controller->send_ctx.is_tx_pending, false);
/* Register TX done callback */
twai_core_ctx_t *core_ctx = &controller->core_ctx;
core_ctx->driver_cbs.on_tx_done = twai_send_tx_done_cb;
return ESP_OK;
}
/**
* @brief Deinitialize the send module for a controller
*
* @param[in] controller Pointer to the controller context
*/
static void twai_send_deinit_controller(twai_controller_ctx_t *controller)
{
/* Clear pending flag */
atomic_store(&controller->send_ctx.is_tx_pending, false);
/* Delete TX completion semaphore */
if (controller->send_ctx.tx_done_sem) {
vSemaphoreDelete(controller->send_ctx.tx_done_sem);
controller->send_ctx.tx_done_sem = NULL;
}
/* Clear callback */
controller->core_ctx.driver_cbs.on_tx_done = NULL;
} }
/** /**
@@ -115,33 +62,21 @@ static void twai_send_deinit_controller(twai_controller_ctx_t *controller)
*/ */
static esp_err_t send_frame_sync(twai_controller_ctx_t *controller, const twai_frame_t *frame, uint32_t timeout_ms) static esp_err_t send_frame_sync(twai_controller_ctx_t *controller, const twai_frame_t *frame, uint32_t timeout_ms)
{ {
if (!controller) { ESP_RETURN_ON_FALSE(controller, ESP_ERR_INVALID_ARG, TAG, "Invalid controller pointer");
ESP_LOGE(TAG, "Invalid controller pointer");
return ESP_ERR_INVALID_ARG;
}
int controller_id = controller - &g_twai_controller_ctx[0]; int controller_id = controller - &g_twai_controller_ctx[0];
esp_err_t ret = ESP_OK;
twai_core_ctx_t *ctx = &controller->core_ctx; twai_core_ctx_t *ctx = &controller->core_ctx;
/* Check if TWAI driver is running */ /* Check if TWAI driver is running */
ESP_RETURN_ON_FALSE(atomic_load(&ctx->is_initialized), ESP_ERR_INVALID_STATE, TAG, "TWAI%d not initialized", controller_id); ESP_RETURN_ON_FALSE(atomic_load(&ctx->is_initialized), ESP_ERR_INVALID_STATE, TAG, "TWAI%d not initialized", controller_id);
/* Mark TX as pending */
atomic_store(&controller->send_ctx.is_tx_pending, true);
/* Transmit the frame */ /* Transmit the frame */
ret = twai_node_transmit(controller->node_handle, frame, timeout_ms); ESP_RETURN_ON_ERROR(twai_node_transmit(controller->node_handle, frame, timeout_ms), TAG, "Node %d: Failed to queue TX frame", controller_id);
ESP_GOTO_ON_ERROR(ret, err, TAG, "Node %d: Failed to queue TX frame: %s", controller_id, esp_err_to_name(ret));
/* Wait for TX completion or timeout */ /* Wait for TX completion or timeout */
ESP_GOTO_ON_FALSE(xSemaphoreTake(controller->send_ctx.tx_done_sem, pdMS_TO_TICKS(timeout_ms)) == pdTRUE, ESP_ERR_TIMEOUT, err, TAG, ESP_RETURN_ON_ERROR(twai_node_transmit_wait_all_done(controller->node_handle, timeout_ms), TAG, "Node %d: TX not completed after %"PRIu32" ms", controller_id, timeout_ms);
"Node %d: TX timed out after %"PRIu32" ms", controller_id, timeout_ms);
return ESP_OK; return ESP_OK;
err:
atomic_store(&controller->send_ctx.is_tx_pending, false);
return ret;
} }
/** /**
@@ -228,10 +163,7 @@ void register_twai_send_commands(void)
/* Initialize send context for all controllers */ /* Initialize send context for all controllers */
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
twai_controller_ctx_t *controller = &g_twai_controller_ctx[i]; twai_controller_ctx_t *controller = &g_twai_controller_ctx[i];
esp_err_t ret = twai_send_init_controller(controller); controller->core_ctx.driver_cbs.on_tx_done = twai_send_tx_done_cb;
if (ret != ESP_OK) {
ESP_LOGW(TAG, "Failed to initialize send module for TWAI%d: %s", i, esp_err_to_name(ret));
}
} }
/* Register command arguments */ /* Register command arguments */
@@ -270,6 +202,6 @@ void unregister_twai_send_commands(void)
/* Cleanup all controller send modules */ /* Cleanup all controller send modules */
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) { for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
twai_controller_ctx_t *controller = &g_twai_controller_ctx[i]; twai_controller_ctx_t *controller = &g_twai_controller_ctx[i];
twai_send_deinit_controller(controller); controller->core_ctx.driver_cbs.on_tx_done = NULL;
} }
} }