#ifdef __cplusplus
extern "C" {
#endif
-
+/** @cond */
typedef void (*esp_ipc_func_t)(void* arg);
-
-/**
- * @brief Inter-processor call APIs
+/** @endcond */
+/*
+ * Inter-processor call APIs
*
* FreeRTOS provides several APIs which can be used to communicate between
* different tasks, including tasks running on different CPUs.
*/
-/**
- * @brief Initialize inter-processor call module.
+/*
+ * Initialize inter-processor call module. This function is called automatically
+ * on CPU start and should not be called from the application.
*
* This function start two tasks, one on each CPU. These tasks are started
* with high priority. These tasks are normally inactive, waiting until one of
* woken up to execute the callback provided to esp_ipc_call_nonblocking or
* esp_ipc_call_blocking.
*/
+/** @cond */
void esp_ipc_init();
-
+/** @endcond */
/**
- * @brief Execute function on the given CPU
- *
- * This will wake a high-priority task on CPU indicated by cpu_id argument,
- * and run func(arg) in the context of that task.
- * This function returns as soon as the high-priority task is woken up.
- * If another IPC call is already being executed, this function will also wait
- * for it to complete.
+ * @brief Execute a function on the given CPU
*
- * In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
+ * 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.
*
- * For complex functions, you may need to increase the stack size of the "IPC task"
- * which runs the function must be sufficient. See the "Inter-Processor Call (IPC)
- * task stack size" setting in menuconfig.
+ * @note In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
*
- * @param cpu_id CPU where function should be executed (0 or 1)
- * @param func pointer to a function which should be executed
- * @param arg arbitrary argument to be passed into function
+ * @param[in] cpu_id CPU where the given function should be executed (0 or 1)
+ * @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
*
- * @return ESP_ERR_INVALID_ARG if cpu_id is invalid
- * ESP_ERR_INVALID_STATE if FreeRTOS scheduler is not running
- * ESP_OK otherwise
+ * @return
+ * - ESP_ERR_INVALID_ARG if cpu_id is invalid
+ * - ESP_ERR_INVALID_STATE if the FreeRTOS scheduler is not running
+ * - ESP_OK otherwise
*/
esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
/**
- * @brief Execute function on the given CPU and wait for it to finish
+ * @brief Execute a function on the given CPU and blocks until it completes
*
- * This will wake a high-priority task on CPU indicated by cpu_id argument,
- * and run func(arg) in the context of that task.
- * This function waits for func to return.
+ * 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.
*
- * In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
+ * @note In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
*
- * @param cpu_id CPU where function should be executed (0 or 1)
- * @param func pointer to a function which should be executed
- * @param arg arbitrary argument to be passed into function
+ * @param[in] cpu_id CPU where the given function should be executed (0 or 1)
+ * @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
*
- * @return ESP_ERR_INVALID_ARG if cpu_id is invalid
- * ESP_ERR_INVALID_STATE if FreeRTOS scheduler is not running
- * ESP_OK otherwise
+ * @return
+ * - ESP_ERR_INVALID_ARG if cpu_id is invalid
+ * - ESP_ERR_INVALID_STATE if the FreeRTOS scheduler is not running
+ * - ESP_OK otherwise
*/
esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
--- /dev/null
+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
+:cpp:func:`esp_ipc_call` or :cpp:func:`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
+:cpp:func:`esp_ipc_call` or :cpp:func:`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
+-----
+
+:cpp:func:`esp_ipc_call` unblocks the IPC task on a particular core to execute
+a given function. The task that calls :cpp:func:`esp_ipc_call` will be blocked
+until the IPC Task begins execution of the given function.
+:cpp:func:`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
+:ref:`CONFIG_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
+-------------
+
+.. include:: /_build/inc/esp_ipc.inc
+
+