1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
31
32
33
34
35
36
37
40
44
45
46
47
48
49
50
51
52
61
62
63
64
65
66
72
73
79
80
81
82
83
84
93
94
95
96
101
102
103
104
105
106
107
108
109
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
143
144
145
150
151
152
153
159
160
165
166
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
200
201
202
/* ... */
#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;
uint32_t volatile esp_ipc_isr_end_fl = 1;
esp_ipc_isr_func_t volatile esp_ipc_func;
void * volatile esp_ipc_func_arg;
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;
/* ... */
typedef enum {
IPC_ISR_WAIT_FOR_START = 0,
IPC_ISR_WAIT_FOR_END = 1,
}{ ... } 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);
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;
}{...}
}{ ... }
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();
}{ ... }
void esp_ipc_isr_waiting_for_finish_cmd(void* finish_cmd);
/* ... */
void IRAM_ATTR esp_ipc_isr_stall_other_cpu(void)
{
#if CONFIG_FREERTOS_SMP
/* ... */
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;
}{...}
#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;
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
/* ... */
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)
{
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();
}{ ... }
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();
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;
esp_ipc_isr_port_int_trigger(!cpu_id);
if (wait_for == IPC_ISR_WAIT_FOR_START) {
while (!esp_ipc_isr_start_fl) {};
}{...} else {
while (!esp_ipc_isr_end_fl) {};
}{...}
}{ ... }