esp_hal/soc/esp32/
cpu_control.rs1use core::sync::atomic::Ordering;
10
11use crate::{
12 peripherals::{DPORT, LPWR, SPI0},
13 system::{Cpu, multi_core::*},
14};
15
16pub(crate) unsafe fn internal_park_core(core: Cpu, park: bool) {
17 let c1_value = if park { 0x21 } else { 0 };
18 let c0_value = if park { 0x02 } else { 0 };
19 match core {
20 Cpu::ProCpu => {
21 LPWR::regs()
22 .sw_cpu_stall()
23 .modify(|_, w| unsafe { w.sw_stall_procpu_c1().bits(c1_value) });
24 LPWR::regs()
25 .options0()
26 .modify(|_, w| unsafe { w.sw_stall_procpu_c0().bits(c0_value) });
27 }
28 Cpu::AppCpu => {
29 LPWR::regs()
30 .sw_cpu_stall()
31 .modify(|_, w| unsafe { w.sw_stall_appcpu_c1().bits(c1_value) });
32 LPWR::regs()
33 .options0()
34 .modify(|_, w| unsafe { w.sw_stall_appcpu_c0().bits(c0_value) });
35 }
36 }
37}
38
39#[instability::unstable]
41pub fn is_running(core: Cpu) -> bool {
42 if core == Cpu::AppCpu {
43 let dport = DPORT::regs();
44 if dport
47 .appcpu_ctrl_b()
48 .read()
49 .appcpu_clkgate_en()
50 .bit_is_clear()
51 || dport.appcpu_ctrl_c().read().appcpu_runstall().bit_is_set()
52 {
53 return false;
55 }
56 }
57
58 let is_stalled = match core {
61 Cpu::ProCpu => {
62 let c1 = LPWR::regs()
63 .sw_cpu_stall()
64 .read()
65 .sw_stall_procpu_c1()
66 .bits();
67 let c0 = LPWR::regs().options0().read().sw_stall_procpu_c0().bits();
68 (c1 << 2) | c0
69 }
70 Cpu::AppCpu => {
71 let c1 = LPWR::regs()
72 .sw_cpu_stall()
73 .read()
74 .sw_stall_appcpu_c1()
75 .bits();
76 let c0 = LPWR::regs().options0().read().sw_stall_appcpu_c0().bits();
77 (c1 << 2) | c0
78 }
79 };
80
81 is_stalled != 0x86
82}
83
84fn flush_cache(core: Cpu) {
85 let dport_control = DPORT::regs();
86
87 match core {
88 Cpu::ProCpu => {
89 dport_control
90 .pro_cache_ctrl()
91 .modify(|_, w| w.pro_cache_flush_ena().clear_bit());
92 dport_control
93 .pro_cache_ctrl()
94 .modify(|_, w| w.pro_cache_flush_ena().set_bit());
95 while dport_control
96 .pro_cache_ctrl()
97 .read()
98 .pro_cache_flush_done()
99 .bit_is_clear()
100 {}
101
102 dport_control
103 .pro_cache_ctrl()
104 .modify(|_, w| w.pro_cache_flush_ena().clear_bit());
105 }
106 Cpu::AppCpu => {
107 dport_control
108 .app_cache_ctrl()
109 .modify(|_, w| w.app_cache_flush_ena().clear_bit());
110 dport_control
111 .app_cache_ctrl()
112 .modify(|_, w| w.app_cache_flush_ena().set_bit());
113 while dport_control
114 .app_cache_ctrl()
115 .read()
116 .app_cache_flush_done()
117 .bit_is_clear()
118 {}
119 dport_control
120 .app_cache_ctrl()
121 .modify(|_, w| w.app_cache_flush_ena().clear_bit());
122 }
123 };
124}
125
126fn enable_cache(core: Cpu) {
127 let spi0 = SPI0::regs();
128 let dport_control = DPORT::regs();
129
130 match core {
131 Cpu::ProCpu => {
132 spi0.cache_fctrl().modify(|_, w| w.cache_req_en().set_bit());
133 dport_control
134 .pro_cache_ctrl()
135 .modify(|_, w| w.pro_cache_enable().set_bit());
136 }
137 Cpu::AppCpu => {
138 spi0.cache_fctrl().modify(|_, w| w.cache_req_en().set_bit());
139 dport_control
140 .app_cache_ctrl()
141 .modify(|_, w| w.app_cache_enable().set_bit());
142 }
143 };
144}
145
146pub(crate) fn start_core1(entry_point: *const u32) {
147 let dport_control = DPORT::regs();
148
149 flush_cache(Cpu::AppCpu);
150 enable_cache(Cpu::AppCpu);
151
152 dport_control
153 .appcpu_ctrl_d()
154 .write(|w| unsafe { w.appcpu_boot_addr().bits(entry_point as u32) });
155
156 dport_control
157 .appcpu_ctrl_b()
158 .modify(|_, w| w.appcpu_clkgate_en().set_bit());
159 dport_control
160 .appcpu_ctrl_c()
161 .modify(|_, w| w.appcpu_runstall().clear_bit());
162 dport_control
163 .appcpu_ctrl_a()
164 .modify(|_, w| w.appcpu_resetting().set_bit());
165 dport_control
166 .appcpu_ctrl_a()
167 .modify(|_, w| w.appcpu_resetting().clear_bit());
168}
169
170pub(crate) fn start_core1_init<F>() -> !
171where
172 F: FnOnce(),
173{
174 unsafe {
176 xtensa_lx::interrupt::set_mask(0);
177 }
178
179 xtensa_lx::timer::set_ccompare0(0);
181 xtensa_lx::timer::set_ccompare1(0);
182 xtensa_lx::timer::set_ccompare2(0);
183
184 unsafe extern "C" {
185 static mut _init_start: u32;
186 }
187
188 unsafe {
190 xtensa_lx::set_vecbase(&raw const _init_start);
191 xtensa_lx::set_stack_pointer(APP_CORE_STACK_TOP.load(Ordering::Acquire));
192
193 #[cfg(all(feature = "rt", stack_guard_monitoring))]
194 {
195 let stack_guard = APP_CORE_STACK_GUARD.load(Ordering::Acquire);
196 stack_guard.write_volatile(esp_config::esp_config_int!(
197 u32,
198 "ESP_HAL_CONFIG_STACK_GUARD_VALUE"
199 ));
200 crate::debugger::set_stack_watchpoint(stack_guard as usize);
202 }
203 }
204
205 unsafe { crate::interrupt::init_vectoring() };
207
208 unsafe { CpuControl::start_core1_run::<F>() }
213}