diff --git a/components/esp32/include/esp_ipc.h b/components/esp32/include/esp_ipc.h index 28b17a9a3..b229cb337 100644 --- a/components/esp32/include/esp_ipc.h +++ b/components/esp32/include/esp_ipc.h @@ -20,11 +20,11 @@ #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. @@ -34,8 +34,9 @@ typedef void (*esp_ipc_func_t)(void* arg); */ -/** - * @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 @@ -43,51 +44,59 @@ typedef void (*esp_ipc_func_t)(void* arg); * 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 + * @brief Execute a 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. + * 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. * - * 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. * - * 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. + * @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 * - * @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 - * - * @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); diff --git a/docs/Doxyfile b/docs/Doxyfile index 7b5e1d4d5..e2dc5eab8 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -128,6 +128,8 @@ INPUT = \ ../components/esp32/include/esp_task_wdt.h \ ## Hooks ../components/esp32/include/esp_freertos_hooks.h \ + ## Inter-Processor Call + ../components/esp32/include/esp_ipc.h \ ## Over The Air Updates (OTA) ../components/app_update/include/esp_ota_ops.h \ ## Sleep diff --git a/docs/api-reference/system/index.rst b/docs/api-reference/system/index.rst index a4c348170..b4e92050d 100644 --- a/docs/api-reference/system/index.rst +++ b/docs/api-reference/system/index.rst @@ -9,6 +9,7 @@ System API Interrupt Allocation Watchdogs Hooks + Inter-Processor Call Over The Air Updates (OTA) Sleep Modes Power Management diff --git a/docs/api-reference/system/ipc.rst b/docs/api-reference/system/ipc.rst new file mode 100644 index 000000000..37d416145 --- /dev/null +++ b/docs/api-reference/system/ipc.rst @@ -0,0 +1,43 @@ +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 + +