mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-03 02:20:57 +02:00
fix(driver_twai): update example using wait_tx_done api
This commit is contained in:
@@ -45,17 +45,17 @@ idf.py -p PORT flash monitor
|
||||
install twai success
|
||||
node started
|
||||
|
||||
sending frame 0
|
||||
sending frame 1
|
||||
sending frame 0, please trigger error during sending
|
||||
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)
|
||||
bus error: 0x2
|
||||
state changed: error_active -> error_warning
|
||||
|
||||
...
|
||||
sending frame 9
|
||||
sending frame 9, please trigger error during sending
|
||||
// Trigger error again
|
||||
bus error: 0x2
|
||||
state changed: error_passive -> bus_off
|
||||
@@ -66,7 +66,7 @@ waiting ... 0
|
||||
state changed: bus_off -> error_active
|
||||
node recovered! continue
|
||||
|
||||
sending frame 0
|
||||
sending frame 0, please trigger error during sending
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
@@ -89,7 +89,7 @@ void app_main(void)
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
ESP_ERROR_CHECK(twai_node_transmit(node_hdl, &tx_frame, 500));
|
||||
}
|
||||
|
@@ -34,13 +34,10 @@ typedef struct {
|
||||
// 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)
|
||||
{
|
||||
BaseType_t woken;
|
||||
SemaphoreHandle_t *tx_semaphore = (SemaphoreHandle_t *)user_ctx;
|
||||
if (!edata->is_tx_success) {
|
||||
ESP_EARLY_LOGW(TAG, "Failed to transmit message, ID: 0x%X", edata->done_tx_frame->header.id);
|
||||
}
|
||||
xSemaphoreGiveFromISR(*tx_semaphore, &woken);
|
||||
return (woken == pdTRUE);
|
||||
return false; // No task wake required
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
twai_node_handle_t sender_node = NULL;
|
||||
SemaphoreHandle_t tx_semaphore = NULL;
|
||||
printf("===================TWAI Sender Example Starting...===================\n");
|
||||
|
||||
// Configure TWAI node
|
||||
@@ -79,15 +75,10 @@ void app_main(void)
|
||||
.on_tx_done = twai_sender_tx_done_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
|
||||
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, "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_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
|
||||
if ((timestamp / 1000000) % 10 == 0) {
|
||||
@@ -118,9 +109,7 @@ void app_main(void)
|
||||
}
|
||||
|
||||
// Frames mounted, wait for all frames to be transmitted
|
||||
for (int i = 0; i < num_frames; i++) {
|
||||
xSemaphoreTake(tx_semaphore, portMAX_DELAY);
|
||||
}
|
||||
ESP_ERROR_CHECK(twai_node_transmit_wait_all_done(sender_node, -1));
|
||||
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_delete(sender_node));
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
ESP_UNUSED(handle);
|
||||
ESP_UNUSED(event_data);
|
||||
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];
|
||||
|
||||
/* Create TX completion semaphore */
|
||||
controller->send_ctx.tx_done_sem = xSemaphoreCreateBinary();
|
||||
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;
|
||||
if (!event_data->is_tx_success) {
|
||||
ESP_EARLY_LOGW(TAG, "Node %d: Bus error when sending frame with ID: 0x%X", controller_id, event_data->done_tx_frame->header.id);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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)
|
||||
{
|
||||
if (!controller) {
|
||||
ESP_LOGE(TAG, "Invalid controller pointer");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(controller, ESP_ERR_INVALID_ARG, TAG, "Invalid controller pointer");
|
||||
|
||||
int controller_id = controller - &g_twai_controller_ctx[0];
|
||||
esp_err_t ret = ESP_OK;
|
||||
twai_core_ctx_t *ctx = &controller->core_ctx;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Mark TX as pending */
|
||||
atomic_store(&controller->send_ctx.is_tx_pending, true);
|
||||
|
||||
/* Transmit the frame */
|
||||
ret = twai_node_transmit(controller->node_handle, frame, timeout_ms);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "Node %d: Failed to queue TX frame: %s", controller_id, esp_err_to_name(ret));
|
||||
ESP_RETURN_ON_ERROR(twai_node_transmit(controller->node_handle, frame, timeout_ms), TAG, "Node %d: Failed to queue TX frame", controller_id);
|
||||
|
||||
/* 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,
|
||||
"Node %d: TX timed out after %"PRIu32" ms", controller_id, timeout_ms);
|
||||
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);
|
||||
|
||||
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 */
|
||||
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
|
||||
twai_controller_ctx_t *controller = &g_twai_controller_ctx[i];
|
||||
esp_err_t ret = twai_send_init_controller(controller);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to initialize send module for TWAI%d: %s", i, esp_err_to_name(ret));
|
||||
}
|
||||
controller->core_ctx.driver_cbs.on_tx_done = twai_send_tx_done_cb;
|
||||
}
|
||||
|
||||
/* Register command arguments */
|
||||
@@ -270,6 +202,6 @@ void unregister_twai_send_commands(void)
|
||||
/* Cleanup all controller send modules */
|
||||
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; 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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user