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