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::{KernelResources, SyscallDriverLookup};
19use kernel::process::ProcessArray;
20use kernel::scheduler::priority::PrioritySched;
21use kernel::utilities::registers::interfaces::ReadWriteable;
22use kernel::{create_capability, debug, hil, static_init};
23use rv32i::csr;
24
25pub mod io;
26
27#[cfg(test)]
28mod tests;
29
30const NUM_PROCS: usize = 4;
31
32type ChipHw = esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>;
33type AlarmHw = esp32_c3::timg::TimG<'static>;
34type SchedulerTimerHw =
35 components::virtual_scheduler_timer::VirtualSchedulerTimerNoMuxComponentType<AlarmHw>;
36
37static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
39static mut CHIP: Option<&'static esp32_c3::chip::Esp32C3<Esp32C3DefaultPeripherals>> = None;
41static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
43 None;
44
45const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
47 capsules_system::process_policies::PanicFaultPolicy {};
48
49#[cfg(test)]
51static mut PERIPHERALS: Option<&'static Esp32C3DefaultPeripherals> = None;
52#[cfg(test)]
54static mut SCHEDULER: Option<&PrioritySched> = None;
55#[cfg(test)]
57static mut BOARD: Option<&'static kernel::Kernel> = None;
58#[cfg(test)]
60static mut PLATFORM: Option<&'static Esp32C3Board> = None;
61#[cfg(test)]
63static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
64static mut ALARM: Option<&'static MuxAlarm<'static, esp32_c3::timg::TimG<'static>>> = None;
66
67kernel::stack_size! {0x900}
68
69type RngDriver = components::rng::RngComponentType<esp32_c3::rng::Rng<'static>>;
70type GpioHw = esp32::gpio::GpioPin<'static>;
71type LedHw = components::sk68xx::Sk68xxLedComponentType<GpioHw, 3>;
72type LedDriver = components::led::LedsComponentType<LedHw, 3>;
73type ButtonDriver = components::button::ButtonComponentType<GpioHw>;
74
75struct Esp32C3Board {
78 gpio: &'static capsules_core::gpio::GPIO<'static, esp32::gpio::GpioPin<'static>>,
79 console: &'static capsules_core::console::Console<'static>,
80 alarm: &'static capsules_core::alarm::AlarmDriver<
81 'static,
82 VirtualMuxAlarm<'static, esp32_c3::timg::TimG<'static>>,
83 >,
84 scheduler: &'static PrioritySched,
85 scheduler_timer: &'static SchedulerTimerHw,
86 rng: &'static RngDriver,
87 led: &'static LedDriver,
88 button: &'static ButtonDriver,
89}
90
91impl SyscallDriverLookup for Esp32C3Board {
93 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
94 where
95 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
96 {
97 match driver_num {
98 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
99 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
100 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
101 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
102 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
103 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
104 _ => f(None),
105 }
106 }
107}
108
109impl KernelResources<esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>>
110 for Esp32C3Board
111{
112 type SyscallDriverLookup = Self;
113 type SyscallFilter = ();
114 type ProcessFault = ();
115 type ContextSwitchCallback = ();
116 type Scheduler = PrioritySched;
117 type SchedulerTimer = SchedulerTimerHw;
118 type WatchDog = ();
119
120 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
121 self
122 }
123 fn syscall_filter(&self) -> &Self::SyscallFilter {
124 &()
125 }
126 fn process_fault(&self) -> &Self::ProcessFault {
127 &()
128 }
129 fn scheduler(&self) -> &Self::Scheduler {
130 self.scheduler
131 }
132 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
133 self.scheduler_timer
134 }
135 fn watchdog(&self) -> &Self::WatchDog {
136 &()
137 }
138 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
139 &()
140 }
141}
142
143unsafe fn setup() -> (
144 &'static kernel::Kernel,
145 &'static Esp32C3Board,
146 &'static esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>,
147 &'static Esp32C3DefaultPeripherals<'static>,
148) {
149 use esp32_c3::sysreg::{CpuFrequency, PllFrequency};
150
151 esp32_c3::chip::configure_trap_handler();
153
154 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
156 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
157 >();
158
159 let peripherals = static_init!(Esp32C3DefaultPeripherals, Esp32C3DefaultPeripherals::new());
164
165 peripherals.timg0.disable_wdt();
166 peripherals.rtc_cntl.disable_wdt();
167 peripherals.rtc_cntl.disable_super_wdt();
168 peripherals.rtc_cntl.enable_fosc();
169 peripherals.sysreg.disable_timg0();
170 peripherals.sysreg.enable_timg0();
171
172 peripherals
173 .sysreg
174 .use_pll_clock_source(PllFrequency::MHz320, CpuFrequency::MHz160);
175
176 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
178 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
179
180 let processes = components::process_array::ProcessArrayComponent::new()
186 .finalize(components::process_array_component_static!(NUM_PROCS));
187 PROCESSES = Some(processes);
188
189 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
191
192 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
198 .finalize(components::uart_mux_component_static!());
199
200 let console = components::console::ConsoleComponent::new(
202 board_kernel,
203 capsules_core::console::DRIVER_NUM,
204 uart_mux,
205 )
206 .finalize(components::console_component_static!());
207 components::debug_writer::DebugWriterComponent::new_unsafe(
209 uart_mux,
210 create_capability!(capabilities::SetDebugWriterCapability),
211 || unsafe {
212 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
213 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
214 >();
215 },
216 )
217 .finalize(components::debug_writer_component_static!());
218
219 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
221 .finalize(components::process_printer_text_component_static!());
222 PROCESS_PRINTER = Some(process_printer);
223
224 let gpio = components::gpio::GpioComponent::new(
229 board_kernel,
230 capsules_core::gpio::DRIVER_NUM,
231 components::gpio_component_helper!(
232 esp32::gpio::GpioPin,
233 0 => &peripherals.gpio[0],
234 1 => &peripherals.gpio[1],
235 2 => &peripherals.gpio[2],
236 3 => &peripherals.gpio[3],
237 4 => &peripherals.gpio[4],
238 5 => &peripherals.gpio[5],
239 6 => &peripherals.gpio[6],
240 7 => &peripherals.gpio[7],
241 8 => &peripherals.gpio[15]
242 ),
243 )
244 .finalize(components::gpio_component_static!(esp32::gpio::GpioPin));
245
246 let mux_alarm = static_init!(
253 MuxAlarm<'static, esp32_c3::timg::TimG>,
254 MuxAlarm::new(&peripherals.timg0)
255 );
256 hil::time::Alarm::set_alarm_client(&peripherals.timg0, mux_alarm);
257
258 ALARM = Some(mux_alarm);
259
260 let virtual_alarm_user = static_init!(
262 VirtualMuxAlarm<'static, esp32_c3::timg::TimG>,
263 VirtualMuxAlarm::new(mux_alarm)
264 );
265 virtual_alarm_user.setup();
266
267 let alarm = static_init!(
268 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, esp32_c3::timg::TimG>>,
269 capsules_core::alarm::AlarmDriver::new(
270 virtual_alarm_user,
271 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
272 )
273 );
274 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
275
276 let led_gpio = &peripherals.gpio[8];
281 let sk68xx = components::sk68xx::Sk68xxComponent::new(led_gpio, rv32i::support::nop)
282 .finalize(components::sk68xx_component_static_esp32c3_160mhz!(GpioHw,));
283
284 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
285 LedHw,
286 capsules_extra::sk68xx::Sk68xxLed::new(sk68xx, 0), capsules_extra::sk68xx::Sk68xxLed::new(sk68xx, 1), capsules_extra::sk68xx::Sk68xxLed::new(sk68xx, 2), ));
290
291 let button_boot_gpio = &peripherals.gpio[9];
296 let button = components::button::ButtonComponent::new(
297 board_kernel,
298 capsules_core::button::DRIVER_NUM,
299 components::button_component_helper!(
300 GpioHw,
301 (
302 button_boot_gpio,
303 kernel::hil::gpio::ActivationMode::ActiveLow,
304 kernel::hil::gpio::FloatingState::PullUp
305 )
306 ),
307 )
308 .finalize(components::button_component_static!(GpioHw));
309
310 let scheduler_timer_alarm = &peripherals.timg1;
315 let scheduler_timer =
316 components::virtual_scheduler_timer::VirtualSchedulerTimerNoMuxComponent::new(
317 scheduler_timer_alarm,
318 )
319 .finalize(components::virtual_scheduler_timer_no_mux_component_static!(AlarmHw));
320
321 let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
322 .finalize(components::priority_component_static!());
323
324 let process_console = components::process_console::ProcessConsoleComponent::new(
329 board_kernel,
330 uart_mux,
331 mux_alarm,
332 process_printer,
333 None,
334 )
335 .finalize(components::process_console_component_static!(
336 esp32_c3::timg::TimG
337 ));
338 let _ = process_console.start();
339
340 let rng = components::rng::RngComponent::new(
345 board_kernel,
346 capsules_core::rng::DRIVER_NUM,
347 &peripherals.rng,
348 )
349 .finalize(components::rng_component_static!(esp32_c3::rng::Rng));
350
351 let chip = static_init!(
356 esp32_c3::chip::Esp32C3<
357 Esp32C3DefaultPeripherals,
358 >,
359 esp32_c3::chip::Esp32C3::new(peripherals)
360 );
361 CHIP = Some(chip);
362
363 chip.map_pic_interrupts();
365 chip.enable_pic_interrupts();
366
367 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
369
370 debug!("ESP32-C3 initialisation complete.");
371 debug!("Entering main loop.");
372
373 extern "C" {
379 static _sapps: u8;
381 static _eapps: u8;
383 static mut _sappmem: u8;
385 static _eappmem: u8;
387 }
388
389 let esp32_c3_board = static_init!(
390 Esp32C3Board,
391 Esp32C3Board {
392 gpio,
393 console,
394 alarm,
395 scheduler,
396 scheduler_timer,
397 rng,
398 led,
399 button
400 }
401 );
402
403 kernel::process::load_processes(
404 board_kernel,
405 chip,
406 core::slice::from_raw_parts(
407 core::ptr::addr_of!(_sapps),
408 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
409 ),
410 core::slice::from_raw_parts_mut(
411 core::ptr::addr_of_mut!(_sappmem),
412 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
413 ),
414 &FAULT_RESPONSE,
415 &process_mgmt_cap,
416 )
417 .unwrap_or_else(|err| {
418 debug!("Error loading processes!");
419 debug!("{:?}", err);
420 });
421
422 peripherals.init();
423
424 (board_kernel, esp32_c3_board, chip, peripherals)
425}
426
427#[no_mangle]
432pub unsafe fn main() {
433 #[cfg(test)]
434 test_main();
435
436 #[cfg(not(test))]
437 {
438 let (board_kernel, esp32_c3_board, chip, _peripherals) = setup();
439
440 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
441
442 board_kernel.kernel_loop(
443 esp32_c3_board,
444 chip,
445 None::<&kernel::ipc::IPC<0>>,
446 &main_loop_cap,
447 );
448 }
449}
450
451#[cfg(test)]
452use kernel::platform::watchdog::WatchDog;
453
454#[cfg(test)]
455fn test_runner(tests: &[&dyn Fn()]) {
456 unsafe {
457 let (board_kernel, esp32_c3_board, _chip, peripherals) = setup();
458
459 BOARD = Some(board_kernel);
460 PLATFORM = Some(&esp32_c3_board);
461 PERIPHERALS = Some(peripherals);
462 SCHEDULER = Some(
463 components::sched::priority::PriorityComponent::new(board_kernel)
464 .finalize(components::priority_component_static!()),
465 );
466 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
467
468 PLATFORM.map(|p| {
469 p.watchdog().setup();
470 });
471
472 for test in tests {
473 test();
474 }
475 }
476
477 loop {}
478}