docs: provide CN translation for three short docs of api-guides (backport v5.1)

This commit is contained in:
Cai Xin Ying 2023-09-05 11:11:27 +08:00 committed by morris
parent 1b87f35f0f
commit ef5c85158d
6 changed files with 362 additions and 121 deletions

View File

@ -1,6 +1,8 @@
RF calibration
RF Calibration
==============
:link_to_translation:`zh_CN:[中文]`
{IDF_TARGET_NAME} supports three RF calibration methods during RF initialization:
1. Partial calibration
@ -9,55 +11,45 @@ RF calibration
3. No calibration
Partial calibration
Partial Calibration
-------------------
During RF initialization, the partial calibration method is used by default for RF calibration.
It is done based on the full calibration data which is stored in the NVS.
To use this method, please go to ``menuconfig`` and enable :ref:`CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE`.
Full calibration
During RF initialization, the partial calibration method is used by default for RF calibration. It is done based on the full calibration data which is stored in the NVS. To use this method, please go to ``menuconfig`` and enable :ref:`CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE`.
Full Calibration
----------------
Full calibration is triggered in the follwing conditions:
Full calibration is triggered in the following conditions:
1. NVS does not exist.
2. The NVS partition to store calibration data is erased.
2. The NVS partition to store calibration data has been erased.
3. Hardware MAC address is changed.
3. Hardware MAC address has changed.
4. PHY library version is changed.
4. PHY library version has changed.
5. The RF calibration data loaded from the NVS partition is broken.
It takes about 100ms more than partial calibration.
If boot duration is not critical, it is suggested to use the full calibration method.
To switch to the full calibration method, go to ``menuconfig`` and disable :ref:`CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE`.
If you use the default method of RF calibration, there are two ways to add the function of triggering full calibration as a last-resort remedy.
Full calibration takes 100 ms longer than the partial calibration method. If boot duration is not of critical importance to the application, the full calibration method is recommended. To switch to the full calibration method, go to ``menuconfig`` and disable :ref:`CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE`. If you use the default method of RF calibration, there are two ways to add the function of triggering full calibration as a last-resort remedy.
1. Erase the NVS partition if you don't mind all of the data stored in the NVS partition is erased. That is indeed the easiest way.
1. Erase the NVS partition if you do not mind all of the data stored in the NVS partition is erased. That is indeed the easiest way.
2. Call API :cpp:func:`esp_phy_erase_cal_data_in_nvs` before initializing WiFi and BT/BLE based on some conditions (e.g. an option provided in some diagnostic mode).
In this case, only phy namespace of the NVS partition is erased.
2. Call API :cpp:func:`esp_phy_erase_cal_data_in_nvs` before initializing Wi-Fi and Bluetooth®/Bluetooth Low Energy based on some conditions (e.g., an option provided in some diagnostic mode). In this case, only the PHY namespace of the NVS partition is erased.
No calibration
No Calibration
---------------
No calibration method is only used when the device wakes up from deep sleep.
PHY initialization data
The no calibration method is only used when the device wakes up from Deep-sleep mode.
PHY Initialization Data
-----------------------
The PHY initialization data is used for RF calibration.
There are two ways to get the PHY initialization data.
One is the default initialization data which is located in the header file :idf_file:`components/esp_phy/{IDF_TARGET_PATH_NAME}/include/phy_init_data.h`.
The PHY initialization data is used for RF calibration. There are two ways to get the PHY initialization data.
It is embedded into the application binary after compiling and then stored into read-only memory (DROM).
To use the default initialization data, please go to ``menuconfig`` and disable :ref:`CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION`.
One is to use the default initialization data which is located in the header file :idf_file:`components/esp_phy/{IDF_TARGET_PATH_NAME}/include/phy_init_data.h`. It is embedded into the application binary after compiling and then stored into read-only memory (DROM). To use the default initialization data, please go to ``menuconfig`` and disable :ref:`CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION`.
Another is the initialization data which is stored in a partition.
When using a custom partition table, make sure that PHY data partition is included (type: `data`, subtype: `phy`).
With default partition table, this is done automatically.
If initialization data is stored in a partition, it has to be flashed there, otherwise runtime error will occur.
To switch to the initialization data stored in a partition, go to ``menuconfig`` and enable :ref:`CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION`.
An alternative is to store the initialization data in a PHY data partition. A PHY data partition is included in the default partition table. However, when using a custom partition table, please ensure that a PHY data partition (type: ``data``, subtype: ``phy``) is included in the custom partition table. Whether you are using a custom partition table or the default partition table, if initialization data is stored in a partition, it has to be flashed there, otherwise a runtime error occurs. If you want to use initialization data stored in a partition, go to ``menuconfig`` and enable the option :ref:`CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION`.
API Reference
-------------

