Inter-Processor Call¶
Overview¶
Due to the dual core nature of the ESP32, there are instances where a certain function must be run in the context of a particular core (e.g. allocating ISR to an interrupt source of a particular core). The IPC (Inter-Processor Call) feature allows for the execution of functions on a particular CPU.
A given function can be executed on a particular core by calling
esp_ipc_call()
or esp_ipc_call_blocking()
. IPC is
implemented via two high priority FreeRTOS tasks pinned to each CPU known as
the IPC Tasks. The two IPC Tasks remain inactive (blocked) until
esp_ipc_call()
or esp_ipc_call_blocking()
is called. When
an IPC Task of a particular core is unblocked, it will preempt the current
running task on that core and execute a given function.
Usage¶
esp_ipc_call()
unblocks the IPC task on a particular core to execute
a given function. The task that calls esp_ipc_call()
will be blocked
until the IPC Task begins execution of the given function.
esp_ipc_call_blocking()
is similar but will block the calling task
until the IPC Task has completed execution of the given function.
Functions executed by IPCs must be functions of type void func(void *arg). To run more complex functions which require a larger stack, the IPC tasks’ stack size can be configured by modifying CONFIG_ESP_IPC_TASK_STACK_SIZE in menuconfig. The IPC API is protected by a mutex hence simultaneous IPC calls are not possible.
Care should taken to avoid deadlock when writing functions to be executed by IPC, especially when attempting to take a mutex within the function.
API Reference¶
Header File¶
Functions¶
-
esp_err_t
esp_ipc_call
(uint32_t cpu_id, esp_ipc_func_t func, void *arg)¶ Execute a function on the given CPU.
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.
- Note
In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
- Return
ESP_ERR_INVALID_ARG if cpu_id is invalid
ESP_ERR_INVALID_STATE if the FreeRTOS scheduler is not running
ESP_OK otherwise
- Parameters
[in] cpu_id
: CPU where the given function should be executed (0 or 1)[in] func
: Pointer to a function of type void func(void* arg) to be executed[in] arg
: Arbitrary argument of type void* to be passed into the function
-
esp_err_t
esp_ipc_call_blocking
(uint32_t cpu_id, esp_ipc_func_t func, void *arg)¶ Execute a function on the given CPU and blocks 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.
- Note
In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
- Return
ESP_ERR_INVALID_ARG if cpu_id is invalid
ESP_ERR_INVALID_STATE if the FreeRTOS scheduler is not running
ESP_OK otherwise
- Parameters
[in] cpu_id
: CPU where the given function should be executed (0 or 1)[in] func
: Pointer to a function of type void func(void* arg) to be executed[in] arg
: Arbitrary argument of type void* to be passed into the function