1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of_mut;
14
15use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
16use components::gpio::GpioComponent;
17use components::led::LedsComponent;
18use enum_primitive::cast::FromPrimitive;
19use kernel::component::Component;
20use kernel::hil::led::LedHigh;
21use kernel::hil::usb::Client;
22use kernel::platform::{KernelResources, SyscallDriverLookup};
23use kernel::process::ProcessArray;
24use kernel::scheduler::round_robin::RoundRobinSched;
25use kernel::{capabilities, create_capability, static_init};
26use kernel::{debug, hil};
27
28use rp2040::adc::{Adc, Channel};
29use rp2040::chip::{Rp2040, Rp2040DefaultPeripherals};
30use rp2040::clocks::{
31 AdcAuxiliaryClockSource, PeripheralAuxiliaryClockSource, PllClock,
32 ReferenceAuxiliaryClockSource, ReferenceClockSource, RtcAuxiliaryClockSource,
33 SystemAuxiliaryClockSource, SystemClockSource, UsbAuxiliaryClockSource,
34};
35use rp2040::gpio::{GpioFunction, RPGpio, RPGpioPin};
36use rp2040::pio::Pio;
37use rp2040::pio_pwm::PioPwm;
38use rp2040::resets::Peripheral;
39use rp2040::spi::Spi;
40use rp2040::sysinfo;
41use rp2040::timer::RPTimer;
42
43mod io;
44
45mod flash_bootloader;
46
47#[no_mangle]
49#[link_section = ".stack_buffer"]
50static mut STACK_MEMORY: [u8; 0x1500] = [0; 0x1500];
51
52#[used]
54#[link_section = ".flash_bootloader"]
55static FLASH_BOOTLOADER: [u8; 256] = flash_bootloader::FLASH_BOOTLOADER;
56
57const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
60 capsules_system::process_policies::PanicFaultPolicy {};
61
62const NUM_PROCS: usize = 4;
64
65static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
67static mut CHIP: Option<&'static Rp2040<Rp2040DefaultPeripherals>> = None;
68static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
69 None;
70
71type TemperatureRp2040Sensor = components::temperature_rp2040::TemperatureRp2040ComponentType<
72 capsules_core::virtualizers::virtual_adc::AdcDevice<'static, rp2040::adc::Adc<'static>>,
73>;
74type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureRp2040Sensor>;
75
76pub struct PicoExplorerBase {
78 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
79 console: &'static capsules_core::console::Console<'static>,
80 alarm: &'static capsules_core::alarm::AlarmDriver<
81 'static,
82 VirtualMuxAlarm<'static, rp2040::timer::RPTimer<'static>>,
83 >,
84 gpio: &'static capsules_core::gpio::GPIO<'static, RPGpioPin<'static>>,
85 led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, RPGpioPin<'static>>, 1>,
86 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
87 temperature: &'static TemperatureDriver,
88 buzzer_driver: &'static capsules_extra::buzzer_driver::Buzzer<
89 'static,
90 capsules_extra::buzzer_pwm::PwmBuzzer<
91 'static,
92 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
93 'static,
94 rp2040::timer::RPTimer<'static>,
95 >,
96 capsules_core::virtualizers::virtual_pwm::PwmPinUser<
97 'static,
98 rp2040::pwm::Pwm<'static>,
99 >,
100 >,
101 >,
102 button: &'static capsules_core::button::Button<'static, RPGpioPin<'static>>,
103 screen: &'static capsules_extra::screen::Screen<'static>,
104
105 scheduler: &'static RoundRobinSched<'static>,
106 systick: cortexm0p::systick::SysTick,
107}
108
109impl SyscallDriverLookup for PicoExplorerBase {
110 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
111 where
112 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
113 {
114 match driver_num {
115 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
116 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
117 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
118 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
119 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
120 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
121 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
122 capsules_extra::buzzer_driver::DRIVER_NUM => f(Some(self.buzzer_driver)),
123 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
124 capsules_extra::screen::DRIVER_NUM => f(Some(self.screen)),
125 _ => f(None),
126 }
127 }
128}
129
130impl KernelResources<Rp2040<'static, Rp2040DefaultPeripherals<'static>>> for PicoExplorerBase {
131 type SyscallDriverLookup = Self;
132 type SyscallFilter = ();
133 type ProcessFault = ();
134 type Scheduler = RoundRobinSched<'static>;
135 type SchedulerTimer = cortexm0p::systick::SysTick;
136 type WatchDog = ();
137 type ContextSwitchCallback = ();
138
139 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
140 self
141 }
142 fn syscall_filter(&self) -> &Self::SyscallFilter {
143 &()
144 }
145 fn process_fault(&self) -> &Self::ProcessFault {
146 &()
147 }
148 fn scheduler(&self) -> &Self::Scheduler {
149 self.scheduler
150 }
151 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
152 &self.systick
153 }
154 fn watchdog(&self) -> &Self::WatchDog {
155 &()
156 }
157 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
158 &()
159 }
160}
161
162#[no_mangle]
173#[unsafe(naked)]
174pub unsafe extern "C" fn jump_to_bootloader() {
175 use core::arch::naked_asm;
176 naked_asm!(
177 "
178 movs r0, #0
179 ldr r1, =(0xe0000000 + 0x0000ed08)
180 str r0, [r1]
181 ldmia r0!, {{r1, r2}}
182 msr msp, r1
183 bx r2
184 ",
185 );
186}
187
188fn init_clocks(peripherals: &Rp2040DefaultPeripherals) {
189 peripherals.watchdog.start_tick(12);
191
192 peripherals.clocks.disable_resus();
194
195 peripherals.xosc.init();
197
198 peripherals.clocks.disable_sys_aux();
200 peripherals.clocks.disable_ref_aux();
201
202 peripherals
203 .resets
204 .reset(&[Peripheral::PllSys, Peripheral::PllUsb]);
205 peripherals
206 .resets
207 .unreset(&[Peripheral::PllSys, Peripheral::PllUsb], true);
208
209 peripherals
217 .clocks
218 .pll_init(PllClock::Sys, 12, 1, 1500 * 1000000, 6, 2);
219 peripherals
220 .clocks
221 .pll_init(PllClock::Usb, 12, 1, 480 * 1000000, 5, 2);
222
223 peripherals.clocks.configure_reference(
225 ReferenceClockSource::Xosc,
226 ReferenceAuxiliaryClockSource::PllUsb,
227 12000000,
228 12000000,
229 );
230 peripherals.clocks.configure_system(
232 SystemClockSource::Auxiliary,
233 SystemAuxiliaryClockSource::PllSys,
234 125000000,
235 125000000,
236 );
237 peripherals
239 .clocks
240 .configure_usb(UsbAuxiliaryClockSource::PllSys, 48000000, 48000000);
241 peripherals
243 .clocks
244 .configure_adc(AdcAuxiliaryClockSource::PllUsb, 48000000, 48000000);
245 peripherals
247 .clocks
248 .configure_rtc(RtcAuxiliaryClockSource::PllSys, 48000000, 46875);
249 peripherals
253 .clocks
254 .configure_peripheral(PeripheralAuxiliaryClockSource::System, 125000000);
255}
256
257#[inline(never)]
261pub unsafe fn start() -> (
262 &'static kernel::Kernel,
263 PicoExplorerBase,
264 &'static rp2040::chip::Rp2040<'static, Rp2040DefaultPeripherals<'static>>,
265) {
266 rp2040::init();
268
269 let peripherals = static_init!(Rp2040DefaultPeripherals, Rp2040DefaultPeripherals::new());
270 peripherals.resolve_dependencies();
271
272 peripherals.resets.reset_all_except(&[
274 Peripheral::IOQSpi,
275 Peripheral::PadsQSpi,
276 Peripheral::PllUsb,
277 Peripheral::PllSys,
278 ]);
279
280 peripherals.resets.unreset_all_except(
283 &[
284 Peripheral::Adc,
285 Peripheral::Rtc,
286 Peripheral::Spi0,
287 Peripheral::Spi1,
288 Peripheral::Uart0,
289 Peripheral::Uart1,
290 Peripheral::UsbCtrl,
291 ],
292 true,
293 );
294
295 init_clocks(peripherals);
296
297 peripherals.resets.unreset_all_except(&[], true);
299
300 let gpio_tx = peripherals.pins.get_pin(RPGpio::GPIO0);
302 let gpio_rx = peripherals.pins.get_pin(RPGpio::GPIO1);
303 gpio_rx.set_function(GpioFunction::UART);
304 gpio_tx.set_function(GpioFunction::UART);
305
306 (*addr_of_mut!(io::WRITER)).set_uart(&peripherals.uart0);
308
309 for pin in 26..30 {
311 peripherals
312 .pins
313 .get_pin(RPGpio::from_usize(pin).unwrap())
314 .deactivate_pads();
315 }
316
317 let chip = static_init!(
318 Rp2040<Rp2040DefaultPeripherals>,
319 Rp2040::new(peripherals, &peripherals.sio)
320 );
321
322 CHIP = Some(chip);
323
324 let processes = components::process_array::ProcessArrayComponent::new()
326 .finalize(components::process_array_component_static!(NUM_PROCS));
327 PROCESSES = Some(processes);
328
329 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
331
332 let process_management_capability =
333 create_capability!(capabilities::ProcessManagementCapability);
334 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
335
336 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.timer)
337 .finalize(components::alarm_mux_component_static!(RPTimer));
338
339 let alarm = components::alarm::AlarmDriverComponent::new(
340 board_kernel,
341 capsules_core::alarm::DRIVER_NUM,
342 mux_alarm,
343 )
344 .finalize(components::alarm_component_static!(RPTimer));
345
346 let strings = static_init!(
348 [&str; 3],
349 [
350 "Raspberry Pi", "pico explorer base - TockOS", "00000000000000000", ]
354 );
355
356 let cdc = components::cdc::CdcAcmComponent::new(
357 &peripherals.usb,
358 64,
360 peripherals.sysinfo.get_manufacturer_rp2040(),
361 peripherals.sysinfo.get_part(),
362 strings,
363 mux_alarm,
364 None,
365 )
366 .finalize(components::cdc_acm_component_static!(
367 rp2040::usb::UsbCtrl,
368 rp2040::timer::RPTimer
369 ));
370
371 let uart_mux = components::console::UartMuxComponent::new(cdc, 115200)
374 .finalize(components::uart_mux_component_static!());
375
376 let console = components::console::ConsoleComponent::new(
382 board_kernel,
383 capsules_core::console::DRIVER_NUM,
384 uart_mux,
385 )
386 .finalize(components::console_component_static!());
387 components::debug_writer::DebugWriterComponent::new(
389 uart_mux,
390 create_capability!(capabilities::SetDebugWriterCapability),
391 )
392 .finalize(components::debug_writer_component_static!());
393
394 cdc.enable();
395 cdc.attach();
396
397 let gpio = GpioComponent::new(
398 board_kernel,
399 capsules_core::gpio::DRIVER_NUM,
400 components::gpio_component_helper!(
401 RPGpioPin,
402 3 => peripherals.pins.get_pin(RPGpio::GPIO3),
408 4 => peripherals.pins.get_pin(RPGpio::GPIO4),
409 5 => peripherals.pins.get_pin(RPGpio::GPIO5),
410 6 => peripherals.pins.get_pin(RPGpio::GPIO6),
411 7 => peripherals.pins.get_pin(RPGpio::GPIO7),
412 20 => peripherals.pins.get_pin(RPGpio::GPIO20),
413 21 => peripherals.pins.get_pin(RPGpio::GPIO21),
414 22 => peripherals.pins.get_pin(RPGpio::GPIO22),
415 ),
416 )
417 .finalize(components::gpio_component_static!(RPGpioPin<'static>));
418
419 let led = LedsComponent::new().finalize(components::led_component_static!(
420 LedHigh<'static, RPGpioPin<'static>>,
421 LedHigh::new(peripherals.pins.get_pin(RPGpio::GPIO25))
422 ));
423
424 peripherals.adc.init();
425
426 peripherals
428 .pins
429 .get_pin(RPGpio::GPIO2)
430 .set_function(GpioFunction::PWM);
431
432 let adc_mux = components::adc::AdcMuxComponent::new(&peripherals.adc)
433 .finalize(components::adc_mux_component_static!(Adc));
434
435 let temp_sensor = components::temperature_rp2040::TemperatureRp2040Component::new(
436 adc_mux,
437 Channel::Channel4,
438 1.721,
439 0.706,
440 )
441 .finalize(components::temperature_rp2040_adc_component_static!(
442 rp2040::adc::Adc
443 ));
444
445 let temp = components::temperature::TemperatureComponent::new(
446 board_kernel,
447 capsules_extra::temperature::DRIVER_NUM,
448 temp_sensor,
449 )
450 .finalize(components::temperature_component_static!(
451 TemperatureRp2040Sensor
452 ));
453
454 let spi_clk = peripherals.pins.get_pin(RPGpio::GPIO18);
456 let spi_csn = peripherals.pins.get_pin(RPGpio::GPIO17);
457 let spi_mosi = peripherals.pins.get_pin(RPGpio::GPIO19);
458 spi_clk.set_function(GpioFunction::SPI);
459 spi_csn.set_function(GpioFunction::SPI);
460 spi_mosi.set_function(GpioFunction::SPI);
461 let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.spi0)
462 .finalize(components::spi_mux_component_static!(Spi));
463
464 let bus = components::bus::SpiMasterBusComponent::new(
465 mux_spi,
466 hil::spi::cs::IntoChipSelect::<_, hil::spi::cs::ActiveLow>::into_cs(
467 peripherals.pins.get_pin(RPGpio::GPIO17),
468 ),
469 20_000_000,
470 kernel::hil::spi::ClockPhase::SampleLeading,
471 kernel::hil::spi::ClockPolarity::IdleLow,
472 )
473 .finalize(components::spi_bus_component_static!(Spi));
474
475 let tft = components::st77xx::ST77XXComponent::new(
476 mux_alarm,
477 bus,
478 Some(peripherals.pins.get_pin(RPGpio::GPIO16)),
479 None,
480 &capsules_extra::st77xx::ST7789H2,
481 )
482 .finalize(components::st77xx_component_static!(
483 capsules_extra::bus::SpiMasterBus<
485 'static,
486 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, Spi>,
487 >,
488 RPTimer,
490 RPGpioPin,
492 ));
493
494 let _ = tft.init();
495
496 let button = components::button::ButtonComponent::new(
497 board_kernel,
498 capsules_core::button::DRIVER_NUM,
499 components::button_component_helper!(
500 RPGpioPin,
501 (
502 peripherals.pins.get_pin(RPGpio::GPIO12),
503 kernel::hil::gpio::ActivationMode::ActiveLow,
504 kernel::hil::gpio::FloatingState::PullUp
505 ), (
507 peripherals.pins.get_pin(RPGpio::GPIO13),
508 kernel::hil::gpio::ActivationMode::ActiveLow,
509 kernel::hil::gpio::FloatingState::PullUp
510 ), (
512 peripherals.pins.get_pin(RPGpio::GPIO14),
513 kernel::hil::gpio::ActivationMode::ActiveLow,
514 kernel::hil::gpio::FloatingState::PullUp
515 ), (
517 peripherals.pins.get_pin(RPGpio::GPIO15),
518 kernel::hil::gpio::ActivationMode::ActiveLow,
519 kernel::hil::gpio::FloatingState::PullUp
520 ), ),
522 )
523 .finalize(components::button_component_static!(RPGpioPin));
524
525 let screen = components::screen::ScreenComponent::new(
526 board_kernel,
527 capsules_extra::screen::DRIVER_NUM,
528 tft,
529 Some(tft),
530 )
531 .finalize(components::screen_component_static!(57600));
532
533 let adc_channel_0 = components::adc::AdcComponent::new(adc_mux, Channel::Channel0)
534 .finalize(components::adc_component_static!(Adc));
535
536 let adc_channel_1 = components::adc::AdcComponent::new(adc_mux, Channel::Channel1)
537 .finalize(components::adc_component_static!(Adc));
538
539 let adc_channel_2 = components::adc::AdcComponent::new(adc_mux, Channel::Channel2)
540 .finalize(components::adc_component_static!(Adc));
541
542 let adc_syscall =
543 components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
544 .finalize(components::adc_syscall_component_helper!(
545 adc_channel_0,
546 adc_channel_1,
547 adc_channel_2,
548 ));
549
550 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
551 .finalize(components::process_printer_text_component_static!());
552 PROCESS_PRINTER = Some(process_printer);
553 let process_console = components::process_console::ProcessConsoleComponent::new(
555 board_kernel,
556 uart_mux,
557 mux_alarm,
558 process_printer,
559 Some(cortexm0p::support::reset),
560 )
561 .finalize(components::process_console_component_static!(RPTimer));
562 let _ = process_console.start();
563
564 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
565 .finalize(components::round_robin_component_static!(NUM_PROCS));
566
567 use kernel::hil::buzzer::Buzzer;
571 use kernel::hil::time::Alarm;
572
573 let mux_pwm = components::pwm::PwmMuxComponent::new(&peripherals.pwm)
574 .finalize(components::pwm_mux_component_static!(rp2040::pwm::Pwm));
575
576 let virtual_pwm_buzzer =
577 components::pwm::PwmPinUserComponent::new(mux_pwm, rp2040::gpio::RPGpio::GPIO2)
578 .finalize(components::pwm_pin_user_component_static!(rp2040::pwm::Pwm));
579
580 let virtual_alarm_buzzer = static_init!(
581 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
582 'static,
583 rp2040::timer::RPTimer,
584 >,
585 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm::new(mux_alarm)
586 );
587
588 virtual_alarm_buzzer.setup();
589
590 let pwm_buzzer = static_init!(
591 capsules_extra::buzzer_pwm::PwmBuzzer<
592 'static,
593 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
594 'static,
595 rp2040::timer::RPTimer,
596 >,
597 capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, rp2040::pwm::Pwm>,
598 >,
599 capsules_extra::buzzer_pwm::PwmBuzzer::new(
600 virtual_pwm_buzzer,
601 virtual_alarm_buzzer,
602 capsules_extra::buzzer_pwm::DEFAULT_MAX_BUZZ_TIME_MS,
603 )
604 );
605
606 let buzzer_driver = static_init!(
607 capsules_extra::buzzer_driver::Buzzer<
608 'static,
609 capsules_extra::buzzer_pwm::PwmBuzzer<
610 'static,
611 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
612 'static,
613 rp2040::timer::RPTimer,
614 >,
615 capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, rp2040::pwm::Pwm>,
616 >,
617 >,
618 capsules_extra::buzzer_driver::Buzzer::new(
619 pwm_buzzer,
620 capsules_extra::buzzer_driver::DEFAULT_MAX_BUZZ_TIME_MS,
621 board_kernel.create_grant(
622 capsules_extra::buzzer_driver::DRIVER_NUM,
623 &memory_allocation_capability
624 )
625 )
626 );
627
628 pwm_buzzer.set_client(buzzer_driver);
629
630 virtual_alarm_buzzer.set_alarm_client(pwm_buzzer);
631
632 let pico_explorer_base = PicoExplorerBase {
633 ipc: kernel::ipc::IPC::new(
634 board_kernel,
635 kernel::ipc::DRIVER_NUM,
636 &memory_allocation_capability,
637 ),
638 alarm,
639 gpio,
640 led,
641 console,
642 adc: adc_syscall,
643 temperature: temp,
644 buzzer_driver,
645 button,
646 screen,
647 scheduler,
648 systick: cortexm0p::systick::SysTick::new_with_calibration(125_000_000),
649 };
650
651 let platform_type = match peripherals.sysinfo.get_platform() {
652 sysinfo::Platform::Asic => "ASIC",
653 sysinfo::Platform::Fpga => "FPGA",
654 };
655
656 debug!(
657 "RP2040 Revision {} {}",
658 peripherals.sysinfo.get_revision(),
659 platform_type
660 );
661 debug!("Initialization complete. Enter main loop");
662
663 extern "C" {
665 static _sapps: u8;
667 static _eapps: u8;
669 static mut _sappmem: u8;
671 static _eappmem: u8;
673 }
674
675 kernel::process::load_processes(
676 board_kernel,
677 chip,
678 core::slice::from_raw_parts(
679 core::ptr::addr_of!(_sapps),
680 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
681 ),
682 core::slice::from_raw_parts_mut(
683 core::ptr::addr_of_mut!(_sappmem),
684 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
685 ),
686 &FAULT_RESPONSE,
687 &process_management_capability,
688 )
689 .unwrap_or_else(|err| {
690 debug!("Error loading processes!");
691 debug!("{:?}", err);
692 });
693
694 let mut pio: Pio = Pio::new_pio0();
699
700 let _pio_pwm = PioPwm::new(&mut pio, &peripherals.clocks);
701 (board_kernel, pico_explorer_base, chip)
711}
712
713#[no_mangle]
715pub unsafe fn main() {
716 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
717
718 let (board_kernel, platform, chip) = start();
719 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
720}