esp_ipc: Update documentation and API descriptions

This commit updates the documentation and API descriptions of
the esp_ipc and esp_ipc_isr features.
This commit is contained in:
KonstantinKondrashov
2021-10-26 21:12:26 +08:00
committed by Darian Leung
parent 460f3ad7b6
commit 209702d055
12 changed files with 182 additions and 144 deletions

View File

@@ -512,33 +512,27 @@ menu "IPC (Inter-Processor Call)"
default 2048 if APPTRACE_ENABLE
default 1024
help
Configure the IPC tasks stack size. One IPC task runs on each core
(in dual core mode), and allows for cross-core function calls.
See IPC documentation for more details.
The default stack size should be enough for most common use cases.
It can be shrunk if you are sure that you do not use any custom
IPC functionality.
Configure the IPC tasks stack size. An IPC task runs on each core (in dual core mode), and allows for
cross-core function calls. See IPC documentation for more details. The default IPC stack size should be
enough for most common simple use cases. However, users can increase/decrease the stack size to their
needs.
config ESP_IPC_USES_CALLERS_PRIORITY
bool "IPC runs at caller's priority"
default y
depends on !FREERTOS_UNICORE
help
If this option is not enabled then the IPC task will keep behavior
same as prior to that of ESP-IDF v4.0, and hence IPC task will run
at (configMAX_PRIORITIES - 1) priority.
If this option is not enabled then the IPC task will keep behavior same as prior to that of ESP-IDF v4.0,
hence IPC task will run at (configMAX_PRIORITIES - 1) priority.
config ESP_IPC_ISR_ENABLE
bool
default y if !FREERTOS_UNICORE
help
This feature serves a similar purpose to the IPC except that the callback function is run
in the context of a level 4 interrupt (i.e., high priority/level interrupt). The IPC ISR
feature is intended for low latency execution of simple functions written in assembly on
another CPU. Due to being run in higher level interrupt context, the assembly functions
should be written in a particular way (see esp_test_ipc_isr_asm() and the "High-Level Interrupts"
chapter in hlinterrupts.rst for more details).
The IPC ISR feature is similar to the IPC feature except that the callback function is executed in the
context of a High Priority Interrupt. The IPC ISR feature is itended for low latency execution of simple
callbacks written in assembly on another CPU. Due to being run in a High Priority Interrupt, the assembly
callbacks must be written with particular restrictions (see "IPC" and "High-Level Interrupt" docs for more
details).
endmenu # "IPC (Inter-Processor Call)

View File

@@ -195,6 +195,6 @@ esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void
return ret == pdTRUE ? ESP_OK : ESP_FAIL;
}
#endif
#endif // CONFIG_APPTRACE_GCOV_ENABLE
#endif // not CONFIG_FREERTOS_UNICORE or CONFIG_APPTRACE_GCOV_ENABLE
#endif // !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)

View File

@@ -4,8 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __ESP_IPC_H__
#define __ESP_IPC_H__
#pragma once
#include <esp_err.h>
@@ -15,30 +14,30 @@ extern "C" {
#if !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)
/** @cond */
typedef void (*esp_ipc_func_t)(void* arg);
/** @endcond */
/*
* Inter-processor call APIs
*
* FreeRTOS provides several APIs which can be used to communicate between
* different tasks, including tasks running on different CPUs.
* This module provides additional APIs to run some code on the other CPU.
*
* These APIs can only be used when FreeRTOS scheduler is running.
* FreeRTOS provides several APIs which can be used to communicate between different tasks, including tasks running on
* different CPUs. This module provides additional APIs to run some code on the other CPU. These APIs can only be used
* when FreeRTOS scheduler is running.
*/
/**
* @brief Execute a function on the given CPU
* @brief IPC Callback
*
* Run a given function on a particular CPU. The given function must accept a
* void* argument and return void. The given function is run in the context of
* the IPC task of the CPU specified by the cpu_id parameter. The calling task
* will be blocked until the IPC task begins executing the given function. If
* another IPC call is ongoing, the calling task will block until the other IPC
* call completes. The stack size allocated for the IPC task can be configured
* in the "Inter-Processor Call (IPC) task stack size" setting in menuconfig.
* Increase this setting if the given function requires more stack than default.
* A callback of this type should be provided as an argument when calling esp_ipc_call() or esp_ipc_call_blocking().
*/
typedef void (*esp_ipc_func_t)(void* arg);
/**
* @brief Execute a callback on a given CPU
*
* Execute a given callback on a particular CPU. The callback must be of type "esp_ipc_func_t" and will be invoked in
* the context of the target CPU's IPC task.
*
* - This function will block the target CPU's IPC task has begun execution of the callback
* - If another IPC call is ongoing, this function will block until the ongoing IPC call completes
* - The stack size of the IPC task can be configured via the CONFIG_ESP_IPC_TASK_STACK_SIZE option
*
* @note In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
*
@@ -55,17 +54,10 @@ esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
/**
* @brief Execute a function on the given CPU and blocks until it completes
* @brief Execute a callback on a given CPU until and block until it completes
*
* Run a given function on a particular CPU. The given function must accept a
* void* argument and return void. The given function is run in the context of
* the IPC task of the CPU specified by the cpu_id parameter. The calling task
* will be blocked until the IPC task completes execution of the given function.
* If another IPC call is ongoing, the calling task will block until the other
* IPC call completes. The stack size allocated for the IPC task can be
* configured in the "Inter-Processor Call (IPC) task stack size" setting in
* menuconfig. Increase this setting if the given function requires more stack
* than default.
* This function is identical to esp_ipc_call() except that this function will block until the execution of the callback
* completes.
*
* @note In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
*
@@ -80,10 +72,8 @@ esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
*/
esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
#endif // not CONFIG_FREERTOS_UNICORE or CONFIG_APPTRACE_GCOV_ENABLE
#endif // !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE)
#ifdef __cplusplus
}
#endif
#endif /* __ESP_IPC_H__ */

