Select one of the symbols to view example projects that use it.
 
Outline
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "esp_err.h"
#include "esp_attr.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/portmacro.h"
#include "esp_private/esp_ipc_isr.h"
#include "esp_private/esp_ipc_isr_port.h"
#include "esp_ipc_isr.h"
#include "sdkconfig.h"
s_ipc_isr_mux
esp_ipc_isr_start_fl
esp_ipc_isr_end_fl
esp_ipc_func
esp_ipc_func_arg
stall_state_t
s_stall_state
s_count_of_nested_calls
s_stored_interrupt_level
esp_ipc_isr_finish_cmd
esp_ipc_isr_wait_t
#define IPC_ISR_ENTER_CRITICAL
#define IPC_ISR_EXIT_CRITICAL
esp_ipc_isr_init()
esp_ipc_isr_call(esp_ipc_isr_func_t, void *)
esp_ipc_isr_call_blocking(esp_ipc_isr_func_t, void *)
esp_ipc_isr_stall_other_cpu()
esp_ipc_isr_release_other_cpu()
esp_ipc_isr_stall_pause()
esp_ipc_isr_stall_abort()
esp_ipc_isr_stall_resume()
esp_ipc_isr_call_and_wait(esp_ipc_isr_func_t, void *, esp_ipc_isr_wait_t)
Files
loading...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/esp_system/port/esp_ipc_isr.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */ #include <stddef.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include "esp_err.h" #include "esp_attr.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/portmacro.h" #include "esp_private/esp_ipc_isr.h" #include "esp_private/esp_ipc_isr_port.h" #include "esp_ipc_isr.h" #include "sdkconfig.h"13 includes static portMUX_TYPE s_ipc_isr_mux = portMUX_INITIALIZER_UNLOCKED; uint32_t volatile esp_ipc_isr_start_fl; // the flag shows that it is about to run esp_ipc_func() uint32_t volatile esp_ipc_isr_end_fl = 1; // the flag shows that esp_ipc_func() is done esp_ipc_isr_func_t volatile esp_ipc_func; // the function which will be run in the ipc_isr context void * volatile esp_ipc_func_arg; // the argument of esp_ipc_func() typedef enum { STALL_STATE_IDLE = 0, STALL_STATE_RUNNING = 1, }{ ... } stall_state_t; static stall_state_t volatile s_stall_state = STALL_STATE_IDLE; static int32_t volatile s_count_of_nested_calls[CONFIG_FREERTOS_NUMBER_OF_CORES] = { 0 }; static BaseType_t s_stored_interrupt_level; static uint32_t volatile esp_ipc_isr_finish_cmd; /** * @brief Type of calling *//* ... */ typedef enum { IPC_ISR_WAIT_FOR_START = 0, /*!< The caller is waiting for the start */ IPC_ISR_WAIT_FOR_END = 1, /*!< The caller is waiting for the end */ }{ ... } esp_ipc_isr_wait_t; #define IPC_ISR_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&s_ipc_isr_mux) #define IPC_ISR_EXIT_CRITICAL() portEXIT_CRITICAL_SAFE(&s_ipc_isr_mux) static void esp_ipc_isr_call_and_wait(esp_ipc_isr_func_t func, void* arg, esp_ipc_isr_wait_t wait_for); /* Initializing IPC_ISR */ void esp_ipc_isr_init(void) { const uint32_t cpuid = xPortGetCoreID(); esp_ipc_isr_port_init(cpuid); if (cpuid != 0) { s_stall_state = STALL_STATE_RUNNING; }{...} }{ ... } /* End initializing IPC_ISR */ /* Public API functions */ void IRAM_ATTR esp_ipc_isr_call(esp_ipc_isr_func_t func, void* arg) { IPC_ISR_ENTER_CRITICAL(); esp_ipc_isr_call_and_wait(func, arg, IPC_ISR_WAIT_FOR_START); IPC_ISR_EXIT_CRITICAL(); }{ ... } void IRAM_ATTR esp_ipc_isr_call_blocking(esp_ipc_isr_func_t func, void* arg) { IPC_ISR_ENTER_CRITICAL(); esp_ipc_isr_call_and_wait(func, arg, IPC_ISR_WAIT_FOR_END); IPC_ISR_EXIT_CRITICAL(); }{ ... } // This asm function is from esp_ipc_isr_routines.S. // It is waiting for the finish_cmd command in a loop. void esp_ipc_isr_waiting_for_finish_cmd(void* finish_cmd); /* * esp_ipc_isr_stall_other_cpu is used for: * - stall other CPU, * - do protection when dual core access DPORT internal register and APB register via DPORT simultaneously. * This function will be initialize after FreeRTOS startup. * When cpu0 wants to access DPORT register, it should notify cpu1 enter in high-priority interrupt for be mute. * When cpu1 already in high-priority interrupt, cpu0 can access DPORT register. * Currently, cpu1 will wait for cpu0 finish access and exit high-priority interrupt. *//* ... */ void IRAM_ATTR esp_ipc_isr_stall_other_cpu(void) { #if CONFIG_FREERTOS_SMP /* Temporary workaround to prevent deadlocking on the SMP FreeRTOS kernel lock after stalling the other CPU. See IDF-5257 *//* ... */ taskENTER_CRITICAL();/* ... */ #endif if (s_stall_state == STALL_STATE_RUNNING) { #if CONFIG_FREERTOS_SMP BaseType_t intLvl = portDISABLE_INTERRUPTS(); #else BaseType_t intLvl = portSET_INTERRUPT_MASK_FROM_ISR(); #endif const uint32_t cpu_id = xPortGetCoreID(); if (s_count_of_nested_calls[cpu_id]++ == 0) { IPC_ISR_ENTER_CRITICAL(); s_stored_interrupt_level = intLvl; esp_ipc_isr_finish_cmd = 0; esp_ipc_isr_call_and_wait(&esp_ipc_isr_waiting_for_finish_cmd, (void*)&esp_ipc_isr_finish_cmd, IPC_ISR_WAIT_FOR_START); return; }{...} /* Interrupts are already disabled by the parent, we're nested here. */ #if CONFIG_FREERTOS_SMP portRESTORE_INTERRUPTS(intLvl); #else portCLEAR_INTERRUPT_MASK_FROM_ISR(intLvl); #endif }{...} }{ ... } void IRAM_ATTR esp_ipc_isr_release_other_cpu(void) { if (s_stall_state == STALL_STATE_RUNNING) { const uint32_t cpu_id = xPortGetCoreID(); if (--s_count_of_nested_calls[cpu_id] == 0) { esp_ipc_isr_finish_cmd = 1; // Make sure end flag is cleared and esp_ipc_isr_waiting_for_finish_cmd is done. while (!esp_ipc_isr_end_fl) {}; IPC_ISR_EXIT_CRITICAL(); #if CONFIG_FREERTOS_SMP portRESTORE_INTERRUPTS(s_stored_interrupt_level); #else portCLEAR_INTERRUPT_MASK_FROM_ISR(s_stored_interrupt_level); #endif }{...} else if (s_count_of_nested_calls[cpu_id] < 0) { assert(0); }{...} }{...} #if CONFIG_FREERTOS_SMP /* Temporary workaround to prevent deadlocking on the SMP FreeRTOS kernel lock after stalling the other CPU. See IDF-5257 *//* ... */ taskEXIT_CRITICAL();/* ... */ #endif }{ ... } void IRAM_ATTR esp_ipc_isr_stall_pause(void) { IPC_ISR_ENTER_CRITICAL(); s_stall_state = STALL_STATE_IDLE; IPC_ISR_EXIT_CRITICAL(); }{ ... } 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; }{ ... } void IRAM_ATTR esp_ipc_isr_stall_resume(void) { IPC_ISR_ENTER_CRITICAL(); s_stall_state = STALL_STATE_RUNNING; IPC_ISR_EXIT_CRITICAL(); }{ ... } /* End public API functions */ /* Private functions*/ static void IRAM_ATTR esp_ipc_isr_call_and_wait(esp_ipc_isr_func_t func, void* arg, esp_ipc_isr_wait_t wait_for) { const uint32_t cpu_id = xPortGetCoreID(); // waiting for the end of the previous call while (!esp_ipc_isr_end_fl) {}; esp_ipc_func = func; esp_ipc_func_arg = arg; esp_ipc_isr_start_fl = 0; esp_ipc_isr_end_fl = 0; // Trigger an interrupt on the opposite core. esp_ipc_isr_port_int_trigger(!cpu_id); // IPC_ISR handler will be called and `...isr_start` and `...isr_end` will be updated there if (wait_for == IPC_ISR_WAIT_FOR_START) { while (!esp_ipc_isr_start_fl) {}; }{...} else { // IPC_ISR_WAIT_FOR_END while (!esp_ipc_isr_end_fl) {}; }{...} }{ ... } /* End private functions*/
Details