View File

@ -1,49 +1,80 @@
High-Level Interrupts
=====================
High Priority Interrupts
========================
:link_to_translation:`zh_CN:[中文]`
.. toctree::
:maxdepth: 1
The Xtensa architecture has support for 32 interrupts, divided over 7 levels (levels 1 to 7, with 7 being an NMI), plus an assortment of exceptions. On the {IDF_TARGET_NAME}, the interrupt mux allows most interrupt sources to be routed to these interrupts using the :doc:`interrupt allocator <../api-reference/system/intr_alloc>`. Normally, interrupts will be written in C, but ESP-IDF allows high-level interrupts to be written in assembly as well, resulting in very low interrupt latencies.
The Xtensa architecture supports 32 interrupts, divided over 7 priority levels from level 1 to 7, with level 7 being an non-maskable interrupt (NMI), plus an assortment of exceptions. On the {IDF_TARGET_NAME}, the :doc:`../api-reference/system/intr_alloc` can route most interrupt sources to these interrupts via the interrupt mux. Normally, interrupts are written in C, but ESP-IDF allows high-priority interrupts to be written in assembly as well, resulting in very low interrupt latencies.
Interrupt Levels
----------------
Interrupt Priorities
--------------------
.. only:: esp32
===== ================= ====================================================
Level Symbol Remark
===== ================= ====================================================
1 N/A Exception and level 0 interrupts. Handled by ESP-IDF
2-3 N/A Medium level interrupts. Handled by ESP-IDF
4 xt_highint4 Free to use :ref:`(See 1) <hlinterrupts-pin-notes>`
5 xt_highint5 Normally used by ESP-IDF debug logic :ref:`(See 1) <hlinterrupts-pin-notes>`
NMI xt_nmi Free to use
dbg xt_debugexception Debug exception. Called on e.g. a BREAK instruction. :ref:`(See 2) <hlinterrupts-pin-notes>`
===== ================= ====================================================
.. list-table::
:header-rows: 1
:widths: 20 30 50
:align: center
* - Priority Level
- Symbol
- Remark
* - 1
- N/A
- Exception and low priority interrupts, handled by ESP-IDF.
* - 2-3
- N/A
- Medium priority interrupts, handled by ESP-IDF.
* - 4
- xt_highint4
- High priority interrupt, free to use. [1]_
* - 5
- xt_highint5
- Normally used by ESP-IDF debug logic. [1]_
* - NMI
- xt_nmi
- Non-maskable interrupt, free to use.
* - dbg
- xt_debugexception
- Debug exception. Called on e.g., a BREAK instruction. [2]_
.. _hlinterrupts-pin-notes:
The following notes give more information about the items in the tables above.
1. ESP-IDF debug logic can be configured to run on `xt_highint4` or `xt_highint5` in :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`. Bluetooth's interrupt can be configured to run on level 4 by enabling :ref:`CONFIG_BTDM_CTRL_HLI`. If :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, ESP-IDF debug logic must be running on level 5 interrupt.
2. If :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, `xt_debugexception` is used to fix `live lock issue <https://www.espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf>`_ in ESP32 ECO3.
.. [1] ESP-IDF debug logic can be configured to run on ``xt_highint4`` or ``xt_highint5`` in :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`. Bluetooth's interrupt can be configured to run on priority level 4 by enabling :ref:`CONFIG_BTDM_CTRL_HLI`. If :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, ESP-IDF debug logic must be running on priority level 5 interrupt.
.. [2] If :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, ``xt_debugexception`` is used to fix the `live lock issue <https://www.espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf>`_ in ESP32 ECO3.
.. only:: not esp32
===== ================= ====================================================
Level Symbol Remark
===== ================= ====================================================
1 N/A Exception and level 0 interrupts. Handled by ESP-IDF
2-3 N/A Medium level interrupts. Handled by ESP-IDF
4 xt_highint4 Normally used by ESP-IDF debug logic
5 xt_highint5 Free to use
NMI xt_nmi Free to use
dbg xt_debugexception Debug exception. Called on e.g. a BREAK instruction.
===== ================= ====================================================
.. list-table::
:header-rows: 1
:widths: 20 30 50
:align: center
Using these symbols is done by creating an assembly file (suffix .S) and defining the named symbols, like this::
* - Priority Level
- Symbol
- Remark
* - 1
- N/A
- Exception and low priority interrupts, handled by ESP-IDF.
* - 2-3
- N/A
- Medium priority interrupts, handled by ESP-IDF.
* - 4
- xt_highint4
- Normally used by ESP-IDF debug logic.
* - 5
- xt_highint5
- High priority interrupts, free to use.
* - NMI
- xt_nmi
- Non-maskable interrupt, free to use.
* - dbg
- xt_debugexception
- Debug exception. Called on e.g., a BREAK instruction.
Using these symbols is done by creating an assembly file with suffix ``.S`` and defining the named symbols, like this:
.. code-block:: none
.section .iram1,"ax"
.global xt_highint5
@ -60,32 +91,31 @@ For a real-life example, see the :component_file:`esp_system/port/soc/{IDF_TARGE
Notes
-----
- Do not call C code from a high-level interrupt; as these interrupts are run from a critical section, this can cause the target to crash.
Note that although the panic handler interrupt does call normal C code, this exception is allowed due to the fact that this handler never returns (i.e., the application will not continue to run after the panic handler).
so breaking C code execution flow is not a problem.
- Do not call C code from a high-priority interrupt; as these interrupts are run from a critical section, this can cause the target to crash. Note that although the panic handler interrupt does call normal C code, this exception is allowed due to the fact that this handler never returns (i.e., the application does not continue to run after the panic handler), so breaking C code execution flow is not a problem.
.. only:: esp32
.. only:: esp32
When :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, C code is also called from a high-level interrupt, this is possible thanks to some additional protection added to it.
When :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, C code is also called from a high-priority interrupt, this is possible thanks to some additional protection added to it.
- Make sure your assembly code gets linked in. Indeed, as the free-to-use symbols are declared as weak, the linker may discard the file containing the symbol. This will
happen if the only symbol defined, or used, from the user file is the ``xt_*`` free-to-use symbol. To avoid this, in the assembly file containing the ``xt_*`` symbol,
define another symbol, like::
- Make sure your assembly code gets linked in. Indeed, as the free-to-use symbols are declared as weak, the linker may discard the file containing the symbol. This happens if the only symbol defined, or used from the user file is the ``xt_*`` free-to-use symbol. To avoid this, in the assembly file containing the ``xt_*`` symbol, define another symbol, like:
.global ld_include_my_isr_file
ld_include_my_isr_file:
.. code-block:: none
Here it is called ``ld_include_my_isr_file`` but can have any name, as long as it is not defined anywhere else in the project.
.global ld_include_my_isr_file
ld_include_my_isr_file:
Then, in the component ``CMakeLists.txt``, add this name as an unresolved symbol to the ld command line arguments::
Here it is called ``ld_include_my_isr_file`` but can have any name, as long as it is not defined anywhere else in the project.
target_link_libraries(${COMPONENT_TARGET} "-u ld_include_my_isr_file")
Then, in the component ``CMakeLists.txt``, add this name as an unresolved symbol to the ld command line arguments:
This should cause the linker to always include the file defining ``ld_include_my_isr_file``, causing the ISR to always be linked in.
.. code-block:: none
- High-level interrupts can be routed and handled using :cpp:func:`esp_intr_alloc` and associated functions. The handler and handler arguments
to :cpp:func:`esp_intr_alloc` must be NULL, however.
target_link_libraries(${COMPONENT_TARGET} "-u ld_include_my_isr_file")
- In theory, medium priority interrupts could also be handled in this way. ESP-IDF does not support this yet.
This will ensure the linker to always includes the file defining ``ld_include_my_isr_file``, so that the ISR is always linked.
- To check Xtensa instruction set architecture (ISA), please refer to `Xtensa ISA Summary <https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/ip/tensilica-ip/isa-summary.pdf>`_.
- High-priority interrupts can be routed and handled using :cpp:func:`esp_intr_alloc` and associated functions. The handler and handler arguments to :cpp:func:`esp_intr_alloc` must be NULL, however.
- In theory, medium priority interrupts could also be handled in this way. ESP-IDF does not support this yet.
- To check Xtensa instruction set architecture (ISA), please refer to `Xtensa ISA Summary <https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/ip/tensilica-ip/isa-summary.pdf>`_.

View File

@ -1,67 +1,55 @@
Thread Local Storage
====================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
Thread-local storage (TLS) is a mechanism by which variables are allocated such that there
is one instance of the variable per extant thread. ESP-IDF provides three ways to make use
of such variables:
Thread-local storage (TLS) is a mechanism by which variables are allocated such that there is one instance of the variable per extant thread. ESP-IDF provides three ways to make use of such variables:
- :ref:`freertos-native`: ESP-IDF FreeRTOS native API.
- :ref:`pthread-api`: ESP-IDF's pthread API.
- :ref:`c11-std`: C11 standard introduces special keyword to declare variables as thread local.
- :ref:`freertos-native`: ESP-IDF FreeRTOS native APIs.
- :ref:`pthread-api`: ESP-IDF pthread APIs.
- :ref:`c11-std`: C11 standard introduces special keywords to declare variables as thread local.
.. _freertos-native:
FreeRTOS Native API
FreeRTOS Native APIs
--------------------
The ESP-IDF FreeRTOS provides the following API to manage thread local variables:
The ESP-IDF FreeRTOS provides the following APIs to manage thread local variables:
- :cpp:func:`vTaskSetThreadLocalStoragePointer`
- :cpp:func:`pvTaskGetThreadLocalStoragePointer`
- :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback`
- :cpp:func:`vTaskSetThreadLocalStoragePointer`
- :cpp:func:`pvTaskGetThreadLocalStoragePointer`
- :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback`
In this case maximum number of variables that can be allocated is limited by
:ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` configuration value. Variables are kept in the task control block (TCB)
and accessed by their index. Note that index 0 is reserved for ESP-IDF internal uses.
In this case, the maximum number of variables that can be allocated is limited by :ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS`. Variables are kept in the task control block (TCB) and accessed by their index. Note that index 0 is reserved for ESP-IDF internal uses.
Using that API user can allocate thread local variables of an arbitrary size and assign them to any number of tasks.
Different tasks can have different sets of TLS variables.
Using the APIs above, you can allocate thread local variables of an arbitrary size, and assign them to any number of tasks. Different tasks can have different sets of TLS variables.
If size of the variable is more then 4 bytes then user is responsible for allocating/deallocating memory for it.
Variable's deallocation is initiated by FreeRTOS when task is deleted, but user must provide function (callback)
to do proper cleanup.
If size of the variable is more then 4 bytes, then you need to allocate/deallocate memory for it. Variable's deallocation is initiated by FreeRTOS when task is deleted, but user must provide callback function to do proper cleanup.
.. _pthread-api:
Pthread API
Pthread APIs
----------------
The ESP-IDF provides the following :doc:`pthread API </api-reference/system/pthread>` to manage thread local variables:
The ESP-IDF provides the following :doc:`/api-reference/system/pthread` to manage thread local variables:
- :cpp:func:`pthread_key_create`
- :cpp:func:`pthread_key_delete`
- :cpp:func:`pthread_getspecific`
- :cpp:func:`pthread_setspecific`
- :cpp:func:`pthread_key_create`
- :cpp:func:`pthread_key_delete`
- :cpp:func:`pthread_getspecific`
- :cpp:func:`pthread_setspecific`
This API has all benefits of the one above, but eliminates some its limits. The number of variables is
limited only by size of available memory on the heap.
Due to the dynamic nature this API introduces additional performance overhead compared to the native one.
These APIs have all benefits of the ones above, but eliminates some their limits. The number of variables is limited only by size of available memory on the heap. Due to the dynamic nature, this APIs introduce additional performance overhead compared to the native one.
.. _c11-std:
C11 Standard
------------
The ESP-IDF FreeRTOS supports thread local variables according to C11 standard (ones specified with ``__thread`` keyword).
For details on this GCC feature please see https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/Thread-Local.html#Thread-Local.
Storage for that kind of variables is allocated on the task's stack.
Note that area for all such variables in the program will be allocated on the stack of
every task in the system even if that task does not use such variables at all. For example
ESP-IDF system tasks (like ``ipc``, ``timer`` tasks etc.) will also have that extra stack space allocated.
So this feature should be used with care. There is a tradeoff: C11 thread local variables are quite handy
to use in programming and can be accessed using minimal CPU instructions, but this benefit goes
with the cost of additional stack usage for all tasks in the system.
Due to static nature of variables allocation all tasks in the system have the same sets of C11 thread local variables.
The ESP-IDF FreeRTOS supports thread local variables according to C11 standard, ones specified with ``__thread`` keyword. For details on this feature, please refer to the `GCC documentation <https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/Thread-Local.html#Thread-Local>`_.
Storage for that kind of variables is allocated on the task stack. Note that area for all such variables in the program is allocated on the stack of every task in the system even if that task does not use such variables at all. For example, ESP-IDF system tasks (e.g., ``ipc``, ``timer`` tasks etc.) will also have that extra stack space allocated. Thus feature should be used with care.
Using C11 thread local variables comes at a trade-off. One one hand, they are quite handy to use in programming and can be accessed using minimal CPU instructions. However, this benefit comes at the cost of additional stack usage for all tasks in the system. Due to static nature of variables allocation, all tasks in the system have the same sets of C11 thread local variables.

