mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'feature/adds_ipc_isr_safe_api_v6.1' into 'release/v6.1'
feat(ipc_isr): Adds IPC ISR safe API to stall other CPU (v6.1) See merge request espressif/esp-idf!50963
This commit is contained in:
@@ -97,6 +97,11 @@ The IPC feature offers the API listed below to execute a callback in a High Prio
|
||||
- :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 core. This function will busy-wait until the target core **completes** execution of the callback.
|
||||
|
||||
These functions interrupt the other CPU and execute the callback in the context of a High Priority Interrupt. There are two common usage patterns:
|
||||
|
||||
- For simple callbacks that do not enter critical sections shared with the other CPU, call :cpp:func:`esp_ipc_isr_call` or :cpp:func:`esp_ipc_isr_call_blocking` directly.
|
||||
- If the calling CPU may enter critical sections used by the other CPU, or if several callbacks must run while the other CPU remains stopped, first stall the other CPU using :cpp:func:`esp_ipc_isr_stall_other_cpu` or :cpp:func:`esp_ipc_isr_stall_other_cpu_safe`. Then use :cpp:func:`esp_ipc_isr_call` or :cpp:func:`esp_ipc_isr_call_blocking` to execute callbacks. After the operation is complete, release the other CPU with :cpp:func:`esp_ipc_isr_release_other_cpu`.
|
||||
|
||||
.. 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 core's cycle count:
|
||||
@@ -117,10 +122,23 @@ The IPC feature offers the API listed below to execute a callback in a High Prio
|
||||
s32i a3, a2, 0
|
||||
ret
|
||||
|
||||
The callback can be called directly when no shared critical section can deadlock:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
unit32_t cycle_count;
|
||||
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)cycle_count);
|
||||
uint32_t cycle_count;
|
||||
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)&cycle_count);
|
||||
|
||||
Alternatively, safely stall the other CPU before making one or more IPC calls:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
while (esp_ipc_isr_stall_other_cpu_safe() != ESP_OK) {
|
||||
// Optionally, add a timeout or yield to avoid infinite loop
|
||||
}
|
||||
uint32_t cycle_count;
|
||||
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)&cycle_count);
|
||||
esp_ipc_isr_release_other_cpu();
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -144,6 +162,7 @@ The High Priority Interrupt IPC API also provides the following convenience func
|
||||
|
||||
: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 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_stall_other_cpu_safe` attempts to stall the other core only if it is not in a critical section or ISR context. If the other core is in such a state, the function considers it unsafe to stall, releases the core, and returns an error.
|
||||
- :cpp:func:`esp_ipc_isr_release_other_cpu` resumes the target core.
|
||||
|
||||
Application Examples
|
||||
|
||||
@@ -97,6 +97,11 @@ IPC 功能提供了下列 API,以在高优先级中断的上下文中执行回
|
||||
- :cpp:func:`esp_ipc_isr_call` 能够在目标内核上触发一个 IPC 调用。在目标内核 **开始** 执行回调前,此函数将一直处于忙等待。
|
||||
- :cpp:func:`esp_ipc_isr_call_blocking` 能够在目标内核上触发一个 IPC 调用。在目标内核 **完成** 回调执行前,此函数将一直处于忙等待。
|
||||
|
||||
这些函数会中断另一 CPU,并在高优先级中断的上下文中执行回调。常见用法有两种:
|
||||
|
||||
- 对于不会进入与另一 CPU 共享的临界区的简单回调,可以直接调用 :cpp:func:`esp_ipc_isr_call` 或 :cpp:func:`esp_ipc_isr_call_blocking`。
|
||||
- 如果调用 CPU 可能进入另一 CPU 使用的临界区,或者需要在另一 CPU 保持停止时执行多个回调,则应先使用 :cpp:func:`esp_ipc_isr_stall_other_cpu` 或 :cpp:func:`esp_ipc_isr_stall_other_cpu_safe` 暂停另一 CPU。然后使用 :cpp:func:`esp_ipc_isr_call` 或 :cpp:func:`esp_ipc_isr_call_blocking` 执行回调。操作完成后,使用 :cpp:func:`esp_ipc_isr_release_other_cpu` 释放另一 CPU。
|
||||
|
||||
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
以下示例代码用汇编语言编写了一个高优先级中断 IPC 回调,该回调的作用为读取目标内核的周期计数:
|
||||
@@ -117,10 +122,23 @@ IPC 功能提供了下列 API,以在高优先级中断的上下文中执行回
|
||||
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);
|
||||
uint32_t cycle_count;
|
||||
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)&cycle_count);
|
||||
|
||||
或者,也可以在进行一次或多次 IPC 调用之前,安全地暂停另一 CPU:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
while (esp_ipc_isr_stall_other_cpu_safe() != ESP_OK) {
|
||||
// 在生产代码中,可按需添加超时或 yield,以避免无限循环。
|
||||
}
|
||||
uint32_t cycle_count;
|
||||
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)&cycle_count);
|
||||
esp_ipc_isr_release_other_cpu();
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -144,6 +162,7 @@ IPC 功能提供了下列 API,以在高优先级中断的上下文中执行回
|
||||
|
||||
: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_stall_other_cpu_safe`:仅当另一内核不在临界区或 ISR 上下文中时,才尝试暂停该内核。如果另一内核处于此类状态,则认为暂停不安全,会释放该内核并返回错误。
|
||||
- :cpp:func:`esp_ipc_isr_release_other_cpu`:恢复目标内核。
|
||||
|
||||
应用示例
|
||||
|
||||
Reference in New Issue
Block a user