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