View File

@ -1 +1,58 @@
.. include:: ../../en/api-guides/RF_calibration.rst
RF 校准
==============
:link_to_translation:`en:[English]`
{IDF_TARGET_NAME} 在 RF 初始化过程中支持以下三种 RF 校准:
1. 部分校准
2. 全面校准
3. 不校准
部分校准
-------------------
在 RF 初始化期间,默认使用部分校准,该方法基于存储在 NVS 中的完全校准数据实现。要使用此校准方法,请前往 ``menuconfig`` 并启用 :ref:`CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE`
全面校准
----------------
在以下几种情况下,使用全面校准:
1. NVS 不存在。
2. 存储校准数据的 NVS 分区已擦除。
3. 硬件 MAC 地址变更。
4. PHY 库版本变更。
5. 从 NVS 分区加载的 RF 校准数据损坏。
全面校准耗时比部分校准长约 100 ms。当启动时长的重要性不高时建议使用全面校准。要切换到全面校准请前往 ``menuconfig`` 并禁用 :ref:`CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE`。如果使用了默认的部分校准,作为最后补救措施,可以使用以下两种方法添加函数,触发全面校准:
1. 如果不介意擦除 NVS 分区中的所有数据,那么擦除 NVS 分区是最简单的方法。
2. 在初始化 Wi-Fi 和 Bluetooth®/Bluetooth Low Energy 前,根据某些条件(例如,在某些诊断模式下提供的选项)调用 API :cpp:func:`esp_phy_erase_cal_data_in_nvs`,此时仅会擦除 NVS 分区的 PHY 命名空间。
不校准
---------------
设备从 Deep-sleep 模式中唤醒时,可以不校准。
PHY 初始化数据
-----------------------
PHY 初始化数据用于 RF 校准,通过以下两种方法,可以获取 PHY 初始化数据。
一是使用默认初始化数据,该数据位于头文件 :idf_file:`components/esp_phy/{IDF_TARGET_PATH_NAME}/include/phy_init_data.h` 中。默认初始化数据会在编译后嵌入到应用程序的二进制文件,然后存储在只读存储器 (DROM) 中。要使用默认的初始化数据,请前往 ``menuconfig`` 并禁用 :ref:`CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION`
二是将初始化数据存储在 PHY 数据分区中。默认的分区表中已经包含了 PHY 数据分区,但是使用自定义分区表时,请确保在自定义分区表中包含一个 PHY 数据分区(类型:``data``,子类型:``phy``)。无论使用自定义分区表还是默认分区表,只要初始化数据存储在分区中,就需要将其烧录到相应的分区中,否则运行时可能会出现错误。如果想要使用存储在分区中的初始化数据,请前往 ``menuconfig`` 并启用选项 :ref:`CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION`
API 参考
-------------
.. include-build-file:: inc/esp_phy_init.inc
.. include-build-file:: inc/esp_phy_cert_test.inc

