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