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::debug::PanicResources;
19use kernel::platform::{KernelResources, SyscallDriverLookup};
20use kernel::scheduler::priority::PrioritySched;
21use kernel::utilities::registers::interfaces::ReadWriteable;
22use kernel::utilities::single_thread_value::SingleThreadValue;
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
33type ChipHw = esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>;
34type AlarmHw = esp32_c3::timg::TimG<'static>;
35type SchedulerTimerHw =
36 components::virtual_scheduler_timer::VirtualSchedulerTimerNoMuxComponentType<AlarmHw>;
37type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
38
39static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
41 SingleThreadValue::new(PanicResources::new());
42
43const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
45 capsules_system::process_policies::PanicFaultPolicy {};
46
47#[cfg(test)]
49static mut PERIPHERALS: Option<&'static Esp32C3DefaultPeripherals> = None;
50#[cfg(test)]
52static mut SCHEDULER: Option<&PrioritySched> = None;
53#[cfg(test)]
55static mut BOARD: Option<&'static kernel::Kernel> = None;
56#[cfg(test)]
58static mut PLATFORM: Option<&'static Esp32C3Board> = None;
59#[cfg(test)]
61static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
62static mut ALARM: Option<&'static MuxAlarm<'static, esp32_c3::timg::TimG<'static>>> = None;
64
65kernel::stack_size! {0x900}
66
67type RngDriver = components::rng::RngComponentType<esp32_c3::rng::Rng<'static>>;
68type GpioHw = esp32::gpio::GpioPin<'static>;
69type LedHw = components::sk68xx::Sk68xxLedComponentType<GpioHw, 3>;
70type LedDriver = components::led::LedsComponentType<LedHw, 3>;
71type ButtonDriver = components::button::ButtonComponentType<GpioHw>;
72
73struct Esp32C3Board {
76 gpio: &'static capsules_core::gpio::GPIO<'static, esp32::gpio::GpioPin<'static>>,
77 console: &'static capsules_core::console::Console<'static>,
78 alarm: &'static capsules_core::alarm::AlarmDriver<
79 'static,
80 VirtualMuxAlarm<'static, esp32_c3::timg::TimG<'static>>,
81 >,
82 scheduler: &'static PrioritySched,
83 scheduler_timer: &'static SchedulerTimerHw,
84 rng: &'static RngDriver,
85 led: &'static LedDriver,
86 button: &'static ButtonDriver,
87}
88
89impl SyscallDriverLookup for Esp32C3Board {
91 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
92 where
93 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
94 {
95 match driver_num {
96 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
97 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
98 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
99 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
100 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
101 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
102 _ => f(None),
103 }
104 }
105}
106
107impl KernelResources<esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>>
108 for Esp32C3Board
109{
110 type SyscallDriverLookup = Self;
111 type SyscallFilter = ();
112 type ProcessFault = ();
113 type ContextSwitchCallback = ();
114 type Scheduler = PrioritySched;
115 type SchedulerTimer = SchedulerTimerHw;
116 type WatchDog = ();
117
118 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
119 self
120 }
121 fn syscall_filter(&self) -> &Self::SyscallFilter {
122 &()
123 }
124 fn process_fault(&self) -> &Self::ProcessFault {
125 &()
126 }
127 fn scheduler(&self) -> &Self::Scheduler {
128 self.scheduler
129 }
130 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
131 self.scheduler_timer
132 }
133 fn watchdog(&self) -> &Self::WatchDog {
134 &()
135 }
136 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
137 &()
138 }
139}
140
141unsafe fn setup() -> (
142 &'static kernel::Kernel,
143 &'static Esp32C3Board,
144 &'static esp32_c3::chip::Esp32C3<'static, Esp32C3DefaultPeripherals<'static>>,
145 &'static Esp32C3DefaultPeripherals<'static>,
146) {
147 use esp32_c3::sysreg::{CpuFrequency, PllFrequency};
148
149 esp32_c3::chip::configure_trap_handler();
151
152 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
154 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
155 >();
156
157 PANIC_RESOURCES
159 .bind_to_thread_unsafe::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
160
161 let peripherals = static_init!(Esp32C3DefaultPeripherals, Esp32C3DefaultPeripherals::new());
166
167 peripherals.timg0.disable_wdt();
168 peripherals.rtc_cntl.disable_wdt();
169 peripherals.rtc_cntl.disable_super_wdt();
170 peripherals.rtc_cntl.enable_fosc();
171 peripherals.sysreg.disable_timg0();
172 peripherals.sysreg.enable_timg0();
173
174 peripherals
175 .sysreg
176 .use_pll_clock_source(PllFrequency::MHz320, CpuFrequency::MHz160);
177
178 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
180 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
181
182 let processes = components::process_array::ProcessArrayComponent::new()
188 .finalize(components::process_array_component_static!(NUM_PROCS));
189 PANIC_RESOURCES.get().map(|resources| {
190 resources.processes.put(processes.as_slice());
191 });
192
193 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
195
196 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
202 .finalize(components::uart_mux_component_static!());
203
204 let console = components::console::ConsoleComponent::new(
206 board_kernel,
207 capsules_core::console::DRIVER_NUM,
208 uart_mux,
209 )
210 .finalize(components::console_component_static!());
211 components::debug_writer::DebugWriterComponent::new_unsafe(
213 uart_mux,
214 create_capability!(capabilities::SetDebugWriterCapability),
215 || unsafe {
216 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
217 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
218 >();
219 },
220 )
221 .finalize(components::debug_writer_component_static!());
222
223 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
225 .finalize(components::process_printer_text_component_static!());
226 PANIC_RESOURCES.get().map(|resources| {
227 resources.printer.put(process_printer);
228 });
229
230 let gpio = components::gpio::GpioComponent::new(
235 board_kernel,
236 capsules_core::gpio::DRIVER_NUM,
237 components::gpio_component_helper!(
238 esp32::gpio::GpioPin,
239 0 => &peripherals.gpio[0],
240 1 => &peripherals.gpio[1],
241 2 => &peripherals.gpio[2],
242 3 => &peripherals.gpio[3],
243 4 => &peripherals.gpio[4],
244 5 => &peripherals.gpio[5],
245 6 => &peripherals.gpio[6],
246 7 => &peripherals.gpio[7],
247 8 => &peripherals.gpio[15]
248 ),
249 )
250 .finalize(components::gpio_component_static!(esp32::gpio::GpioPin));
251
252 let mux_alarm = static_init!(
259 MuxAlarm<'static, esp32_c3::timg::TimG>,
260 MuxAlarm::new(&peripherals.timg0)
261 );
262 hil::time::Alarm::set_alarm_client(&peripherals.timg0, mux_alarm);
263
264 ALARM = Some(mux_alarm);
265
266 let virtual_alarm_user = static_init!(
268 VirtualMuxAlarm<'static, esp32_c3::timg::TimG>,
269 VirtualMuxAlarm::new(mux_alarm)
270 );
271 virtual_alarm_user.setup();
272
273 let alarm = static_init!(
274 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, esp32_c3::timg::TimG>>,
275 capsules_core::alarm::AlarmDriver::new(
276 virtual_alarm_user,
277 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
278 )
279 );
280 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
281
282 let led_gpio = &peripherals.gpio[8];
287 let sk68xx = components::sk68xx::Sk68xxComponent::new(led_gpio, rv32i::support::nop)
288 .finalize(components::sk68xx_component_static_esp32c3_160mhz!(GpioHw,));
289
290 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
291 LedHw,
292 capsules_extra::sk68xx::Sk68xxLed::new(sk68xx, 0), capsules_extra::sk68xx::Sk68xxLed::new(sk68xx, 1), capsules_extra::sk68xx::Sk68xxLed::new(sk68xx, 2), ));
296
297 let button_boot_gpio = &peripherals.gpio[9];
302 let button = components::button::ButtonComponent::new(
303 board_kernel,
304 capsules_core::button::DRIVER_NUM,
305 components::button_component_helper!(
306 GpioHw,
307 (
308 button_boot_gpio,
309 kernel::hil::gpio::ActivationMode::ActiveLow,
310 kernel::hil::gpio::FloatingState::PullUp
311 )
312 ),
313 )
314 .finalize(components::button_component_static!(GpioHw));
315
316 let scheduler_timer_alarm = &peripherals.timg1;
321 let scheduler_timer =
322 components::virtual_scheduler_timer::VirtualSchedulerTimerNoMuxComponent::new(
323 scheduler_timer_alarm,
324 )
325 .finalize(components::virtual_scheduler_timer_no_mux_component_static!(AlarmHw));
326
327 let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
328 .finalize(components::priority_component_static!());
329
330 let process_console = components::process_console::ProcessConsoleComponent::new(
335 board_kernel,
336 uart_mux,
337 mux_alarm,
338 process_printer,
339 None,
340 )
341 .finalize(components::process_console_component_static!(
342 esp32_c3::timg::TimG
343 ));
344 let _ = process_console.start();
345
346 let rng = components::rng::RngComponent::new(
351 board_kernel,
352 capsules_core::rng::DRIVER_NUM,
353 &peripherals.rng,
354 )
355 .finalize(components::rng_component_static!(esp32_c3::rng::Rng));
356
357 let chip = static_init!(
362 esp32_c3::chip::Esp32C3<
363 Esp32C3DefaultPeripherals,
364 >,
365 esp32_c3::chip::Esp32C3::new(peripherals)
366 );
367 PANIC_RESOURCES.get().map(|resources| {
368 resources.chip.put(chip);
369 });
370
371 chip.map_pic_interrupts();
373 chip.enable_pic_interrupts();
374
375 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
377
378 debug!("ESP32-C3 initialisation complete.");
379 debug!("Entering main loop.");
380
381 extern "C" {
387 static _sapps: u8;
389 static _eapps: u8;
391 static mut _sappmem: u8;
393 static _eappmem: u8;
395 }
396
397 let esp32_c3_board = static_init!(
398 Esp32C3Board,
399 Esp32C3Board {
400 gpio,
401 console,
402 alarm,
403 scheduler,
404 scheduler_timer,
405 rng,
406 led,
407 button
408 }
409 );
410
411 kernel::process::load_processes(
412 board_kernel,
413 chip,
414 core::slice::from_raw_parts(
415 core::ptr::addr_of!(_sapps),
416 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
417 ),
418 core::slice::from_raw_parts_mut(
419 core::ptr::addr_of_mut!(_sappmem),
420 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
421 ),
422 &FAULT_RESPONSE,
423 &process_mgmt_cap,
424 )
425 .unwrap_or_else(|err| {
426 debug!("Error loading processes!");
427 debug!("{:?}", err);
428 });
429
430 peripherals.init();
431
432 (board_kernel, esp32_c3_board, chip, peripherals)
433}
434
435#[no_mangle]
440pub unsafe fn main() {
441 #[cfg(test)]
442 test_main();
443
444 #[cfg(not(test))]
445 {
446 let (board_kernel, esp32_c3_board, chip, _peripherals) = setup();
447
448 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
449
450 board_kernel.kernel_loop(
451 esp32_c3_board,
452 chip,
453 None::<&kernel::ipc::IPC<0>>,
454 &main_loop_cap,
455 );
456 }
457}
458
459#[cfg(test)]
460use kernel::platform::watchdog::WatchDog;
461
462#[cfg(test)]
463fn test_runner(tests: &[&dyn Fn()]) {
464 unsafe {
465 let (board_kernel, esp32_c3_board, _chip, peripherals) = setup();
466
467 BOARD = Some(board_kernel);
468 PLATFORM = Some(&esp32_c3_board);
469 PERIPHERALS = Some(peripherals);
470 SCHEDULER = Some(
471 components::sched::priority::PriorityComponent::new(board_kernel)
472 .finalize(components::priority_component_static!()),
473 );
474 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
475
476 PLATFORM.map(|p| {
477 p.watchdog().setup();
478 });
479
480 for test in tests {
481 test();
482 }
483 }
484
485 loop {}
486}