View File

@ -1 +1,121 @@
.. include:: ../../en/api-guides/hlinterrupts.rst
高优先级中断处理程序
=====================
:link_to_translation:`en:[English]`
.. toctree::
:maxdepth: 1
Xtensa 架构支持 32 个中断处理程序,这些中断分为从 1 到 7 的 7 个优先级,其中优先级 7 是非可屏蔽中断 (NMI)。此外,该架构也支持处理其他异常情况。在 {IDF_TARGET_NAME} 上,:doc:`../api-reference/system/intr_alloc` 可以通过中断复用器,将大多数中断源路由到上述中断上。通常中断由 C 语言编写,但 ESP-IDF 支持使用汇编语言编写高优先级中断,从而尽可能消除中断延迟。
中断处理程序优先级
--------------------
.. only:: esp32
.. list-table::
:header-rows: 1
:widths: 20 30 50
:align: center
* - 优先级
- 符号
- 备注
* - 1
- N/A
- 异常和低优先级中断,由 ESP-IDF 处理。
* - 2-3
- N/A
- 中等优先级中断,由 ESP-IDF 处理。
* - 4
- xt_highint4
- 高优先级中断,可供自由使用。 [1]_
* - 5
- xt_highint5
- 通常由 ESP-IDF 的调试逻辑使用。 [1]_
* - NMI
- xt_nmi
- 非可屏蔽中断,可供自由使用。
* - dbg
- xt_debugexception
- 调试异常情况,例如在执行 BREAK 指令时调用。 [2]_
.. [1]:ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 中配置 ESP-IDF 的调试逻辑,可以使其在 ``xt_highint4````xt_highint5`` 上运行。启用 :ref:`CONFIG_BTDM_CTRL_HLI`,可以将蓝牙中断配置为优先级 4。如果启用了 :ref:`CONFIG_BTDM_CTRL_HLI`,则 ESP-IDF 的调试逻辑必须运行在优先级 5 的中断上。
.. [2] 如果启用了 :ref:`CONFIG_BTDM_CTRL_HLI`,则可以用 ``xt_debugexception`` 修复 ESP32 ECO3 中的 `活锁问题 <https://www.espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf>`_
.. only:: not esp32
.. list-table::
:header-rows: 1
:widths: 20 30 50
:align: center
* - 优先级
- 符号
- 备注
* - 1
- N/A
- 异常和低优先级中断,由 ESP-IDF 处理。
* - 2-3
- N/A
- 中等优先级中断,由 ESP-IDF 处理。
* - 4
- xt_highint4
- 通常由 ESP-IDF 的调试逻辑使用。
* - 5
- xt_highint5
- 高优先级中断,可供自由使用。
* - NMI
- xt_nmi
- 非可屏蔽中断,可供自由使用。
* - dbg
- xt_debugexception
- 调试异常情况,例如在执行 BREAK 指令时调用。
要使用这些符号,需要创建一个后缀为 ``.S`` 的汇编文件,并定义命名的符号,如下所示:
.. code-block:: none
.section .iram1,"ax"
.global xt_highint5
.type xt_highint5,@function
.align 4
xt_highint5:
... your code here
rsr a0, EXCSAVE_5
rfi 5
实际应用示例请参阅 :component_file:`esp_system/port/soc/{IDF_TARGET_PATH_NAME}/highint_hdl.S`,该示例使用了紧急处理程序。
注意事项
--------
- 请勿从高级中断中调用 C 代码,因为这些中断在临界区域运行,从高级中断调用 C 代码可能会导致目标系统崩溃。注意,尽管紧急处理程序会调用常见的 C 代码,但由于该处理程序不会返回,即在紧急处理程序之后,应用程序不会继续运行,因此中断 C 代码的执行流程不会造成问题。
.. only:: esp32
由于存在额外保护措施,启用 :ref:`CONFIG_BTDM_CTRL_HLI` 时,可以放心从高级中断中调用 C 代码。
- 请确保所用汇编代码成功链接。由于可自由使用的符号声明为弱符号,链接器可能会丢弃包含此类符号的文件。如果用户文件中定义或使用的唯一符号是可自由使用的符号 ``xt_*``,则会发生上述情况。为了避免这种情况,应在包含 ``xt_*`` 符号的汇编文件中定义另一个符号,例如:
.. code-block:: none
.global ld_include_my_isr_file
ld_include_my_isr_file:
此处符号名称为 ``ld_include_my_isr_file``,但只要该符号未在项目的其他位置定义,也可使用任意名称。
随后,在组件的 ``CMakeLists.txt`` 文件中,将该名称作为未解析符号,添加到 ld 命令行参数中:
.. code-block:: none
target_link_libraries(${COMPONENT_TARGET} "-u ld_include_my_isr_file")
这能够确保链接器始终包含定义 ``ld_include_my_isr_file`` 的文件,从而保持 ISR 与项目的链接。
- 使用 :cpp:func:`esp_intr_alloc` 和相关函数可以路由和处理高级中断,但传递给 :cpp:func:`esp_intr_alloc` 的处理程序和处理程序参数必须为 NULL。
- 中等优先级的中断理论上也可以通过上述方式处理,但 ESP-IDF 尚不支持此功能。
- 要检查 Xtensa 指令集架构 (ISA),请参阅 `Xtensa ISA 摘要 <https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/ip/tensilica-ip/isa-summary.pdf>`_

