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
@@ -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