mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'fix/twai_queue_remain_and_doc_v5.5' into 'release/v5.5'
fix(driver_twai): improve error logging in _node_queue_tx function (v5.5) See merge request espressif/esp-idf!44478
This commit is contained in:
@@ -569,6 +569,7 @@ static esp_err_t _node_get_status(twai_node_handle_t node, twai_node_status_t *s
|
||||
status_ret->state = atomic_load(&twai_ctx->state);
|
||||
status_ret->tx_error_count = twai_hal_get_tec(twai_ctx->hal);
|
||||
status_ret->rx_error_count = twai_hal_get_rec(twai_ctx->hal);
|
||||
status_ret->tx_queue_remaining = uxQueueSpacesAvailable(twai_ctx->tx_mount_queue);
|
||||
}
|
||||
if (record_ret) {
|
||||
*record_ret = twai_ctx->history;
|
||||
@@ -582,7 +583,7 @@ static esp_err_t _node_queue_tx(twai_node_handle_t node, const twai_frame_t *fra
|
||||
{
|
||||
twai_onchip_ctx_t *twai_ctx = __containerof(node, twai_onchip_ctx_t, api_base);
|
||||
if (frame->header.dlc && frame->buffer_len) {
|
||||
ESP_RETURN_ON_FALSE_ISR(frame->header.dlc == twaifd_len2dlc(frame->buffer_len), ESP_ERR_INVALID_ARG, TAG, "unmatched dlc and buffer_len");
|
||||
ESP_RETURN_ON_FALSE_ISR(frame->header.dlc == twaifd_len2dlc(frame->buffer_len), ESP_ERR_INVALID_ARG, TAG, "unmatched dlc(%i) and buffer_len(%i)", frame->header.dlc, twaifd_len2dlc(frame->buffer_len));
|
||||
}
|
||||
#if !SOC_TWAI_SUPPORT_FD
|
||||
ESP_RETURN_ON_FALSE_ISR(!frame->header.fdf || frame->buffer_len <= TWAI_FRAME_MAX_LEN, ESP_ERR_INVALID_ARG, TAG, "fdf flag or buffer_len not supported");
|
||||
|
||||
@@ -18,7 +18,8 @@ extern "C" {
|
||||
* @brief Enable the TWAI node
|
||||
*
|
||||
* @param node Handle to the TWAI node
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Node already in enabled state
|
||||
*/
|
||||
esp_err_t twai_node_enable(twai_node_handle_t node);
|
||||
|
||||
@@ -26,7 +27,8 @@ esp_err_t twai_node_enable(twai_node_handle_t node);
|
||||
* @brief Disable the TWAI node
|
||||
*
|
||||
* @param node Handle to the TWAI node
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Node not in enabled state
|
||||
*/
|
||||
esp_err_t twai_node_disable(twai_node_handle_t node);
|
||||
|
||||
@@ -35,7 +37,8 @@ esp_err_t twai_node_disable(twai_node_handle_t node);
|
||||
* @note Follow `on_state_change` callback or `twai_node_get_info` to know recover finish or not
|
||||
*
|
||||
* @param node Handle to the TWAI node
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Node not in bus-off state
|
||||
*/
|
||||
esp_err_t twai_node_recover(twai_node_handle_t node);
|
||||
|
||||
@@ -43,7 +46,8 @@ esp_err_t twai_node_recover(twai_node_handle_t node);
|
||||
* @brief Delete the TWAI node and release resources
|
||||
*
|
||||
* @param node Handle to the TWAI node
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Node not in disabled state
|
||||
*/
|
||||
esp_err_t twai_node_delete(twai_node_handle_t node);
|
||||
|
||||
@@ -75,7 +79,9 @@ esp_err_t twai_node_reconfig_timing(twai_node_handle_t node, const twai_timing_a
|
||||
* @param node Handle to the TWAI node
|
||||
* @param filter_id Index of the filter to configure
|
||||
* @param mask_cfg Pointer to the mask filter configuration
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Node not in disabled state
|
||||
*/
|
||||
esp_err_t twai_node_config_mask_filter(twai_node_handle_t node, uint8_t filter_id, const twai_mask_filter_config_t *mask_cfg);
|
||||
|
||||
@@ -85,7 +91,9 @@ esp_err_t twai_node_config_mask_filter(twai_node_handle_t node, uint8_t filter_i
|
||||
* @param node Handle to the TWAI node
|
||||
* @param filter_id Index of the filter to configure
|
||||
* @param range_cfg Pointer to the range filter configuration
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Node not in disabled state
|
||||
*/
|
||||
esp_err_t twai_node_config_range_filter(twai_node_handle_t node, uint8_t filter_id, const twai_range_filter_config_t *range_cfg);
|
||||
|
||||
@@ -107,7 +115,11 @@ esp_err_t twai_node_get_info(twai_node_handle_t node, twai_node_status_t *status
|
||||
* @param[in] node Handle to the TWAI node
|
||||
* @param[in] frame Pointer to the frame to transmit
|
||||
* @param[in] timeout_ms Maximum wait time if the transmission queue is full (milliseconds), -1 to wait forever
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Node already in bus-off state
|
||||
* - ESP_ERR_NOT_SUPPORTED: Node is config as listen only
|
||||
* - ESP_ERR_TIMEOUT: Timeout to wait for queue space
|
||||
*/
|
||||
esp_err_t twai_node_transmit(twai_node_handle_t node, const twai_frame_t *frame, int timeout_ms);
|
||||
|
||||
@@ -116,7 +128,9 @@ esp_err_t twai_node_transmit(twai_node_handle_t node, const twai_frame_t *frame,
|
||||
*
|
||||
* @param[in] node Handle to the TWAI node
|
||||
* @param[in] timeout_ms Maximum wait time for all pending transfers to finish (milliseconds), -1 to wait forever
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Node already in bus-off state
|
||||
* - ESP_ERR_TIMEOUT: Timeout
|
||||
*/
|
||||
esp_err_t twai_node_transmit_wait_all_done(twai_node_handle_t node, int timeout_ms);
|
||||
|
||||
@@ -129,7 +143,8 @@ esp_err_t twai_node_transmit_wait_all_done(twai_node_handle_t node, int timeout_
|
||||
*
|
||||
* @param[in] node Handle to the TWAI node
|
||||
* @param[out] rx_frame Pointer to the frame store rx content
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
* @return - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Called from a task or from other callbacks except `rx_done_cb`
|
||||
*/
|
||||
esp_err_t twai_node_receive_from_isr(twai_node_handle_t node, twai_frame_t *rx_frame);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef struct {
|
||||
twai_error_state_t state; /**< Node's error state */
|
||||
uint16_t tx_error_count; /**< Node's TX error count */
|
||||
uint16_t rx_error_count; /**< Node's RX error count */
|
||||
uint32_t tx_queue_remaining; /**< Node's TX queue remaining frame space (number of frames) */
|
||||
} twai_node_status_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -230,7 +230,11 @@ TEST_CASE("twai transmit stop resume (loopback)", "[twai]")
|
||||
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||
|
||||
//waiting pkg receive finish
|
||||
TEST_ESP_OK(twai_node_transmit_wait_all_done(node_hdl, -1));
|
||||
twai_node_status_t status = {};
|
||||
while (status.tx_queue_remaining < TEST_TWAI_QUEUE_DEPTH) {
|
||||
TEST_ESP_OK(twai_node_get_info(node_hdl, &status, NULL));
|
||||
printf("%ld\n", status.tx_queue_remaining);
|
||||
}
|
||||
free(tx_msgs);
|
||||
|
||||
// check if pkg receive correct
|
||||
|
||||
@@ -103,7 +103,12 @@ TWAI messages come in various types, which are specified by their headers. A typ
|
||||
.. image:: ../../../_static/diagrams/twai/frame_struct.svg
|
||||
:align: center
|
||||
|
||||
To reduce performance overhead caused by memory copying, the TWAI driver uses pointers to pass messages. The following code demonstrates how to transmit a typical data frame:
|
||||
To reduce performance overhead caused by memory copying, the TWAI driver uses pointers to pass messages. The driver is designed to operate in asynchronous mode, so the :cpp:type:`twai_frame_t` structure and the memory pointed to by :cpp:member:`twai_frame_t::buffer` must remain valid until the transmission is actually complete. You can determine when transmission is complete in the following ways:
|
||||
|
||||
- Call the :cpp:func:`twai_node_transmit_wait_all_done` function to wait for all transmissions to complete.
|
||||
- Register the :cpp:member:`twai_event_callbacks_t::on_tx_done` event callback function to receive a notification when transmission is complete.
|
||||
|
||||
The following code demonstrates how to transmit a typical data frame:
|
||||
|
||||
.. code:: c
|
||||
|
||||
@@ -200,7 +205,7 @@ The TWAI driver supports transmitting messages from an Interrupt Service Routine
|
||||
}
|
||||
|
||||
.. note::
|
||||
When calling :cpp:func:`twai_node_transmit` from an ISR, the ``timeout`` parameter is ignored, and the function will not block. If the transmit queue is full, the function will return immediately with an error. It is the application's responsibility to handle cases where the queue is full.
|
||||
When calling :cpp:func:`twai_node_transmit` from an ISR, the ``timeout`` parameter is ignored, and the function will not block. If the transmit queue is full, the function will return immediately with an error. It is the application's responsibility to handle cases where the queue is full. Similarly, the ``twai_frame_t`` structure and the memory pointed to by ``buffer`` must remain valid until the transmission is complete. You can get the completed frame by the :cpp:member:`twai_tx_done_event_data_t::done_tx_frame` pointer.
|
||||
|
||||
Bit Timing Customization
|
||||
------------------------
|
||||
@@ -311,7 +316,7 @@ The TWAI controller can detect errors caused by bus interference or corrupted fr
|
||||
- **Error Passive**: When either TEC or REC is greater than or equal to 128, the node enters the passive error state. It can still communicate on the bus but sends only one **passive error flag** when detecting errors.
|
||||
- **Bus Off**: When **TEC** is greater than or equal to 256, the node enters the bus off (offline) state. The node is effectively disconnected and does not affect the bus. It remains offline until recovery is triggered by software.
|
||||
|
||||
Software can retrieve the node status anytime via the function :cpp:func:`twai_node_get_info`. When the controller detects errors, it triggers the :cpp:member:`twai_event_callbacks_t::on_error` callback, where the error data provides detailed information.
|
||||
Software can retrieve the node status from tasks via the function :cpp:func:`twai_node_get_info`. When the controller detects errors, it triggers the :cpp:member:`twai_event_callbacks_t::on_error` callback, where the error data provides detailed information.
|
||||
|
||||
When the node’s error state changes, the :cpp:member:`twai_event_callbacks_t::on_state_change` callback is triggered, allowing the application to respond to the state transition. If the node is offline and needs recovery, call :cpp:func:`twai_node_recover` from a task context. **Note that recovery is not immediate; the controller will automatically reconnect to the bus only after detecting 129 consecutive recessive bits (11 bits each).**
|
||||
|
||||
|
||||
@@ -103,7 +103,12 @@ TWAI 报文有多种类型,由报头指定。一个典型的数据帧报文主
|
||||
.. image:: ../../../_static/diagrams/twai/frame_struct.svg
|
||||
:align: center
|
||||
|
||||
为减少拷贝带来的性能损失,TWAI 驱动使用指针进行传递。以下代码展示了如何发送一条典型的数据帧报文:
|
||||
为减少拷贝带来的性能损失,TWAI 驱动使用指针进行传递。且驱动设计为异步模式,因此,在传输真正完成之前, :cpp:type:`twai_frame_t` 实体及其 :cpp:member:`twai_frame_t::buffer` 指向的内存必须保持有效。可通过以下方式得知传输完成:
|
||||
|
||||
- 调用 :cpp:func:`twai_node_transmit_wait_all_done` 函数等待所有传输完成。
|
||||
- 注册 :cpp:member:`twai_event_callbacks_t::on_tx_done` 事件回调函数,在传输完成时接收通知。
|
||||
|
||||
以下代码展示了如何发送一条典型的数据帧报文:
|
||||
|
||||
.. code:: c
|
||||
|
||||
@@ -200,7 +205,7 @@ TWAI 驱动支持在中断服务程序 (ISR) 中发送报文。这对于需要
|
||||
}
|
||||
|
||||
.. note::
|
||||
在 ISR 中调用 :cpp:func:`twai_node_transmit` 时,``timeout`` 参数将被忽略,函数不会阻塞。如果发送队列已满,函数将立即返回错误。应用程序需要自行处理队列已满的情况。
|
||||
在 ISR 中调用 :cpp:func:`twai_node_transmit` 时,``timeout`` 参数将被忽略,函数不会阻塞。如果发送队列已满,函数将立即返回错误。应用程序需要自行处理队列已满的情况。同样,``twai_frame_t`` 及其 ``buffer`` 指向的内存必须在 **该传输** 完成之前保持有效。通过 :cpp:member:`twai_tx_done_event_data_t::done_tx_frame` 指针可得知该次完成的报文。
|
||||
|
||||
位时序自定义
|
||||
-------------
|
||||
@@ -311,7 +316,7 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
- **被动错误:** 当 TEC 或 REC 中的一个大于或等于 128 时,节点处于被动错误状态。仍可以参与总线通信,但在检测到错误时,只能发送一次 **被动错误标志**。
|
||||
- **离线:** 当 **TEC** 大于或等于 256 时,节点进入离线状态。离线的节点相当于断开连接,不会对总线产生任何影响。节点将保持离线状态,直到软件触发恢复操作。
|
||||
|
||||
软件可随时使用函数 :cpp:func:`twai_node_get_info` 获取节点状态。或当控制器检测到错误时,会产生 :cpp:member:`twai_event_callbacks_t::on_error` 回调,可通过传参中的错误数据查看错误原因。
|
||||
软件可随时在 task 中使用函数 :cpp:func:`twai_node_get_info` 获取节点状态。或当控制器检测到错误时,会产生 :cpp:member:`twai_event_callbacks_t::on_error` 回调,可通过传参中的错误数据查看错误原因。
|
||||
|
||||
当错误导致节点状态变化时,会进入 :cpp:member:`twai_event_callbacks_t::on_state_change` 回调,可在回调中查看节点的状态变化。若节点已经离线且需要恢复,需要在task中调用 :cpp:func:`twai_node_recover`。 **但注意,控制器不会立即恢复** ,需要在检测到 129 次连续 11 个隐性位后才会自动重新连接到总线。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user