View File

@ -1 +1,55 @@
.. include:: ../../en/api-guides/thread-local-storage.rst
线程局部存储
====================
:link_to_translation:`en:[English]`
概述
--------
线程局部存储 (TLS) 机制可以分配变量使每个现有的线程都有相应变量实例。ESP-IDF 提供了以下三种方法,支持使用此类变量:
- :ref:`freertos-native`ESP-IDF FreeRTOS 原生 API。
- :ref:`pthread-api`ESP-IDF pthread API。
- :ref:`c11-std`C11 标准引入了特殊关键字,将变量声明为线程局部变量。
.. _freertos-native:
FreeRTOS 原生 API
--------------------
ESP-IDF FreeRTOS 提供以下 API用于管理线程局部变量
- :cpp:func:`vTaskSetThreadLocalStoragePointer`
- :cpp:func:`pvTaskGetThreadLocalStoragePointer`
- :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback`
此时,可以分配的最大变量数量受 :ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` 限制。变量保存在任务控制块 (TCB) 中,并由其索引访问。注意,索引 0 保留,供 ESP-IDF 内部使用。
通过使用上述 API你可以分配任意大小的线程局部变量并将其分配给任意数量的任务。不同任务可以拥有不同的 TLS 变量集。
如果变量大小超过 4 个字节,你需要负责为其分配/释放内存。在任务删除时FreeRTOS 会释放变量,但必须提供回调函数来适当清理。
.. _pthread-api:
Pthread API
----------------
ESP-IDF 提供以下 :doc:`/api-reference/system/pthread`,用于管理线程局部变量:
- :cpp:func:`pthread_key_create`
- :cpp:func:`pthread_key_delete`
- :cpp:func:`pthread_getspecific`
- :cpp:func:`pthread_setspecific`
Pthread API 具备 FreeRTOS 原生 API 的所有优点,并突破了 FreeRTOS 原生 API 的部分限制,如变量数量仅受堆上可用内存大小的限制。然而由于 Pthread API 具备动态性质,与原生 API 相比,这个 API 引入了额外的性能开销。
.. _c11-std:
C11 标准
------------
ESP-IDF FreeRTOS 支持基于 C11 标准的线程局部变量,使用 ``__thread`` 关键字指定。要了解 GCC 功能详情,请参阅 `GCC 文档 <https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/Thread-Local.html#Thread-Local>`_
这类变量的存储空间分配在任务栈上。请注意即使任务根本不使用这些变量程序中所有这类变量的存储区域都会在系统中每个任务的栈上分配。例如ESP-IDF 系统任务(如 ``ipc````timer`` 任务等)也有额外的栈空间分配。因此,使用这个特性时,需要谨慎考虑。
在使用 C11 线程局部变量时,可以针对以下特点进行权衡:在编程中使用 C11 线程局部变量非常方便,使用最少的 CPU 指令即可访问,但这一优势的代价是系统中所有任务都会额外使用栈。由于变量分配的静态性质,系统中的所有任务具有一组相同的 C11 线程局部变量。