1#![no_std]
9#![no_main]
10#![feature(custom_test_frameworks)]
11#![test_runner(test_runner)]
12#![reexport_test_harness_main = "test_main"]
13
14use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
15use esp32_c3::chip::Esp32C3DefaultPeripherals;
16use kernel::capabilities;
17use kernel::component::Component;
18use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
19use kernel::platform::{KernelResources, SyscallDriverLookup};
20use kernel::process::ProcessArray;
21use kernel::scheduler::priority::PrioritySched;
22use kernel::utilities::registers::interfaces::ReadWriteable;
23use kernel::{create_capability, debug, hil, static_init};
24use rv32i::csr;
25
26pub mod io;
27
28#[cfg(test)]
29mod tests;
30
31const NUM_PROCS: usize = 4;
32
33static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
35static mut CHIP: Option<&'static esp32_c3::chip::Esp32C3<Esp32C3DefaultPeripherals>> = None;
37static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
39 None;
40
41const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
43 capsules_system::process_policies::PanicFaultPolicy {};
44
45#[cfg(test)]
47static mut PERIPHERALS: Option<&'static Esp32C3DefaultPeripherals> = None;
48#[cfg(test)]
50static mut SCHEDULER: Option<&PrioritySched> = None;
51#[cfg(test)]
53static mut BOARD: Option<&'static kernel::Kernel> = None;
54#[cfg(test)]
56static mut PLATFORM: Option<&'static Esp32C3Board> = None;
57#[cfg(test)]
59static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
60static mut ALARM: Option<&'static MuxAlarm<'static, esp32_c3::timg::TimG<'static>>> = None;
62
63kernel::stack_size! {0x900}
64
65type RngDriver = components::rng::RngComponentType<esp32_c3::rng::Rng<'static>>;
66
67struct Esp32C3Board {
70 gpio: &'static capsules_core::gpio::GPIO<'static, esp32::gpio::GpioPin<'static>>,
71 console: &'static capsules_core::console::Console<'static>,
72 alarm: &'static capsules_core::alarm::AlarmDriver<
73 'static,
74 VirtualMuxAlarm<'static, esp32_c3::timg::TimG<'static>>,
75 >,
76 scheduler: &'static PrioritySched,
77 scheduler_timer: &'static VirtualSchedulerTimer<esp32_c3::timg::TimG<'static>>,
78 rng: &'static RngDriver,
79}
80
81impl SyscallDriverLookup for Esp32C3Board {
83 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
84 where
85 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
86 {
87 match driver_num {
88 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
89 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
90 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
91 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
92 _ => f(None),
93 }
94 }
95}
96
97impl KernelResources<esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>>
98 for Esp32C3Board
99{
100 type SyscallDriverLookup = Self;
101 type SyscallFilter = ();
102 type ProcessFault = ();
103 type ContextSwitchCallback = ();
104 type Scheduler = PrioritySched;
105 type SchedulerTimer = VirtualSchedulerTimer<esp32_c3::timg::TimG<'static>>;
106 type WatchDog = ();
107
108 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
109 self
110 }
111 fn syscall_filter(&self) -> &Self::SyscallFilter {
112 &()
113 }
114 fn process_fault(&self) -> &Self::ProcessFault {
115 &()
116 }
117 fn scheduler(&self) -> &Self::Scheduler {
118 self.scheduler
119 }
120 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
121 self.scheduler_timer
122 }
123 fn watchdog(&self) -> &Self::WatchDog {
124 &()
125 }
126 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
127 &()
128 }
129}
130
131unsafe fn setup() -> (
132 &'static kernel::Kernel,
133 &'static Esp32C3Board,
134 &'static esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>,
135 &'static Esp32C3DefaultPeripherals<'static>,
136) {
137 use esp32_c3::sysreg::{CpuFrequency, PllFrequency};
138
139 rv32i::configure_trap_handler();
141
142 let peripherals = static_init!(Esp32C3DefaultPeripherals, Esp32C3DefaultPeripherals::new());
143
144 peripherals.timg0.disable_wdt();
145 peripherals.rtc_cntl.disable_wdt();
146 peripherals.rtc_cntl.disable_super_wdt();
147 peripherals.rtc_cntl.enable_fosc();
148 peripherals.sysreg.disable_timg0();
149 peripherals.sysreg.enable_timg0();
150
151 peripherals
152 .sysreg
153 .use_pll_clock_source(PllFrequency::MHz320, CpuFrequency::MHz160);
154
155 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
157 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
158
159 let processes = components::process_array::ProcessArrayComponent::new()
161 .finalize(components::process_array_component_static!(NUM_PROCS));
162 PROCESSES = Some(processes);
163
164 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
166
167 kernel::debug::assign_gpios(None, None, None);
169
170 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
172 .finalize(components::uart_mux_component_static!());
173
174 let gpio = components::gpio::GpioComponent::new(
175 board_kernel,
176 capsules_core::gpio::DRIVER_NUM,
177 components::gpio_component_helper!(
178 esp32::gpio::GpioPin,
179 0 => &peripherals.gpio[0],
180 1 => &peripherals.gpio[1],
181 2 => &peripherals.gpio[2],
182 3 => &peripherals.gpio[3],
183 4 => &peripherals.gpio[4],
184 5 => &peripherals.gpio[5],
185 6 => &peripherals.gpio[6],
186 7 => &peripherals.gpio[7],
187 8 => &peripherals.gpio[15]
188 ),
189 )
190 .finalize(components::gpio_component_static!(esp32::gpio::GpioPin));
191
192 let mux_alarm = static_init!(
195 MuxAlarm<'static, esp32_c3::timg::TimG>,
196 MuxAlarm::new(&peripherals.timg0)
197 );
198 hil::time::Alarm::set_alarm_client(&peripherals.timg0, mux_alarm);
199
200 ALARM = Some(mux_alarm);
201
202 let virtual_alarm_user = static_init!(
204 VirtualMuxAlarm<'static, esp32_c3::timg::TimG>,
205 VirtualMuxAlarm::new(mux_alarm)
206 );
207 virtual_alarm_user.setup();
208
209 let alarm = static_init!(
210 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, esp32_c3::timg::TimG>>,
211 capsules_core::alarm::AlarmDriver::new(
212 virtual_alarm_user,
213 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
214 )
215 );
216 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
217
218 let scheduler_timer = static_init!(
219 VirtualSchedulerTimer<esp32_c3::timg::TimG<'static>>,
220 VirtualSchedulerTimer::new(&peripherals.timg1)
221 );
222
223 let chip = static_init!(
224 esp32_c3::chip::Esp32C3<
225 Esp32C3DefaultPeripherals,
226 >,
227 esp32_c3::chip::Esp32C3::new(peripherals)
228 );
229 CHIP = Some(chip);
230
231 chip.map_pic_interrupts();
233 chip.enable_pic_interrupts();
234
235 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
237
238 let console = components::console::ConsoleComponent::new(
240 board_kernel,
241 capsules_core::console::DRIVER_NUM,
242 uart_mux,
243 )
244 .finalize(components::console_component_static!());
245 components::debug_writer::DebugWriterComponent::new(
247 uart_mux,
248 create_capability!(capabilities::SetDebugWriterCapability),
249 )
250 .finalize(components::debug_writer_component_static!());
251
252 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
254 .finalize(components::process_printer_text_component_static!());
255 PROCESS_PRINTER = Some(process_printer);
256
257 debug!("ESP32-C3 initialisation complete.");
258 debug!("Entering main loop.");
259
260 extern "C" {
262 static _sapps: u8;
264 static _eapps: u8;
266 static mut _sappmem: u8;
268 static _eappmem: u8;
270 }
271
272 let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
273 .finalize(components::priority_component_static!());
274
275 let process_console = components::process_console::ProcessConsoleComponent::new(
277 board_kernel,
278 uart_mux,
279 mux_alarm,
280 process_printer,
281 None,
282 )
283 .finalize(components::process_console_component_static!(
284 esp32_c3::timg::TimG
285 ));
286 let _ = process_console.start();
287
288 let rng = components::rng::RngComponent::new(
289 board_kernel,
290 capsules_core::rng::DRIVER_NUM,
291 &peripherals.rng,
292 )
293 .finalize(components::rng_component_static!(esp32_c3::rng::Rng));
294
295 let esp32_c3_board = static_init!(
296 Esp32C3Board,
297 Esp32C3Board {
298 gpio,
299 console,
300 alarm,
301 scheduler,
302 scheduler_timer,
303 rng,
304 }
305 );
306
307 kernel::process::load_processes(
308 board_kernel,
309 chip,
310 core::slice::from_raw_parts(
311 core::ptr::addr_of!(_sapps),
312 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
313 ),
314 core::slice::from_raw_parts_mut(
315 core::ptr::addr_of_mut!(_sappmem),
316 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
317 ),
318 &FAULT_RESPONSE,
319 &process_mgmt_cap,
320 )
321 .unwrap_or_else(|err| {
322 debug!("Error loading processes!");
323 debug!("{:?}", err);
324 });
325
326 peripherals.init();
327
328 (board_kernel, esp32_c3_board, chip, peripherals)
329}
330
331#[no_mangle]
336pub unsafe fn main() {
337 #[cfg(test)]
338 test_main();
339
340 #[cfg(not(test))]
341 {
342 let (board_kernel, esp32_c3_board, chip, _peripherals) = setup();
343
344 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
345
346 board_kernel.kernel_loop(
347 esp32_c3_board,
348 chip,
349 None::<&kernel::ipc::IPC<0>>,
350 &main_loop_cap,
351 );
352 }
353}
354
355#[cfg(test)]
356use kernel::platform::watchdog::WatchDog;
357
358#[cfg(test)]
359fn test_runner(tests: &[&dyn Fn()]) {
360 unsafe {
361 let (board_kernel, esp32_c3_board, _chip, peripherals) = setup();
362
363 BOARD = Some(board_kernel);
364 PLATFORM = Some(&esp32_c3_board);
365 PERIPHERALS = Some(peripherals);
366 SCHEDULER = Some(
367 components::sched::priority::PriorityComponent::new(board_kernel)
368 .finalize(components::priority_component_static!()),
369 );
370 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
371
372 PLATFORM.map(|p| {
373 p.watchdog().setup();
374 });
375
376 for test in tests {
377 test();
378 }
379 }
380
381 loop {}
382}