mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
docs: Provide Chinese translation for api-reference/system/ipc.rst
This commit is contained in:
parent
ca1cd88e25
commit
3a16224d1d
@ -1,51 +1,57 @@
|
|||||||
Inter-Processor Call
|
Inter-Processor Call (IPC)
|
||||||
====================
|
==========================
|
||||||
|
|
||||||
|
:link_to_translation:`zh_CN:[中文]`
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The IPC is an **Inter-Processor Call** and **NOT Inter-Process Communication** as found on other operating systems.
|
IPC stands for an **"Inter-Processor Call"** and **NOT** "Inter-Process Communication" as found on other operating systems.
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Due to the dual core nature of the {IDF_TARGET_NAME}, there are instances where a certain callback must be run in the context of a particular CPU such as:
|
Due to the dual core nature of the {IDF_TARGET_NAME}, there are some scenarios where a certain callback must be executed from a particular core such as:
|
||||||
|
|
||||||
- When allocating an ISR to an interrupt source of a particular CPU (applies to freeing a particular CPU's interrupt source as well).
|
- When allocating an ISR to an interrupt source of a particular core (applies to freeing a particular core's interrupt source as well)
|
||||||
- On particular chips (such as the ESP32), accessing memory that is exclusive to a particular CPU (such as RTC Fast Memory).
|
- On particular chips (such as the ESP32), accessing memory that is exclusive to a particular core (such as RTC Fast Memory)
|
||||||
- Reading the registers/state of another CPU.
|
- Reading the registers/state of another core
|
||||||
|
|
||||||
The IPC (Inter-Processor Call) feature allows a particular CPU (the calling CPU) to trigger the execution of a callback function on another CPU (the target CPU). The IPC feature allows execution of a callback function on the target CPU in either ``a task context``, or ``an interrupt context``. Depending on the context that the callback function is executed in, different restrictions apply to the implementation of the callback function.
|
The IPC (Inter-Processor Call) feature allows a particular core (the calling core) to trigger the execution of a callback function on another core (the target core). The IPC feature allows execution of a callback function on the target core in either a task context, or an interrupt context. Depending on the context that the callback function is executed in, different restrictions apply to the implementation of the callback function.
|
||||||
|
|
||||||
IPC in Task Context
|
IPC in Task Context
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
The IPC feature implements callback execution in a task context by creating an IPC task for each CPU during application startup. When the calling CPU needs to execute a callback on the target CPU, the callback will execute in the context of the target CPU's IPC task.
|
The IPC feature implements callback execution in a task context by creating an IPC task for each core during application startup. When the calling core needs to execute a callback on the target core, the callback will execute in the context of the target core's IPC task.
|
||||||
|
|
||||||
When using IPCs in a task context, users need to consider the following:
|
When using IPCs in a task context, users need to consider the following:
|
||||||
|
|
||||||
- IPC callbacks should ideally be simple and short. **An IPC callback should avoid attempting to block or yield**.
|
- IPC callbacks should ideally be simple and short. An IPC callback **must never block or yield**.
|
||||||
- The IPC tasks are created at the highest possible priority (i.e., ``configMAX_PRIORITIES - 1``) thus the callback should also run at that priority as a result. However, :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY` is enabled by default which temporarily lowers the priority of the target CPU's IPC task to the calling CPU before executing the callback.
|
- The IPC tasks are created at the highest possible priority (i.e., ``configMAX_PRIORITIES - 1``).
|
||||||
|
|
||||||
|
- If :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY` is enabled, the target core's IPC task will be lowered to the current priority of the target core before executing the callback.
|
||||||
|
- If :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY` is disabled, the target core will always execute the callback at the highest possible priority.
|
||||||
|
|
||||||
- Depending on the complexity of the callback, users may need to configure the stack size of the IPC task via :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE`.
|
- Depending on the complexity of the callback, users may need to configure the stack size of the IPC task via :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE`.
|
||||||
- The IPC feature is internally protected by a mutex. Therefore, simultaneous IPC calls from two or more calling CPUs are handled on a first come first serve basis.
|
- The IPC feature is internally protected by a mutex. Therefore, simultaneous IPC calls from two or more calling core's are serialized on a first come first serve basis.
|
||||||
|
|
||||||
API Usage
|
API Usage
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
Task Context IPC callbacks have the following restrictions:
|
Task Context IPC callbacks have the following restrictions:
|
||||||
|
|
||||||
- The callback must be of type ``void func(void *arg)``
|
- The callback must be of the :cpp:type:`esp_ipc_func_t` type.
|
||||||
- The callback should avoid attempting to block or yield as this will result in the target CPU's IPC task blocking or yielding.
|
- The callback **must never block or yield** as this will result in the target core's IPC task blocking or yielding.
|
||||||
- The callback must avoid changing any aspect of the IPC task (e.g., by calling ``vTaskPrioritySet(NULL, x)``).
|
- The callback must avoid changing any aspect of the IPC task's state, e.g., by calling ``vTaskPrioritySet(NULL, x)``.
|
||||||
|
|
||||||
The IPC feature offers the API listed below to execute a callback in a task context on a target CPU. The API allows the calling CPU to block until the callback's execution has completed, or return immediately once the callback's execution has started.
|
The IPC feature offers the API listed below to execute a callback in a task context on a target core. The API allows the calling core to block until the callback's execution has completed, or return immediately once the callback's execution has started.
|
||||||
|
|
||||||
- :cpp:func:`esp_ipc_call` triggers an IPC call on the target CPU. This function will block until the target CPU's IPC task **begins** execution of the callback.
|
- :cpp:func:`esp_ipc_call` triggers an IPC call on the target core. This function will block until the target core's IPC task **begins** execution of the callback.
|
||||||
- :cpp:func:`esp_ipc_call_blocking` triggers an IPC on the target CPU. This function will block until the target CPU's IPC task **completes** execution of the callback.
|
- :cpp:func:`esp_ipc_call_blocking` triggers an IPC on the target core. This function will block until the target core's IPC task **completes** execution of the callback.
|
||||||
|
|
||||||
IPC in Interrupt Context
|
IPC in Interrupt Context
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
In some cases, we need to quickly obtain the state of another CPU such as in a core dump, GDB stub, various unit tests, and DPORT workaround. The IPC ISR feature implements the High Priority Interrupt context by reserving a High Priority Interrupt on each CPU for IPC usage. When a calling CPU needs to execute a callback on the target CPU, the callback will execute in the context of the High Priority Interrupt of the target CPU.
|
In some cases, we need to quickly obtain the state of another core such as in a core dump, GDB stub, various unit tests, and hardware errata workarounds. The IPC ISR feature implements callback execution from a High Priority Interrupt context by reserving a High Priority Interrupt on each core for IPC usage. When a calling core needs to execute a callback on the target core, the callback will execute in the context of the High Priority Interrupt of the target core.
|
||||||
|
|
||||||
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
@ -61,10 +67,10 @@ When using IPCs in High Priority Interrupt context, users need to consider the f
|
|||||||
When the callback executes, users need to consider the following:
|
When the callback executes, users need to consider the following:
|
||||||
|
|
||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
- The calling CPU will disable interrupts of level 3 and lower.
|
- The calling core will disable interrupts of priority level 3 and lower.
|
||||||
:CONFIG_IDF_TARGET_ARCH_XTENSA: - Although the priority of the reserved interrupt depends on :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`, during the execution IPC ISR callback, the target CPU will disable interrupts of level 5 and lower regardless of what :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` is set to.
|
:CONFIG_IDF_TARGET_ARCH_XTENSA: - Although the priority of the reserved interrupt depends on :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`, during the execution of IPC ISR callback, the target core will disable interrupts of priority level 5 and lower regardless of what :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` is set to.
|
||||||
:CONFIG_IDF_TARGET_ARCH_RISCV: - Although the priority of the reserved interrupt depends on :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`, during the execution IPC ISR callback, the target CPU will disable all interrupts.
|
:CONFIG_IDF_TARGET_ARCH_RISCV: - Although the priority of the reserved interrupt depends on :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`, during the execution of IPC ISR callback, the target core will disable all interrupts.
|
||||||
|
|
||||||
API Usage
|
API Usage
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
@ -73,32 +79,32 @@ API Usage
|
|||||||
|
|
||||||
High Priority Interrupt IPC callbacks have the following restrictions:
|
High Priority Interrupt IPC callbacks have the following restrictions:
|
||||||
|
|
||||||
- The callback must be of type ``void func(void *arg)`` but implemented entirely in assembly
|
- The callback must be of type :cpp:type:`esp_ipc_isr_func_t` but implemented entirely in assembly.
|
||||||
- The callback is invoked via the ``CALLX0`` instruction with register windowing disabled, thus the callback:
|
- The callback is invoked via the ``CALLX0`` instruction with register windowing disabled, thus the callback:
|
||||||
- Must not call any register window related instructions (e.g., ``entry`` and ``retw``).
|
- must not call any register window related instructions, e.g., ``entry`` and ``retw``.
|
||||||
- Must not call other C functions as register windowing is disabled
|
- must not call other C functions as register windowing is disabled.
|
||||||
- The callback should be placed in IRAM at a 4-byte aligned address
|
- The callback should be placed in IRAM at a 4-byte aligned address.
|
||||||
- (On invocation of/after returning from) the callback, the registers ``a2, a3, a4`` are (saved/restored) automatically thus can be used in the callback. The callback should **ONLY** use those registers.
|
- On invocation of, or after returning from the callback, the registers ``a2, a3, a4`` are saved/restored automatically, thus can be used in the callback. The callback should **ONLY** use those registers.
|
||||||
- ``a2`` contains the ``void *arg`` of the callback
|
- ``a2`` contains the ``void *arg`` of the callback.
|
||||||
- ``a3/a4`` are free to use as scratch registers
|
- ``a3/a4`` are free to use as scratch registers.
|
||||||
|
|
||||||
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
||||||
|
|
||||||
High Priority Interrupt IPC callbacks have the same restrictions as for regular interrupt handlers. The callback function can be written in C.
|
High Priority Interrupt IPC callbacks must be of type :cpp:type:`esp_ipc_isr_func_t` and have the same restrictions as for regular interrupt handlers. The callback function can be written in C.
|
||||||
|
|
||||||
The IPC feature offers the API listed below to execute a callback in a High Priority Interrupt context.
|
The IPC feature offers the API listed below to execute a callback in a High Priority Interrupt context:
|
||||||
|
|
||||||
- :cpp:func:`esp_ipc_isr_call` triggers an IPC call on the target CPU. This function will busy-wait until the target CPU begins execution of the callback.
|
- :cpp:func:`esp_ipc_isr_call` triggers an IPC call on the target core. This function will busy-wait until the target core **begins** execution of the callback.
|
||||||
- :cpp:func:`esp_ipc_isr_call_blocking` triggers an IPC call on the target CPU. This function will busy-wait until the target CPU completes execution of the callback.
|
- :cpp:func:`esp_ipc_isr_call_blocking` triggers an IPC call on the target core. This function will busy-wait until the target core **completes** execution of the callback.
|
||||||
|
|
||||||
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
The following code-blocks demonstrates a High Priority Interrupt IPC callback written in assembly that simply reads the target CPU's cycle count.
|
The following code-blocks demonstrates a High Priority Interrupt IPC callback written in assembly that simply reads the target core's cycle count:
|
||||||
|
|
||||||
.. code-block:: asm
|
.. code-block:: asm
|
||||||
|
|
||||||
/* esp_test_ipc_isr_get_cycle_count_other_cpu(void *arg) */
|
/* esp_test_ipc_isr_get_cycle_count_other_cpu(void *arg) */
|
||||||
// this function reads CCOUNT of the target CPU and stores it in arg.
|
// this function reads CCOUNT of the target core and stores it in arg.
|
||||||
// use only a2, a3 and a4 regs here.
|
// use only a2, a3 and a4 regs here.
|
||||||
.section .iram1, "ax"
|
.section .iram1, "ax"
|
||||||
.align 4
|
.align 4
|
||||||
@ -122,7 +128,7 @@ The IPC feature offers the API listed below to execute a callback in a High Prio
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For more examples of High Priority Interrupt IPC callbacks, see :idf_file:`components/esp_system/port/arch/xtensa/esp_ipc_isr_routines.S` and :idf_file:`components/esp_system/test_apps/esp_system_unity_tests/main/port/arch/xtensa/test_ipc_isr.S`.
|
For more examples of High Priority Interrupt IPC callbacks, you can refer to :idf_file:`components/esp_system/port/arch/xtensa/esp_ipc_isr_routines.S` and :idf_file:`components/esp_system/test_apps/esp_system_unity_tests/main/port/arch/xtensa/test_ipc_isr.S`.
|
||||||
|
|
||||||
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
||||||
|
|
||||||
@ -132,13 +138,13 @@ The IPC feature offers the API listed below to execute a callback in a High Prio
|
|||||||
|
|
||||||
See :idf_file:`examples/system/ipc/ipc_isr/xtensa/main/main.c` for an example of its use.
|
See :idf_file:`examples/system/ipc/ipc_isr/xtensa/main/main.c` for an example of its use.
|
||||||
|
|
||||||
The High Priority Interrupt IPC API also provides the following convenience functions that can stall/resume the target CPU. These API utilize the High Priority Interrupt IPC, but supply their own internal callbacks:
|
The High Priority Interrupt IPC API also provides the following convenience functions that can stall/resume the target core. These APIs utilize the High Priority Interrupt IPC, but supply their own internal callbacks:
|
||||||
|
|
||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
:CONFIG_IDF_TARGET_ARCH_RISCV: - :cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the target CPU. The calling CPU disables interrupts of level 3 and lower while the target CPU will busy-wait with all interrupts disabled. The target CPU will busy-wait until :cpp:func:`esp_ipc_isr_release_other_cpu` is called.
|
:CONFIG_IDF_TARGET_ARCH_RISCV: - :cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the target core. The calling core disables interrupts of level 3 and lower, while the target core will busy-wait with all interrupts disabled. The target core will busy-wait until :cpp:func:`esp_ipc_isr_release_other_cpu` is called.
|
||||||
:CONFIG_IDF_TARGET_ARCH_XTENSA: - :cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the target CPU. The calling CPU disables interrupts of level 3 and lower while the target CPU will busy-wait with interrupts of level 5 and lower disabled. The target CPU will busy-wait until :cpp:func:`esp_ipc_isr_release_other_cpu` is called.
|
:CONFIG_IDF_TARGET_ARCH_XTENSA: - :cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the target core. The calling core disables interrupts of level 3 and lower while the target core will busy-wait with interrupts of level 5 and lower disabled. The target core will busy-wait until :cpp:func:`esp_ipc_isr_release_other_cpu` is called.
|
||||||
- :cpp:func:`esp_ipc_isr_release_other_cpu` resumes the target CPU.
|
- :cpp:func:`esp_ipc_isr_release_other_cpu` resumes the target core.
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
|
@ -1 +1,154 @@
|
|||||||
.. include:: ../../../en/api-reference/system/ipc.rst
|
处理器间调用 (IPC)
|
||||||
|
====================
|
||||||
|
|
||||||
|
:link_to_translation:`en:[English]`
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
IPC 指 **处理器间调用** (Inter-Processor Call),而不是其他操作系统中所指的 **进程间通信** (Inter-Process Communication)。
|
||||||
|
|
||||||
|
概述
|
||||||
|
--------
|
||||||
|
|
||||||
|
由于 {IDF_TARGET_NAME} 的双核特性,在某些情况下,某个回调必须在特定的内核上下文中运行。例如:
|
||||||
|
|
||||||
|
- 为特定内核的中断源分配 ISR,或释放特定内核的中断源时
|
||||||
|
- 在特定芯片(如 ESP32)上访问某个内核独有的内存,如 RTC Fast Memory 时
|
||||||
|
- 读取另一个内核的寄存器或状态时
|
||||||
|
|
||||||
|
IPC 功能允许一个特定的内核(下文称“调用内核”)触发另一个内核(下文称“目标内核”)的回调函数执行,并允许目标内核在任务上下文或中断上下文中执行回调函数。在不同的上下文中,回调函数的实现限制有所不同。
|
||||||
|
|
||||||
|
任务上下文中的 IPC
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
在应用程序启动时,IPC 功能为每个内核创建一个 IPC 任务,从而在任务上下文中执行回调。当调用内核需要在目标内核中执行回调时,回调将在目标内核的 IPC 任务的上下文中执行。
|
||||||
|
|
||||||
|
在任务上下文中使用 IPC 功能时,需考虑以下几点:
|
||||||
|
|
||||||
|
- IPC 回调应该尽可能简短。 **IPC 回调决不能阻塞或让出**。
|
||||||
|
- IPC 任务是以尽可能高的优先级创建的(即 ``configMAX_PRIORITIES - 1``)。
|
||||||
|
|
||||||
|
- 如果启用了 :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY`,执行回调前会降低目标内核的 IPC 任务优先级,使其等于调用内核的优先级。
|
||||||
|
- 如果禁用了 :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY`,目标内核将始终以尽可能高的优先级执行回调。
|
||||||
|
|
||||||
|
- 如果回调较为复杂,用户可能需要通过 :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE` 来配置 IPC 任务的堆栈大小。
|
||||||
|
- IPC 功能受内部互斥锁保护。因此,如果同时收到来自两个或多个调用内核的 IPC 请求,将按照“先到先得”的原则按顺序处理。
|
||||||
|
|
||||||
|
API 用法
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
任务上下文中的 IPC 回调具有以下限制:
|
||||||
|
|
||||||
|
- 回调类型必须是 :cpp:type:`esp_ipc_func_t`。
|
||||||
|
- 回调 **决不能阻塞或让出**,以免导致目标内核的 IPC 任务阻塞或让出。
|
||||||
|
- 回调必须避免改变 IPC 任务的任何状态,例如,不能调用 ``vTaskPrioritySet(NULL, x)``。
|
||||||
|
|
||||||
|
IPC 功能提供了以下 API,用于在目标内核的任务上下文中执行回调。这两个 API 允许调用内核在回调执行完成前处于阻塞,或者在回调开始执行后立即返回。
|
||||||
|
|
||||||
|
- :cpp:func:`esp_ipc_call` 会在目标内核上触发一个 IPC 调用。在目标内核的 IPC 任务 **开始** 执行回调前,此函数会一直处于阻塞状态。
|
||||||
|
- :cpp:func:`esp_ipc_call_blocking` 会在目标内核上触发一个 IPC。在目标内核的 IPC 任务 **完成** 回调执行前,此函数会一直处于阻塞状态。
|
||||||
|
|
||||||
|
中断上下文中的 IPC
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
在某些情况下,我们需要快速获取另一个内核的状态,如在核心转储、GDB Stub、各种单元测试和绕过硬件错误的过程中。IPC ISR 功能会在每个内核上保留一个高优先级中断供 IPC 使用,从而在高优先级中断上下文中执行回调。当调用内核需要在目标内核上执行回调时,该回调将在目标内核的高优先级中断的上下文中执行。
|
||||||
|
|
||||||
|
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
|
在这种情况下,IPC ISR 功能支持在 :doc:`高优先级中断 </api-guides/hlinterrupts>` 上下文中执行回调。
|
||||||
|
|
||||||
|
在高优先级中断上下文中使用 IPC 时,需要考虑以下几点:
|
||||||
|
|
||||||
|
.. list::
|
||||||
|
|
||||||
|
:CONFIG_IDF_TARGET_ARCH_XTENSA: - 由于回调是在高优先级中断上下文中执行的,因此,回调必须完全用汇编语言编写。如需了解更多关于用汇编语言编写回调的内容,请参阅下文的 API 使用介绍。
|
||||||
|
- 保留的高优先级中断的优先级取决于 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 选项。
|
||||||
|
|
||||||
|
当回调执行时,需考虑以下几点:
|
||||||
|
|
||||||
|
.. list::
|
||||||
|
|
||||||
|
- 调用内核会禁用 3 级及以下优先级的中断。
|
||||||
|
:CONFIG_IDF_TARGET_ARCH_XTENSA: - 虽然保留中断的优先级取决于 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`,但是在执行 IPC ISR 回调期间,无论 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 如何设置,目标内核都会禁用 5 级及以下优先级的中断。
|
||||||
|
:CONFIG_IDF_TARGET_ARCH_RISCV: - 虽然保留中断的优先级取决于 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`,但是在执行 IPC ISR 回调期间,目标内核会禁用所有的中断。
|
||||||
|
|
||||||
|
API 用法
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
|
高优先级中断的 IPC 回调具有以下限制:
|
||||||
|
|
||||||
|
- 回调必须是 :cpp:type:`esp_ipc_isr_func_t` 类型,但必须完全用汇编语言实现。
|
||||||
|
- 回调通过 ``CALLX0`` 指令调用,同时禁用寄存器窗口,因此,该回调:
|
||||||
|
- 不得调用任何与寄存器窗口相关的指令,例如 ``entry`` 和 ``retw``。
|
||||||
|
- 由于禁用了寄存器窗口,不得调用其他 C 函数。
|
||||||
|
- 回调应放在 4 字节对齐的 IRAM 地址上。
|
||||||
|
- 在调用或返回回调后,寄存器 ``a2``,``a3``,和 ``a4`` 会被自动保存或恢复,从而在回调中使用。回调 **只能使用这些寄存器**。
|
||||||
|
- ``a2`` 包含回调的 ``void *arg``。
|
||||||
|
- ``a3/a4`` 可以作为临时寄存器使用。
|
||||||
|
|
||||||
|
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
||||||
|
|
||||||
|
高优先级中断 IPC 回调函数的类型必须是 :cpp:type:`esp_ipc_isr_func_t`,其限制条件与常规中断处理程序相同。回调函数可以用 C 语言编写。
|
||||||
|
|
||||||
|
IPC 功能提供了下列 API,以在高优先级中断的上下文中执行回调:
|
||||||
|
|
||||||
|
- :cpp:func:`esp_ipc_isr_call` 能够在目标内核上触发一个 IPC 调用。在目标内核 **开始** 执行回调前,此函数将一直处于忙等待。
|
||||||
|
- :cpp:func:`esp_ipc_isr_call_blocking` 能够在目标内核上触发一个 IPC 调用。在目标内核 **完成** 回调执行前,此函数将一直处于忙等待。
|
||||||
|
|
||||||
|
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
|
以下示例代码用汇编语言编写了一个高优先级中断 IPC 回调,该回调的作用为读取目标内核的周期计数:
|
||||||
|
|
||||||
|
.. code-block:: asm
|
||||||
|
|
||||||
|
/* esp_test_ipc_isr_get_cycle_count_other_cpu(void *arg) */
|
||||||
|
// 此函数读取目标内核的 CCOUNT,并将其存储到 arg 中。
|
||||||
|
// 此处仅使用 a2、a3 和 a4 寄存器。
|
||||||
|
.section .iram1, "ax"
|
||||||
|
.align 4
|
||||||
|
.global esp_test_ipc_isr_get_cycle_count_other_cpu
|
||||||
|
.type esp_test_ipc_isr_get_cycle_count_other_cpu, @function
|
||||||
|
// Args:
|
||||||
|
// a2 - void* arg
|
||||||
|
esp_test_ipc_isr_get_cycle_count_other_cpu:
|
||||||
|
rsr.ccount a3
|
||||||
|
s32i a3, a2, 0
|
||||||
|
ret
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
unit32_t cycle_count;
|
||||||
|
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)cycle_count);
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
对于大多数简单用例,可用的临时寄存器数量是足够的。如果需要在回调函数中使用更多的临时寄存器,可以用 ``void *arg`` 指向一个用作寄存器保存区域的 buffer,使回调函数保存或恢复更多的寄存器。前往 :example:`system/ipc/ipc_isr` 查看示例。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
如需查看更多高优先级中断 IPC 回调的示例,请前往 :idf_file:`components/esp_system/port/arch/xtensa/esp_ipc_isr_routines.S` 和 :idf_file:`components/esp_system/test_apps/esp_system_unity_tests/main/port/arch/xtensa/test_ipc_isr.S`。
|
||||||
|
|
||||||
|
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
||||||
|
|
||||||
|
请前往 :idf_file:`examples/system/ipc/ipc_isr/riscv/main/main.c` 查看使用示例。
|
||||||
|
|
||||||
|
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
|
请前往 :idf_file:`examples/system/ipc/ipc_isr/xtensa/main/main.c` 查看使用示例。
|
||||||
|
|
||||||
|
高优先级中断 IPC API 还提供了以下便利函数,这些函数可以暂停或恢复目标内核的执行。这些 API 利用高优先级中断 IPC,但同时提供了自己的内部回调函数:
|
||||||
|
|
||||||
|
.. list::
|
||||||
|
|
||||||
|
:CONFIG_IDF_TARGET_ARCH_RISCV: - :cpp:func:`esp_ipc_isr_stall_other_cpu`:暂停目标内核。调用内核禁用 3 级及以下级别的中断,而目标内核将在所有中断被禁用的情况下进入忙等待。在调用 :cpp:func:`esp_ipc_isr_release_other_cpu` 前,目标内核会保持忙等待。
|
||||||
|
:CONFIG_IDF_TARGET_ARCH_XTENSA: - :cpp:func:`esp_ipc_isr_stall_other_cpu`:暂停目标内核。调用内核禁用 3 级及以下级别的中断,而目标内核将在 5 级及以下的中断被禁用的情况下进入忙等待。在调用 :cpp:func:`esp_ipc_isr_release_other_cpu` 前,目标内核会保持忙等待。
|
||||||
|
- :cpp:func:`esp_ipc_isr_release_other_cpu`:恢复目标内核。
|
||||||
|
|
||||||
|
API 参考
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. include-build-file:: inc/esp_ipc.inc
|
||||||
|
|
||||||
|
.. include-build-file:: inc/esp_ipc_isr.inc
|
||||||
|
Loading…
Reference in New Issue
Block a user