View File

@@ -14,31 +14,38 @@ extern "C" {
#ifdef CONFIG_ESP_IPC_ISR_ENABLE
/** @cond */
/**
* @brief IPC ISR Callback
*
* A callback of this type should be provided as an argument when calling esp_ipc_isr_asm_call() or
* esp_ipc_isr_asm_call_blocking().
*/
typedef void (*esp_ipc_isr_func_t)(void* arg);
/** @endcond */
/**
* @brief Initialize inter-processor call module which based on #4 high-interrupt.
* @brief Initialize the IPC ISR feature
*
* This function is called on CPU start and should not be called from the application.
* This function initializes the IPC ISR feature and must be called before any other esp_ipc_isr...() functions.
* The IPC ISR feature allows for callbacks (written in assembly) to be run on a particular CPU in the context of a
* High Priority Interrupt.
*
* This function starts two tasks, one on each CPU. These tasks register
* #4 High-interrupt and after that, the tasks are deleted.
* The next API functions work with this functionality:
* esp_ipc_isr_asm_call
* esp_ipc_isr_asm_call_blocking
* They allow to run an asm function on other CPU.
* - This function will register a High Priority Interrupt on each CPU. The priority of the interrupts is dependent on
* the CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL option.
* - Callbacks written in assembly can then run in context of the registered High Priority Interrupts
* - Callbacks can be executed by calling esp_ipc_isr_asm_call() or esp_ipc_isr_asm_call_blocking()
*/
void esp_ipc_isr_init(void);
/**
* @brief Execute an asm function on the other CPU (uses the #4 high-priority interrupt)
* @brief Execute an assembly callback on the other CPU
*
* @note In single-core mode, it is not available.
* This function calls the #4 high-priority interrupt on the other CPU.
* The given function is called in the context of the interrupt by CALLX0 command and
* operates with registers a2, a3, a4.
* Execute a given callback on the other CPU in the context of a High Priority Interrupt.
*
* - This function will busy-wait in a critical section until the other CPU has started execution of the callback
* - The callback must be written in assembly, is invoked using a CALLX0 instruction, and has a2, a3, a4 as scratch
* registers. See docs for more details
*
* @note This function is not available in single-core mode.
*
* @param[in] func Pointer to a function of type void func(void* arg) to be executed
* @param[in] arg Arbitrary argument of type void* to be passed into the function
@@ -46,11 +53,12 @@ void esp_ipc_isr_init(void);
void esp_ipc_isr_asm_call(esp_ipc_isr_func_t func, void* arg);
/**
* @brief Execute an asm function on the other CPU and blocks until it completes (uses the #4 high-priority interrupt)
* @brief Execute an assembly callback on the other CPU and busy-wait until it completes
*
* @note In single-core mode, it is not available.
* This function calls the #4 high-priority interrupt on the other CPU.
* The given function is called in the context of the interrupt by CALLX0 command.
* This function is identical to esp_ipc_isr_asm_call() except that this function will busy-wait until the execution of
* the callback completes.
*
* @note This function is not available in single-core mode.
*
* @param[in] func Pointer to a function of type void func(void* arg) to be executed
* @param[in] arg Arbitrary argument of type void* to be passed into the function
@@ -58,51 +66,60 @@ void esp_ipc_isr_asm_call(esp_ipc_isr_func_t func, void* arg);
void esp_ipc_isr_asm_call_blocking(esp_ipc_isr_func_t func, void* arg);
/**
* @brief Stall the other CPU and the current CPU disables interrupts with level 3 and lower.
* @brief Stall the other CPU
*
* @note In single-core mode, it is not available.
* This function calls the #4 high-priority interrupt on the other CPU.
* The esp_ipc_isr_finish_cmd() function is called on the other CPU in the context of the #4 high-priority interrupt.
* The esp_ipc_isr_finish_cmd is called by CALLX0 command.
* It is waiting for the end command. The command will be sent by esp_ipc_isr_release_other_cpu().
* This function is used for DPORT workaround.
* This function will stall the other CPU. The other CPU is stalled by busy-waiting in the context of a High Priority
* Interrupt. The other CPU will not be resumed until esp_ipc_isr_release_other_cpu() is called.
*
* This function blocks other CPU until the release call esp_ipc_isr_release_other_cpu().
* - This function is internally implemented using IPC ISR
* - This function is used for DPORT workaround.
* - If the stall feature is paused using esp_ipc_isr_stall_pause(), this function will have no effect
*
* This fucntion is used for the DPORT workaround: stall other cpu that this cpu is pending to access dport register start.
* @note This function is not available in single-core mode.
*/
void esp_ipc_isr_stall_other_cpu(void);
/**
* @brief Release the other CPU
*
* @note In single-core mode, it is not available.
* This function will send the end command to release the stall other CPU.
* This function is used for DPORT workaround: stall other cpu that this cpu is pending to access dport register end.
* This function will release the other CPU that was previously stalled from calling esp_ipc_isr_stall_other_cpu()
*
* - This function is used for DPORT workaround.
* - If the stall feature is paused using esp_ipc_isr_stall_pause(), this function will have no effect
*
* @note This function is not available in single-core mode.
*/
void esp_ipc_isr_release_other_cpu(void);
/**
* @brief Pause stall the other CPU
* @brief Puase the CPU stall feature
*
* This function will pause the CPU stall feature. Once paused, calls to esp_ipc_isr_stall_other_cpu() and
* esp_ipc_isr_release_other_cpu() will have no effect. If a IPC ISR call is already in progress, this function will
* busy-wait until the call completes before pausing the CPU stall feature.
*/
void esp_ipc_isr_stall_pause(void);
/**
* @brief Abort stall the other CPU
* @brief Abort a CPU stall
*
* This routine does not stop the stall routines in any way that is recoverable.
* Please only call in case of panic().
* Used in panic code: the enter_critical stuff may be messed up so we just stop everything without checking the mux.
* This function will abort any stalling routine of the other CPU due to a pervious call to
* esp_ipc_isr_stall_other_cpu(). This function aborts the stall in a non-recoverable manner, thus should only be called
* in case of a panic().
*
* - This function is used in panic handling code
*/
void esp_ipc_isr_stall_abort(void);
/**
* @brief Resume stall the other CPU
* @brief Resume the CPU stall feature
*
* This function will resume the CPU stall feature that was previously paused by calling esp_ipc_isr_stall_pause(). Once
* resumed, calls to esp_ipc_isr_stall_other_cpu() and esp_ipc_isr_release_other_cpu() will have effect again.
*/
void esp_ipc_isr_stall_resume(void);
#else // not CONFIG_ESP_IPC_ISR_ENABLE
#else // CONFIG_ESP_IPC_ISR_ENABLE
#define esp_ipc_isr_stall_other_cpu()
#define esp_ipc_isr_release_other_cpu()

View File

@@ -160,6 +160,7 @@ void IRAM_ATTR esp_ipc_isr_stall_pause(void)
void IRAM_ATTR esp_ipc_isr_stall_abort(void)
{
//Note: We don't enter a critical section here as we are calling this from a panic.
s_stall_state = STALL_STATE_IDLE;
}

View File

@@ -11,7 +11,7 @@
/* esp_ipc_isr_waiting_for_finish_cmd(void* finish_cmd)
*
* It should be called by the CALLX0 command from the handler of High-priority interrupt (4 lvl).
* It should be called by the CALLX0 command from the handler of High-priority interrupt.
* Only these registers [a2, a3, a4] can be used here.
*/
.section .iram1, "ax"

View File

@@ -11,7 +11,7 @@
/* esp_test_ipc_isr_asm(void *arg)
*
* It should be called by the CALLX0 command from the handler of High-priority interrupt (4 lvl).
* It should be called by the CALLX0 command from the handler of High-priority interrupt.
* Only these registers [a2, a3, a4] can be used here.
*/
.section .iram1, "ax"