docs: add headings for twai and gptimer api reference

Closes https://github.com/espressif/esp-idf/issues/17891
This commit is contained in:
Wang
2025-11-24 17:16:02 +08:00
parent afc3741ec4
commit c13ebc1643
4 changed files with 144 additions and 82 deletions
+33 -18
View File
@@ -1,3 +1,4 @@
===============================
General Purpose Timer (GPTimer)
===============================
@@ -11,7 +12,7 @@ This document introduces the features of the General Purpose Timer (GPTimer) dri
:depth: 2
Overview
--------
========
GPTimer is a dedicated driver for the {IDF_TARGET_NAME} [`Timer Group peripheral <{IDF_TARGET_TRM_EN_URL}#timg>`__]. This timer can select different clock sources and prescalers to meet the requirements of nanosecond-level resolution. Additionally, it has flexible timeout alarm functions and allows automatic updating of the count value at the alarm moment, achieving very precise timing cycles.
@@ -24,7 +25,7 @@ Based on the **high resolution, high count range, and high response** capabiliti
- etc.
Quick Start
-----------
===========
This section provides a concise overview of how to use the GPTimer driver. Through practical examples, it demonstrates how to initialize and start a timer, configure alarm events, and register callback functions. The typical usage flow is as follows:
@@ -54,7 +55,7 @@ This section provides a concise overview of how to use the GPTimer driver. Throu
}
Creating and Starting a Timer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-----------------------------
First, we need to create a timer instance. The following code shows how to create a timer with a resolution of 1 MHz:
@@ -104,7 +105,7 @@ The :cpp:func:`gptimer_start` and :cpp:func:`gptimer_stop` functions follow the
However, note that when the timer is in the **intermediate state** of starting (the start has begun but not yet completed), if another thread calls the :cpp:func:`gptimer_start` or :cpp:func:`gptimer_stop` function, it will return the :c:macro:`ESP_ERR_INVALID_STATE` error to avoid triggering uncertain behavior.
Setting and Getting the Count Value
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-----------------------------------
When a timer is newly created, its internal counter value defaults to zero. You can set other count values using the :cpp:func:`gptimer_set_raw_count` function. The maximum count value depends on the bit width of the hardware timer (usually no less than ``54 bits``).
@@ -126,7 +127,7 @@ The :cpp:func:`gptimer_get_raw_count` function is used to get the current count
double time = (double)count / resolution_hz;
Triggering Periodic Alarm Events
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--------------------------------
In addition to the timestamp function, the general-purpose timer also supports alarm functions. The following code shows how to set a periodic alarm that triggers once per second:
@@ -194,7 +195,7 @@ The supported event callback functions for GPTimer are as follows:
Be sure to register the callback function before calling :cpp:func:`gptimer_enable`, otherwise the timer event will not correctly trigger the interrupt service.
Triggering One-Shot Alarm Events
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--------------------------------
Some application scenarios only require triggering a one-shot alarm interrupt. The following code shows how to set a one-shot alarm that triggers after 1 second:
@@ -242,17 +243,17 @@ Some application scenarios only require triggering a one-shot alarm interrupt. T
Unlike periodic alarms, the above code disables the auto-reload function when configuring the alarm behavior. This means that after the alarm event occurs, the timer will not automatically reload to the preset count value but will continue counting until it overflows. If you want the timer to stop immediately after the alarm, you can call :cpp:func:`gptimer_stop` in the callback function.
Resource Recycling
^^^^^^^^^^^^^^^^^^
------------------
When the timer is no longer needed, you should call the :cpp:func:`gptimer_delete_timer` function to release software and hardware resources. Before deleting, ensure that the timer is already stopped.
Advanced Features
-----------------
=================
After understanding the basic usage, we can further explore more features of the GPTimer driver.
Dynamic Alarm Value Update
^^^^^^^^^^^^^^^^^^^^^^^^^^
--------------------------
The GPTimer driver supports dynamically updating the alarm value in the interrupt callback function by calling the :cpp:func:`gptimer_set_alarm_action` function, thereby implementing a monotonic software timer list. The following code shows how to reset the next alarm trigger time when the alarm event occurs:
@@ -300,7 +301,7 @@ The GPTimer driver supports dynamically updating the alarm value in the interrup
.. _gptimer-etm-event-and-task:
GPTimer's ETM Events and Tasks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
------------------------------
GPTimer can generate various events that can be connected to the :doc:`ETM </api-reference/peripherals/etm>` module. The event types are listed in :cpp:type:`gptimer_etm_event_type_t`. Users can create an ``ETM event`` handle by calling :cpp:func:`gptimer_new_etm_event`.
GPTimer also supports some tasks that can be triggered by other events and executed automatically. The task types are listed in :cpp:type:`gptimer_etm_task_type_t`. Users can create an ``ETM task`` handle by calling :cpp:func:`gptimer_new_etm_task`.
@@ -308,7 +309,7 @@ The GPTimer driver supports dynamically updating the alarm value in the interrup
For how to connect the timer events and tasks to the ETM channel, please refer to the :doc:`ETM </api-reference/peripherals/etm>` documentation.
Power Management
^^^^^^^^^^^^^^^^
----------------
When power management :ref:`CONFIG_PM_ENABLE` is enabled, the system may adjust or disable the clock source before entering sleep mode, causing the GPTimer to lose accuracy.
@@ -319,7 +320,7 @@ To prevent this, the GPTimer driver creates a power management lock internally.
Besides disabling the clock source, the system can also power down the GPTimer before entering sleep mode to further reduce power consumption. To achieve this, set :cpp:member:`gptimer_config_t::allow_pd` to ``true``. Before the system enters sleep mode, the GPTimer register context will be backed up to memory and restored after the system wakes up. Note that enabling this option reduces power consumption but increases memory usage. Therefore, you need to balance power consumption and memory usage when using this feature.
Thread Safety
^^^^^^^^^^^^^
-------------
The driver uses critical sections to ensure atomic operations on registers. Key members in the driver handle are also protected by critical sections. The driver's internal state machine uses atomic instructions to ensure thread safety, with state checks preventing certain invalid concurrent operations (e.g., conflicts between `start` and `stop`). Therefore, GPTimer driver APIs can be used in a multi-threaded environment without extra locking.
@@ -335,7 +336,7 @@ The following functions can also be used in an interrupt context:
- :cpp:func:`gptimer_set_alarm_action`
Cache Safety
^^^^^^^^^^^^
------------
When the file system performs Flash read/write operations, the system temporarily disables the Cache function to avoid errors when loading instructions and data from Flash. This causes the GPTimer interrupt handler to be unresponsive during this period, preventing the user callback function from executing in time. If you want the interrupt handler to run normally when the Cache is disabled, you can enable the :ref:`CONFIG_GPTIMER_ISR_CACHE_SAFE` option.
@@ -344,7 +345,7 @@ When the file system performs Flash read/write operations, the system temporaril
Note that when this option is enabled, all interrupt callback functions and their context data **must be placed in internal storage**. This is because the system cannot load data and instructions from Flash when the Cache is disabled.
Performance
^^^^^^^^^^^
-----------
To improve the real-time responsiveness of interrupt handling, the GPTimer driver provides the :ref:`CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM` option. Once enabled, the interrupt handler is placed in internal RAM, reducing delays caused by potential cache misses when loading instructions from Flash.
@@ -355,12 +356,12 @@ To improve the real-time responsiveness of interrupt handling, the GPTimer drive
As mentioned above, the GPTimer driver allows some functions to be called in an interrupt context. By enabling the :ref:`CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` option, these functions can also be placed in IRAM, which helps avoid performance loss caused by cache misses and allows them to be used when the Cache is disabled.
Other Kconfig Options
^^^^^^^^^^^^^^^^^^^^^
---------------------
- The :ref:`CONFIG_GPTIMER_ENABLE_DEBUG_LOG` option forces the GPTimer driver to enable all debug logs, regardless of the global log level settings. Enabling this option helps developers obtain more detailed log information during debugging, making it easier to locate and solve problems.
Resource Consumption
^^^^^^^^^^^^^^^^^^^^
--------------------
Use the :doc:`/api-guides/tools/idf-size` tool to check the code and data consumption of the GPTimer driver. The following are the test conditions (using ESP32-C2 as an example):
@@ -386,7 +387,7 @@ Use the :doc:`/api-guides/tools/idf-size` tool to check the code and data consum
Additionally, each GPTimer handle dynamically allocates about ``100`` bytes of memory from the heap. If the :cpp:member:`gptimer_config_t::flags::allow_pd` option is enabled, each timer will also consume approximately ``30`` extra bytes of memory during sleep to store the register context.
Application Examples
--------------------
====================
.. list::
@@ -395,12 +396,26 @@ Application Examples
:SOC_TIMER_SUPPORT_ETM: - :example:`peripherals/timer_group/gptimer_capture_hc_sr04` demonstrates how to use the general-purpose timer and Event Task Matrix (ETM) to accurately capture timestamps of ultrasonic sensor events and convert them into distance information.
API Reference
-------------
=============
GPTimer Driver APIs
-------------------
.. include-build-file:: inc/gptimer.inc
GPTimer Driver Types
--------------------
.. include-build-file:: inc/gptimer_types.inc
GPTimer HAL Types
-----------------
.. include-build-file:: inc/timer_types.inc
GPTimer ETM APIs
----------------
.. only:: SOC_TIMER_SUPPORT_ETM
.. include-build-file:: inc/gptimer_etm.inc
+39 -23
View File
@@ -1,3 +1,4 @@
====================================
Two-Wire Automotive Interface (TWAI)
====================================
@@ -10,7 +11,7 @@ This document introduces the features of the Two-Wire Automotive Interface (TWAI
:depth: 2
Overview
--------
========
TWAI is a highly reliable, multi-master, real-time, serial asynchronous communication protocol designed for automotive and industrial applications. It is compatible with the frame structure defined in the ISO 11898-1 standard and supports both standard frames with 11-bit identifiers and extended frames with 29-bit identifiers. The protocol supports message prioritization with lossless arbitration, automatic retransmission, and fault confinement mechanisms. The {IDF_TARGET_NAME} includes {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} TWAI controllers, allowing for the creation of {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} driver instances.
@@ -30,7 +31,7 @@ Thanks to its hardware-based fault tolerance and multi-master architecture, the
- Acting as a bridging node alongside other communication protocols
Getting Started
---------------
===============
This section provides a quick overview of how to use the TWAI driver. Through simple examples, it demonstrates how to create a TWAI node instance, transmit and receive messages on the bus, and safely stop and uninstall the driver. The general usage flow is as follows:
@@ -38,7 +39,7 @@ This section provides a quick overview of how to use the TWAI driver. Through si
:align: center
Hardware Connection
^^^^^^^^^^^^^^^^^^^
-------------------
The {IDF_TARGET_NAME} does not integrate an internal TWAI transceiver. Therefore, an external transceiver is required to connect to a TWAI bus. The model of the external transceiver depends on the physical layer standard used in your specific application. For example, a TJA105x transceiver can be used to comply with the ISO 11898-2 standard.
@@ -53,7 +54,7 @@ Specifically:
- CLK_OUT (optional): Outputs the time quantum clock of the controller, which is a divided version of the source clock.
Creating and Starting a TWAI Node
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------------
First, we need to create a TWAI instance. The following code demonstrates how to create a TWAI node with a baud rate of 200kHz:
@@ -95,7 +96,7 @@ The :cpp:func:`twai_node_enable` function starts the TWAI controller. Once enabl
The corresponding function, :cpp:func:`twai_node_disable`, immediately stops the node and disconnects it from the bus. Any ongoing transmissions will be aborted. When the node is re-enabled later, if there are pending transmissions in the queue, the driver will immediately initiate a new transmission attempt.
Transmitting Messages
^^^^^^^^^^^^^^^^^^^^^
---------------------
TWAI messages come in various types, which are specified by their headers. A typical data frame consists primarily of a header and data payload, with a structure similar to the following:
@@ -130,7 +131,7 @@ The :cpp:type:`twai_frame_t` message structure also includes other configuration
- :cpp:member:`twai_frame_t::header::esi`: For received frames, indicates the error state of the transmitting node.
Receiving Messages
^^^^^^^^^^^^^^^^^^
------------------
Receiving messages must be done within a receive event callback. Therefore, to receive messages, you need to register a receive event callback via :cpp:member:`twai_event_callbacks_t::on_rx_done` before starting the controller. This enables the controller to deliver received messages via the callback when events occur. The following code snippets demonstrate how to register the receive event callback and how to handle message reception inside the callback:
@@ -163,12 +164,12 @@ Receiving messages inside the callback:
Similarly, since the driver uses pointers for message passing, you must configure the pointer :cpp:member:`twai_frame_t::buffer` and its memory length :cpp:member:`twai_frame_t::buffer_len` before receiving.
Stopping and Deleting the Node
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
------------------------------
When the TWAI node is no longer needed, you should call :cpp:func:`twai_node_delete` to release software and hardware resources. Make sure the TWAI controller is stopped before deleting the node.
Advanced Features
-----------------
=================
After understanding the basic usage, you can further explore more advanced capabilities of the TWAI driver. The driver supports more detailed controller configuration and error feedback features. The complete driver feature diagram is shown below:
@@ -176,7 +177,7 @@ After understanding the basic usage, you can further explore more advanced capab
:align: center
Transmit from ISR
^^^^^^^^^^^^^^^^^
-----------------
The TWAI driver supports transmitting messages from an Interrupt Service Routine (ISR). This is particularly useful for applications requiring low-latency responses or periodic transmissions triggered by hardware timers. For example, you can trigger a new transmission from within the ``on_tx_done`` callback, which is executed in an ISR context.
@@ -202,7 +203,7 @@ The TWAI driver supports transmitting messages from an Interrupt Service Routine
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.
Bit Timing Customization
^^^^^^^^^^^^^^^^^^^^^^^^
------------------------
Unlike other asynchronous communication protocols, the TWAI controller performs counting and sampling within one bit time in units of **Time Quanta (Tq)**. The number of time quanta per bit determines the final baud rate and the sample point position. When signal quality is poor, you can manually fine-tune these timing segments to meet specific requirements. The time quanta within a bit time are divided into different segments, as illustrated below:
@@ -247,10 +248,10 @@ When manually configuring these timing segments, it is important to pay attentio
Different combinations of ``brp``, ``prop_seg``, ``tseg_1``, ``tseg_2``, and ``sjw`` can achieve the same baud rate. Users should consider factors such as **propagation delay, node processing time, and phase errors**, and adjust the timing parameters based on the physical characteristics of the bus.
Filter Configuration
^^^^^^^^^^^^^^^^^^^^^
---------------------
Mask Filters
""""""""""""
^^^^^^^^^^^^
The TWAI controller hardware can filter messages based on their ID to reduce software and hardware overhead, thereby improving node efficiency. Nodes that filter out certain messages will **not receive those messages, but will still send acknowledgments (ACKs)**.
@@ -279,7 +280,7 @@ The following code demonstrates how to calculate the MASK and configure a filter
.. only:: not SOC_TWAI_SUPPORT_FD
Dual Filter Mode
""""""""""""""""
^^^^^^^^^^^^^^^^
{IDF_TARGET_NAME} supports dual filter mode, which allows the hardware to be configured as two parallel independent 16-bit mask filters. By enabling this, more IDs can be received. Note that using dual filter mode to filter 29-bit extended IDs, each filter can only filter the upper 16 bits of the ID, while the remaining 13 bits are not filtered. The following code demonstrates how to configure dual filter mode using the function :cpp:func:`twai_make_dual_filter`:
@@ -293,7 +294,7 @@ The following code demonstrates how to calculate the MASK and configure a filter
.. only:: SOC_TWAI_SUPPORT_FD
Range Filter
""""""""""""
^^^^^^^^^^^^
{IDF_TARGET_NAME} also includes 1 range filter, which exists alongside the mask filters. You can configure the desired ID reception range directly using the function :cpp:func:`twai_node_config_range_filter`. The details are as follows:
@@ -301,7 +302,7 @@ The following code demonstrates how to calculate the MASK and configure a filter
- Configuring an invalid range means no messages will be received.
Bus Errors and Recovery
^^^^^^^^^^^^^^^^^^^^^^^
-----------------------
The TWAI controller can detect errors caused by bus interference or corrupted frames that do not conform to the frame format. It implements a fault isolation mechanism using transmit and receive error counters (TEC and REC). The values of these counters determine the node's error state: Error Active, Error Warning, Error Passive, and Bus Off. This mechanism ensures that nodes with persistent errors eventually disconnect themselves from the bus.
@@ -317,12 +318,12 @@ When the nodes error state changes, the :cpp:member:`twai_event_callbacks_t::
When recovery completes, the :cpp:member:`twai_event_callbacks_t::on_state_change` callback will be triggered again, the node changes its state from :cpp:enumerator:`TWAI_ERROR_BUS_OFF` to :cpp:enumerator:`TWAI_ERROR_ACTIVE`. A recovered node can immediately resume transmissions; if there are pending tasks in the transmit queue, the driver will start transmitting them right away.
Power Management
^^^^^^^^^^^^^^^^
----------------
When power management is enabled via :ref:`CONFIG_PM_ENABLE`, the system may adjust or disable clock sources before entering sleep mode, which could cause TWAI to malfunction. To prevent this, the driver manages a power management lock internally. This lock is acquired when calling :cpp:func:`twai_node_enable`, ensuring the system does not enter sleep mode and TWAI remains functional. To allow the system to enter a low-power state, call :cpp:func:`twai_node_disable` to release the lock. During sleep, the TWAI controller will also stop functioning.
Cache Safety
^^^^^^^^^^^^
------------
During Flash write operations, the system temporarily disables cache to prevent instruction and data fetch errors from Flash. This can cause interrupt handlers stored in Flash to become unresponsive. If you want interrupt routines to remain operational during cache-disabled periods, enable the :ref:`CONFIG_TWAI_ISR_CACHE_SAFE` option.
@@ -331,12 +332,12 @@ During Flash write operations, the system temporarily disables cache to prevent
When this option is enabled, **all interrupt callback functions and their context data must reside in internal memory**, because the system cannot fetch instructions or data from Flash while the cache is disabled.
Thread Safety
^^^^^^^^^^^^^
-------------
The driver guarantees thread safety for all public TWAI APIs. You can safely call these APIs from different RTOS tasks without requiring additional synchronization or locking mechanisms.
Performance
^^^^^^^^^^^
-----------
To improve the real-time performance of interrupt handling, the driver provides the :ref:`CONFIG_TWAI_ISR_IN_IRAM` option. When enabled, the TWAI ISR (Interrupt Service Routine) and receive operations are placed in internal RAM, reducing latency caused by instruction fetching from Flash.
@@ -347,7 +348,7 @@ For applications that require high-performance transmit operations, the driver p
However, user-defined callback functions and context data invoked by the ISR may still reside in Flash. To fully eliminate Flash latency, users must place these functions and data into internal RAM using macros such as :c:macro:`IRAM_ATTR` for functions and :c:macro:`DRAM_ATTR` for data.
Resource Usage
^^^^^^^^^^^^^^
--------------
You can inspect the Flash and memory usage of the TWAI driver using the :doc:`/api-guides/tools/idf-size` tool. Below are the test conditions (based on the ESP32-C6 as an example):
@@ -385,12 +386,12 @@ Resource Usage with :ref:`CONFIG_TWAI_ISR_IN_IRAM` Enabled:
Additionally, each TWAI handle dynamically allocates approximately ``168`` + 4 * :cpp:member:`twai_onchip_node_config_t::tx_queue_depth` bytes of memory from the heap.
Other Kconfig Options
^^^^^^^^^^^^^^^^^^^^^
---------------------
- :ref:`CONFIG_TWAI_ENABLE_DEBUG_LOG`: This option forces all debug logs of the TWAI driver to be enabled regardless of the global log level settings. Enabling this can help developers obtain more detailed log information during debugging, making it easier to locate and resolve issues.
Application Examples
--------------------
====================
.. list::
@@ -398,9 +399,24 @@ Application Examples
- :example:`peripherals/twai/twai_network` using 2 nodes with different roles: transmitting and listening, demonstrates how to use the driver for single and bulk data transmission, as well as configure filters to receive these data.
API Reference
-------------
=============
On-Chip TWAI APIs
-----------------
.. include-build-file:: inc/esp_twai_onchip.inc
TWAI Driver APIs
----------------
.. include-build-file:: inc/esp_twai.inc
TWAI Driver Types
-----------------
.. include-build-file:: inc/esp_twai_types.inc
TWAI HAL Types
--------------
.. include-build-file:: inc/twai_types.inc
@@ -1,3 +1,4 @@
========================
通用硬件定时器 (GPTimer)
========================
@@ -11,7 +12,7 @@
:depth: 2
概述
----
====
通用定时器是 {IDF_TARGET_NAME} [`定时器组外设 <{IDF_TARGET_TRM_CN_URL}#timg>`__]的专用驱动程序。该定时器可以选择不同的时钟源和分频系数,能满足纳秒级的分辨率要求。此外,它还具有灵活的超时报警功能,并允许在报警时刻自动更新计数值,从而实现非常精准的定时周期。
@@ -24,7 +25,7 @@
- 其他
快速入门
--------
========
本节将带你快速了解如何使用 GPTimer 驱动。通过简单的示例,展示如何创建一个定时器并启动它,如何设置警报事件,以及如何注册事件回调函数。一般的使用流程如下:
@@ -54,7 +55,7 @@
}
创建和启动定时器
^^^^^^^^^^^^^^^^
----------------
首先,我们需要创建一个定时器实例。以下代码展示了如何创建一个分辨率为 1 MHz 的定时器:
@@ -104,7 +105,7 @@
但是请注意,当定时器处于启动的 **中间状态** 时(启动开始了,但还没有启动完毕),此时如果另外一个线程调用 :cpp:func:`gptimer_start` 或者 :cpp:func:`gptimer_stop` 函数,则会返回 :c:macro:`ESP_ERR_INVALID_STATE` 错误,避免触发不确定的行为。
设置和获取计数值
^^^^^^^^^^^^^^^^
----------------
一个刚创建的定时器,其内部计数器值默认为 0。你可以通过 :cpp:func:`gptimer_set_raw_count` 设置其他的计数值。最大计数值取决于硬件定时器的位宽(通常不少于 ``54 bit``)。
@@ -126,7 +127,7 @@
double time = (double)count / resolution_hz;
触发周期性警报事件
^^^^^^^^^^^^^^^^^^
------------------
除了时间戳功能以外,通用定时器还支持警报功能。以下代码展示了如何设置一个周期性警报,每秒触发一次:
@@ -194,7 +195,7 @@ GPTimer 支持的事件回调函数有下面这些:
请务必在调用 :cpp:func:`gptimer_enable` 之前注册回调函数,否则定时器事件将无法正确触发中断服务。
触发一次性警报事件
^^^^^^^^^^^^^^^^^^
------------------
还有一些应用场景只需要触发一次警报中断,以下代码展示了如何设置一个一次性警报,在 1 秒后触发:
@@ -242,17 +243,17 @@ GPTimer 支持的事件回调函数有下面这些:
与周期性警报不同,上述代码在配置警报行为时关闭了自动重载功能。这意味着,当警报事件发生后,定时器将不会自动重载到预设的计数值,而是继续计数直到溢出。如果希望定时器在警报后立即停止,可以在回调函数中调用 :cpp:func:`gptimer_stop`
资源回收
^^^^^^^^
--------
当不再需要使用定时器时,应该调用 :cpp:func:`gptimer_delete_timer` 函数来释放软硬件资源。删除前请确保定时器已经处于停止状态。
进阶功能
--------
========
在了解了基本用法后,我们可以进一步探索 GPTimer 驱动的更多玩法。
动态更新警报值
^^^^^^^^^^^^^^
--------------
GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_action` 函数来动态更新警报值,从而实现单调型的软件定时器链表。以下代码展示了如何在警报事件发生时,重新设置下一次警报的触发时间:
@@ -300,7 +301,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
.. _gptimer-etm-event-and-task:
GPTimer 的 ETM 事件与任务
^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------
GPTimer 可以生成多种事件,这些事件可以连接到 :doc:`ETM </api-reference/peripherals/etm>` 模块。事件类型列在 :cpp:type:`gptimer_etm_event_type_t` 中。用户可以通过调用 :cpp:func:`gptimer_new_etm_event` 来创建 ``ETM event`` 句柄。
GPTimer 还支持一些可由其他事件触发并自动执行的任务。任务类型列在 :cpp:type:`gptimer_etm_task_type_t` 中。用户可以通过调用 :cpp:func:`gptimer_new_etm_task` 来创建 ``ETM task`` 句柄。
@@ -308,7 +309,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
有关如何将定时器事件和任务连接到 ETM 通道,请参阅 :doc:`ETM </api-reference/peripherals/etm>` 文档。
关于低功耗
^^^^^^^^^^
----------
当启用电源管理 :ref:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或禁用时钟源,从而导致 GPTimer 的计时出错。
@@ -319,7 +320,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
除了关闭时钟源外,系统在进入睡眠模式时还可以关闭 GPTimer 的电源以进一步降低功耗。要实现这一点,需要将 :cpp:member:`gptimer_config_t::allow_pd` 设置为 ``true``。在系统进入睡眠模式之前, GPTimer 的寄存器上下文会被备份到内存中,并在系统唤醒后恢复。请注意,启用此选项虽然可以降低功耗,但会增加内存的使用量。因此,在使用该功能时需要在功耗和内存消耗之间进行权衡。
关于线程安全
^^^^^^^^^^^^
------------
驱动使用了临界区保证了对寄存器的原子操作。句柄内部的关键成员也受临界区保护。驱动内部的状态机使用了原子指令保证了线程安全,通过状态检查还能进一步防止一些不合法的并发操作(例如 `start``stop` 冲突)。因此, GPTimer 驱动的 API 可以在多线程环境下使用,无需自行加锁。
@@ -335,7 +336,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
- :cpp:func:`gptimer_set_alarm_action`
关于 Cache 安全
^^^^^^^^^^^^^^^
---------------
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 GPTimer 的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :ref:`CONFIG_GPTIMER_ISR_CACHE_SAFE` 选项。
@@ -344,7 +345,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
请注意,在启用该选项后,所有的中断回调函数及其上下文数据 **必须存放在内部存储空间** 中。因为在 Cache 被禁用时,系统无法从 Flash 中加载数据和指令。
关于性能
^^^^^^^^
--------
为了提升中断处理的实时响应能力, GPTimer 驱动提供了 :ref:`CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
@@ -355,12 +356,12 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
前文还提到, GPTimer 驱动允许部分函数在中断上下文中使用。:ref:`CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` 选项可以将这些函数放入 IRAM 中,一来,可以避免缓存缺失带来的性能损失,二来,这些函数在 Cache 关闭期间也能使用。
其他 Kconfig 选项
^^^^^^^^^^^^^^^^^
-----------------
- :ref:`CONFIG_GPTIMER_ENABLE_DEBUG_LOG` 选项允许强制启用 GPTimer 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。
关于资源消耗
^^^^^^^^^^^^
------------
使用 :doc:`/api-guides/tools/idf-size` 工具可以查看 GPTimer 驱动的代码和数据消耗。以下是测试前提条件(以 ESP32-C2 为例):
@@ -386,7 +387,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
此外,每一个 GPTimer 句柄会从 heap 中动态申请约 ``100`` 字节的内存。如果还使能了 :cpp:member:`gptimer_config_t::flags::allow_pd` 选项,那么每个定时器还会在睡眠期间额外消耗约 ``30`` 字节的内存用于保存寄存器上下文。
应用示例
--------
========
.. list::
@@ -395,12 +396,26 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
:SOC_TIMER_SUPPORT_ETM: - :example:`peripherals/timer_group/gptimer_capture_hc_sr04` 展示了如何使用通用定时器和事件任务矩阵(ETM)来精确捕获超声波传感器事件的时间戳,并据此换算成距离信息。
API 参考
--------
========
GPTimer 驱动 API
-----------------
.. include-build-file:: inc/gptimer.inc
GPTimer 驱动类型
----------------
.. include-build-file:: inc/gptimer_types.inc
GPTimer HAL 类型
----------------
.. include-build-file:: inc/timer_types.inc
.. only:: SOC_TIMER_SUPPORT_ETM
GPTimer ETM API
---------------
.. include-build-file:: inc/gptimer_etm.inc
+39 -23
View File
@@ -1,3 +1,4 @@
===================
双线汽车接口 (TWAI)
===================
@@ -10,7 +11,7 @@
:depth: 2
概述
----
====
TWAI 是一种适用于汽车和工业应用的高可靠性的多主机实时串行异步通信协议。它兼容 ISO11898-1 标准定义的帧结构,可以支持 11 位 ID 的标准帧和 29 位 ID 的扩展帧。支持报文优先级和无损仲裁,支持自动重传和故障自动隔离机制。{IDF_TARGET_NAME} 包含 {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} 个 TWAI 控制器,可以创建 {IDF_TARGET_CONFIG_SOC_TWAI_CONTROLLER_NUM} 个驱动实例。
@@ -30,7 +31,7 @@ TWAI 是一种适用于汽车和工业应用的高可靠性的多主机实时串
- 配合其他通信协议作为桥接设备
快速入门
--------
========
本节将带你快速了解如何使用 TWAI 驱动。通过简单的示例,展示如何创建一个 TWAI 节点实例,如何发送和接收总线上的报文,以及如何安全停止和删除驱动。一般的使用流程如下:
@@ -38,7 +39,7 @@ TWAI 是一种适用于汽车和工业应用的高可靠性的多主机实时串
:align: center
硬件连接
^^^^^^^^
--------
{IDF_TARGET_NAME} 内部没有集成 TWAI 收发器。因此你需要外接一个收发器才能加入 TWAI 总线。外部收发器的型号取决于具体应用遵循的物理层规范。例如,使用 TJA105x 收发器以兼容 ISO 11898-2 标准。
@@ -53,7 +54,7 @@ TWAI 是一种适用于汽车和工业应用的高可靠性的多主机实时串
- CLK_OUT (可选),输出控制器时间量子时钟,即源时钟的分频时钟。
创建和启动 TWAI 节点
^^^^^^^^^^^^^^^^^^^^^
---------------------
首先,我们需要创建一个 TWAI 实例。以下代码展示了如何创建一个波特率为 200kHz 的 TWAI 节点:
@@ -95,7 +96,7 @@ TWAI 是一种适用于汽车和工业应用的高可靠性的多主机实时串
与之对应的函数是 :cpp:func:`twai_node_disable`,该函数将立即停止节点工作并与总线断开,正在进行的传输将被中止。当下次重新启动时,如果发送队列中有未完成的任务,驱动将立即发起新的传输。
发送报文
^^^^^^^^
--------
TWAI 报文有多种类型,由报头指定。一个典型的数据帧报文主要包括报头和数据,大概结构如下:
@@ -130,7 +131,7 @@ TWAI 报文有多种类型,由报头指定。一个典型的数据帧报文主
- :cpp:member:`twai_frame_t::header::esi` 对于收到的报文,指示发送节点的错误状态。
接收报文
^^^^^^^^
--------
接收报文必须在接收事件回调中进行,因此,要接收报文需要在控制器启动前注册接收事件回调 :cpp:member:`twai_event_callbacks_t::on_rx_done` ,从而在事件发生时接收报文。以下代码分别展示了如何注册接收事件回调,以及如何在回调中接收报文:
@@ -163,12 +164,12 @@ TWAI 报文有多种类型,由报头指定。一个典型的数据帧报文主
同样,驱动使用指针进行传递,因此需要在接收前配置 :cpp:member:`twai_frame_t::buffer` 的指针及其内存长度 :cpp:member:`twai_frame_t::buffer_len`
停止和删除节点
^^^^^^^^^^^^^^
--------------
当不再需要使用 TWAI 时,应该调用 :cpp:func:`twai_node_delete` 函数来释放软硬件资源。删除前请确保 TWAI 已经处于停止状态。
进阶功能
--------
========
在了解了基本用法后,我们可以进一步探索 TWAI 驱动的更多玩法。驱动支持更详细的控制器配置和错误反馈功能,完整的驱动功能图如下:
@@ -176,7 +177,7 @@ TWAI 报文有多种类型,由报头指定。一个典型的数据帧报文主
:align: center
在 ISR 中发送
^^^^^^^^^^^^^
-------------
TWAI 驱动支持在中断服务程序 (ISR) 中发送报文。这对于需要低延迟响应或由硬件定时器触发的周期性传输的应用特别有用。例如,你可以在 ``on_tx_done`` 回调中触发一次新的传输,该回调在 ISR 上下文中执行。
@@ -202,7 +203,7 @@ TWAI 驱动支持在中断服务程序 (ISR) 中发送报文。这对于需要
在 ISR 中调用 :cpp:func:`twai_node_transmit` 时,``timeout`` 参数将被忽略,函数不会阻塞。如果发送队列已满,函数将立即返回错误。应用程序需要自行处理队列已满的情况。
位时序自定义
^^^^^^^^^^^^^
-------------
和其他异步通信不同的是,TWAI 控制器在一个位时间里实际上在进行以 **时间量子(Tq** 为单位的计数 / 采样,一个位里的时间量子的数量决定了最终的波特率以及采样点位置。在信号质量较低时时,可以手动更加精准的配置这些时序段以满足要求。位时间里的时间量子分为不同的段,如图所示:
@@ -247,10 +248,10 @@ TWAI 驱动支持在中断服务程序 (ISR) 中发送报文。这对于需要
``brp````prop_seg````tseg_1````tseg_2````sjw`` 的不同组合可以实现相同波特率。用户应考虑 **传播延迟、节点信息处理时间和相位误差** 等因素,根据总线的物理特性进行调整。
过滤器配置
^^^^^^^^^^
----------
掩码过滤器
""""""""""
^^^^^^^^^^
TWAI 控制器硬件可以根据 ID 对报文进行过滤,从而减少软硬件开销使节点更加高效。过滤掉报文的节点 **不会接收到该报文,但仍会应答**
@@ -279,7 +280,7 @@ TWAI 控制器硬件可以根据 ID 对报文进行过滤,从而减少软硬
.. only:: not SOC_TWAI_SUPPORT_FD
双过滤器模式
""""""""""""
^^^^^^^^^^^^
{IDF_TARGET_NAME} 支持双过滤器模式,可将硬件配置为并列的两个独立的 16 位掩码过滤器,支持接收更多 ID。但注意,使用双过滤器模式过滤 29 位扩展ID时,每个过滤器只能过滤其ID的高 16 位,剩余13位不做过滤。以下代码展示了如何借助 :cpp:func:`twai_make_dual_filter` 配置双过滤器模式。
@@ -293,7 +294,7 @@ TWAI 控制器硬件可以根据 ID 对报文进行过滤,从而减少软硬
.. only:: SOC_TWAI_SUPPORT_FD
范围过滤器
""""""""""
^^^^^^^^^^
{IDF_TARGET_NAME} 还包含 1 个范围过滤器,与掩码过滤器属并列关系。可以通过 :cpp:func:`twai_node_config_range_filter` 函数直接配置希望接收的 ID 范围。其中:
@@ -301,7 +302,7 @@ TWAI 控制器硬件可以根据 ID 对报文进行过滤,从而减少软硬
- 配置为无效区间则表示不接收任何报文。
总线错误和恢复
^^^^^^^^^^^^^^
--------------
TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式的错误,并规定了一套由发送/接收错误计数器(TEC/REC)实现的故障隔离机制。计数器值决定节点的错误状态,即主动错误、错误警告、被动错误和离线,它可以使持续存在错误的节点最终自行断开与总线的连接。
@@ -317,12 +318,12 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
节点恢复完成时同样进入 :cpp:member:`twai_event_callbacks_t::on_state_change` 回调,状态由 :cpp:enumerator:`TWAI_ERROR_BUS_OFF` 变为 :cpp:enumerator:`TWAI_ERROR_ACTIVE`。恢复完成的节点可以立即进行传输,如果发送队列中有未完成的任务,驱动将立即发起新的传输。
关于低功耗
^^^^^^^^^^
----------
当启用电源管理 :ref:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或关闭时钟源,从而导致 TWAI 出错。为了防止这种情况发生,驱动内部使用电源锁管理。当调用 :cpp:func:`twai_node_enable` 函数后,该锁将被激活,确保系统不会进入睡眠模式,从而保持 TWAI 功能正常。如果需要降低功耗,可以调用 :cpp:func:`twai_node_disable` 函数来释放电源管理锁,使系统能够进入睡眠模式,睡眠期间 TWAI 控制器也将停止工作。
关于 Cache 安全
^^^^^^^^^^^^^^^
---------------
在进行 Flash 写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致存放在 Flash 上的中断处理程序在此期间无法响应。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :ref:`CONFIG_TWAI_ISR_CACHE_SAFE` 选项。
@@ -331,12 +332,12 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
请注意,在启用该选项后,所有的中断回调函数及其上下文数据 **必须存放在内部存储空间** 中。因为在 Cache 被禁用时,系统无法从 Flash 中加载数据和指令。
关于线程安全
^^^^^^^^^^^^^
-------------
驱动程序可保证所有公开的 TWAI API 的线程安全,使用时,可以直接从不同的 RTOS 任务中调用此类 API,无需额外锁保护。
关于性能
^^^^^^^^
--------
为了提升中断处理的实时响应能力, 驱动提供了 :ref:`CONFIG_TWAI_ISR_IN_IRAM` 选项。启用该选项后,中断处理程序和接收操作将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令带来的延迟。
@@ -347,7 +348,7 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
但是,中断处理程序调用的用户回调函数和用户上下文数据仍然可能位于 Flash 中,延迟问题还是会存在,这需要用户自己将回调函数和数据放入内部 RAM 中,比如使用 :c:macro:`IRAM_ATTR`:c:macro:`DRAM_ATTR`
关于资源消耗
^^^^^^^^^^^^
------------
使用 :doc:`/api-guides/tools/idf-size` 工具可以查看 TWAI 驱动的 Flash 和内存空间消耗。以下是测试条件(以 ESP32-C6 为例):
@@ -385,12 +386,12 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
此外,每一个 TWAI 句柄会从 heap 中动态申请约 ``168`` + 4 * :cpp:member:`twai_onchip_node_config_t::tx_queue_depth` 字节的内存。
其他 Kconfig 选项
^^^^^^^^^^^^^^^^^
-----------------
- :ref:`CONFIG_TWAI_ENABLE_DEBUG_LOG` 选项允许强制启用 TWAI 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。
应用示例
--------
========
.. list::
@@ -398,9 +399,24 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
- :example:`peripherals/twai/twai_network` 通过发送、监听, 2 个不同角色的节点,演示了如何使用驱动程序进行单次的和大量的数据发送,以及配置过滤器以接收这些数据。
API 参考
--------
========
片上 TWAI API
-------------
.. include-build-file:: inc/esp_twai_onchip.inc
TWAI 驱动 API
-------------
.. include-build-file:: inc/esp_twai.inc
TWAI 驱动类型
-------------
.. include-build-file:: inc/esp_twai_types.inc
TWAI HAL 类型
--------------
.. include-build-file:: inc/twai_types.inc