1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of_mut;
14
15use capsules_core::i2c_master::I2CMasterDriver;
16use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
17use components::date_time_component_static;
18use components::gpio::GpioComponent;
19use components::led::LedsComponent;
20use enum_primitive::cast::FromPrimitive;
21use kernel::component::Component;
22use kernel::debug;
23use kernel::hil::gpio::{Configure, FloatingState};
24use kernel::hil::i2c::I2CMaster;
25use kernel::hil::led::LedHigh;
26use kernel::hil::usb::Client;
27use kernel::platform::{KernelResources, SyscallDriverLookup};
28use kernel::process::ProcessArray;
29use kernel::scheduler::round_robin::RoundRobinSched;
30use kernel::syscall::SyscallDriver;
31use kernel::{capabilities, create_capability, static_init};
32
33use rp2040::adc::{Adc, Channel};
34use rp2040::chip::{Rp2040, Rp2040DefaultPeripherals};
35use rp2040::clocks::{
36 AdcAuxiliaryClockSource, PeripheralAuxiliaryClockSource, PllClock,
37 ReferenceAuxiliaryClockSource, ReferenceClockSource, RtcAuxiliaryClockSource,
38 SystemAuxiliaryClockSource, SystemClockSource, UsbAuxiliaryClockSource,
39};
40use rp2040::gpio::{GpioFunction, RPGpio, RPGpioPin};
41use rp2040::i2c::I2c;
42use rp2040::resets::Peripheral;
43use rp2040::sysinfo;
44use rp2040::timer::RPTimer;
45
46mod io;
47
48mod flash_bootloader;
49
50kernel::stack_size! {0x1500}
51
52#[cfg_attr(not(target_os = "macos"), link_section = ".flash_bootloader")]
58#[used]
59static FLASH_BOOTLOADER: [u8; 256] = flash_bootloader::FLASH_BOOTLOADER;
60
61const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
64 capsules_system::process_policies::PanicFaultPolicy {};
65
66const NUM_PROCS: usize = 4;
68
69type ChipHw = Rp2040<'static, Rp2040DefaultPeripherals<'static>>;
70
71static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
73
74static mut CHIP: Option<&'static Rp2040<Rp2040DefaultPeripherals>> = None;
75static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
76 None;
77
78type TemperatureRp2040Sensor = components::temperature_rp2040::TemperatureRp2040ComponentType<
79 capsules_core::virtualizers::virtual_adc::AdcDevice<'static, rp2040::adc::Adc<'static>>,
80>;
81type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureRp2040Sensor>;
82
83pub struct RaspberryPiPico {
85 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
86 console: &'static capsules_core::console::Console<'static>,
87 alarm: &'static capsules_core::alarm::AlarmDriver<
88 'static,
89 VirtualMuxAlarm<'static, rp2040::timer::RPTimer<'static>>,
90 >,
91 gpio: &'static capsules_core::gpio::GPIO<'static, RPGpioPin<'static>>,
92 led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, RPGpioPin<'static>>, 1>,
93 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
94 temperature: &'static TemperatureDriver,
95 i2c: &'static capsules_core::i2c_master::I2CMasterDriver<'static, I2c<'static, 'static>>,
96
97 date_time:
98 &'static capsules_extra::date_time::DateTimeCapsule<'static, rp2040::rtc::Rtc<'static>>,
99 scheduler: &'static RoundRobinSched<'static>,
100 systick: cortexm0p::systick::SysTick,
101}
102
103impl SyscallDriverLookup for RaspberryPiPico {
104 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
105 where
106 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
107 {
108 match driver_num {
109 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
110 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
111 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
112 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
113 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
114 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
115 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
116 capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c)),
117 capsules_extra::date_time::DRIVER_NUM => f(Some(self.date_time)),
118 _ => f(None),
119 }
120 }
121}
122
123impl KernelResources<Rp2040<'static, Rp2040DefaultPeripherals<'static>>> for RaspberryPiPico {
124 type SyscallDriverLookup = Self;
125 type SyscallFilter = ();
126 type ProcessFault = ();
127 type Scheduler = RoundRobinSched<'static>;
128 type SchedulerTimer = cortexm0p::systick::SysTick;
129 type WatchDog = ();
130 type ContextSwitchCallback = ();
131
132 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
133 self
134 }
135 fn syscall_filter(&self) -> &Self::SyscallFilter {
136 &()
137 }
138 fn process_fault(&self) -> &Self::ProcessFault {
139 &()
140 }
141 fn scheduler(&self) -> &Self::Scheduler {
142 self.scheduler
143 }
144 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
145 &self.systick
146 }
147 fn watchdog(&self) -> &Self::WatchDog {
148 &()
149 }
150 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
151 &()
152 }
153}
154
155#[no_mangle]
166#[unsafe(naked)]
167pub unsafe extern "C" fn jump_to_bootloader() {
168 use core::arch::naked_asm;
169 naked_asm!(
170 "
171 movs r0, #0
172 ldr r1, =(0xe0000000 + 0x0000ed08)
173 str r0, [r1]
174 ldmia r0!, {{r1, r2}}
175 msr msp, r1
176 bx r2
177 "
178 );
179}
180
181fn init_clocks(peripherals: &Rp2040DefaultPeripherals) {
182 peripherals.watchdog.start_tick(12);
184
185 peripherals.clocks.disable_resus();
187
188 peripherals.xosc.init();
190
191 peripherals.clocks.disable_sys_aux();
193 peripherals.clocks.disable_ref_aux();
194
195 peripherals
196 .resets
197 .reset(&[Peripheral::PllSys, Peripheral::PllUsb]);
198 peripherals
199 .resets
200 .unreset(&[Peripheral::PllSys, Peripheral::PllUsb], true);
201
202 peripherals
210 .clocks
211 .pll_init(PllClock::Sys, 12, 1, 1500 * 1000000, 6, 2);
212 peripherals
213 .clocks
214 .pll_init(PllClock::Usb, 12, 1, 480 * 1000000, 5, 2);
215
216 peripherals.clocks.configure_reference(
218 ReferenceClockSource::Xosc,
219 ReferenceAuxiliaryClockSource::PllUsb,
220 12000000,
221 12000000,
222 );
223 peripherals.clocks.configure_system(
225 SystemClockSource::Auxiliary,
226 SystemAuxiliaryClockSource::PllSys,
227 125000000,
228 125000000,
229 );
230 peripherals
232 .clocks
233 .configure_usb(UsbAuxiliaryClockSource::PllSys, 48000000, 48000000);
234 peripherals
236 .clocks
237 .configure_adc(AdcAuxiliaryClockSource::PllUsb, 48000000, 48000000);
238 peripherals
240 .clocks
241 .configure_rtc(RtcAuxiliaryClockSource::PllSys, 48000000, 46875);
242 peripherals
246 .clocks
247 .configure_peripheral(PeripheralAuxiliaryClockSource::System, 125000000);
248}
249
250#[inline(never)]
254pub unsafe fn start() -> (
255 &'static kernel::Kernel,
256 RaspberryPiPico,
257 &'static rp2040::chip::Rp2040<'static, Rp2040DefaultPeripherals<'static>>,
258) {
259 rp2040::init();
261
262 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
264 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
265 >();
266
267 let peripherals = static_init!(Rp2040DefaultPeripherals, Rp2040DefaultPeripherals::new());
268 peripherals.resolve_dependencies();
269
270 peripherals.resets.reset_all_except(&[
272 Peripheral::IOQSpi,
273 Peripheral::PadsQSpi,
274 Peripheral::PllUsb,
275 Peripheral::PllSys,
276 ]);
277
278 peripherals.resets.unreset_all_except(
281 &[
282 Peripheral::Adc,
283 Peripheral::Rtc,
284 Peripheral::Spi0,
285 Peripheral::Spi1,
286 Peripheral::Uart0,
287 Peripheral::Uart1,
288 Peripheral::UsbCtrl,
289 ],
290 true,
291 );
292
293 init_clocks(peripherals);
294
295 peripherals.resets.unreset_all_except(&[], true);
297
298 (*addr_of_mut!(io::WRITER)).set_uart(&peripherals.uart0);
300
301 let gpio_tx = peripherals.pins.get_pin(RPGpio::GPIO0);
303 let gpio_rx = peripherals.pins.get_pin(RPGpio::GPIO1);
304 gpio_rx.set_function(GpioFunction::UART);
305 gpio_tx.set_function(GpioFunction::UART);
306
307 for pin in 26..30 {
309 peripherals
310 .pins
311 .get_pin(RPGpio::from_usize(pin).unwrap())
312 .deactivate_pads();
313 }
314
315 let chip = static_init!(
316 Rp2040<Rp2040DefaultPeripherals>,
317 Rp2040::new(peripherals, &peripherals.sio)
318 );
319
320 CHIP = Some(chip);
321
322 let processes = components::process_array::ProcessArrayComponent::new()
324 .finalize(components::process_array_component_static!(NUM_PROCS));
325 PROCESSES = Some(processes);
326
327 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
329
330 let process_management_capability =
331 create_capability!(capabilities::ProcessManagementCapability);
332 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
333
334 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.timer)
335 .finalize(components::alarm_mux_component_static!(RPTimer));
336
337 let alarm = components::alarm::AlarmDriverComponent::new(
338 board_kernel,
339 capsules_core::alarm::DRIVER_NUM,
340 mux_alarm,
341 )
342 .finalize(components::alarm_component_static!(RPTimer));
343
344 let strings = static_init!(
346 [&str; 3],
347 [
348 "Raspberry Pi", "Pico - TockOS", "00000000000000000", ]
352 );
353
354 let cdc = components::cdc::CdcAcmComponent::new(
355 &peripherals.usb,
356 64,
358 peripherals.sysinfo.get_manufacturer_rp2040() as u16,
359 peripherals.sysinfo.get_part() as u16,
360 strings,
361 mux_alarm,
362 None,
363 )
364 .finalize(components::cdc_acm_component_static!(
365 rp2040::usb::UsbCtrl,
366 rp2040::timer::RPTimer
367 ));
368
369 let uart_mux = components::console::UartMuxComponent::new(cdc, 115200)
372 .finalize(components::uart_mux_component_static!());
373
374 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_unsafe(
390 uart_mux,
391 create_capability!(capabilities::SetDebugWriterCapability),
392 || unsafe {
393 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
394 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
395 >();
396 },
397 )
398 .finalize(components::debug_writer_component_static!());
399
400 cdc.enable();
401 cdc.attach();
402
403 let gpio = GpioComponent::new(
404 board_kernel,
405 capsules_core::gpio::DRIVER_NUM,
406 components::gpio_component_helper!(
407 RPGpioPin,
408 2 => peripherals.pins.get_pin(RPGpio::GPIO2),
412 3 => peripherals.pins.get_pin(RPGpio::GPIO3),
413 6 => peripherals.pins.get_pin(RPGpio::GPIO6),
417 7 => peripherals.pins.get_pin(RPGpio::GPIO7),
418 8 => peripherals.pins.get_pin(RPGpio::GPIO8),
419 9 => peripherals.pins.get_pin(RPGpio::GPIO9),
420 10 => peripherals.pins.get_pin(RPGpio::GPIO10),
421 11 => peripherals.pins.get_pin(RPGpio::GPIO11),
422 12 => peripherals.pins.get_pin(RPGpio::GPIO12),
423 13 => peripherals.pins.get_pin(RPGpio::GPIO13),
424 14 => peripherals.pins.get_pin(RPGpio::GPIO14),
425 15 => peripherals.pins.get_pin(RPGpio::GPIO15),
426 16 => peripherals.pins.get_pin(RPGpio::GPIO16),
427 17 => peripherals.pins.get_pin(RPGpio::GPIO17),
428 18 => peripherals.pins.get_pin(RPGpio::GPIO18),
429 19 => peripherals.pins.get_pin(RPGpio::GPIO19),
430 20 => peripherals.pins.get_pin(RPGpio::GPIO20),
431 21 => peripherals.pins.get_pin(RPGpio::GPIO21),
432 22 => peripherals.pins.get_pin(RPGpio::GPIO22),
433 23 => peripherals.pins.get_pin(RPGpio::GPIO23),
434 24 => peripherals.pins.get_pin(RPGpio::GPIO24),
435 ),
444 )
445 .finalize(components::gpio_component_static!(RPGpioPin<'static>));
446
447 let led = LedsComponent::new().finalize(components::led_component_static!(
448 LedHigh<'static, RPGpioPin<'static>>,
449 LedHigh::new(peripherals.pins.get_pin(RPGpio::GPIO25))
450 ));
451
452 peripherals.adc.init();
453
454 let adc_mux = components::adc::AdcMuxComponent::new(&peripherals.adc)
455 .finalize(components::adc_mux_component_static!(Adc));
456
457 let temp_sensor = components::temperature_rp2040::TemperatureRp2040Component::new(
458 adc_mux,
459 Channel::Channel4,
460 1.721,
461 0.706,
462 )
463 .finalize(components::temperature_rp2040_adc_component_static!(
464 rp2040::adc::Adc
465 ));
466
467 match peripherals.rtc.rtc_init() {
470 Ok(()) => {}
471 Err(e) => {
472 debug!("error starting rtc {:?}", e)
473 }
474 }
475
476 let date_time = components::date_time::DateTimeComponent::new(
477 board_kernel,
478 capsules_extra::date_time::DRIVER_NUM,
479 &peripherals.rtc,
480 )
481 .finalize(date_time_component_static!(rp2040::rtc::Rtc<'static>));
482
483 let temp = components::temperature::TemperatureComponent::new(
484 board_kernel,
485 capsules_extra::temperature::DRIVER_NUM,
486 temp_sensor,
487 )
488 .finalize(components::temperature_component_static!(
489 TemperatureRp2040Sensor
490 ));
491
492 let adc_channel_0 = components::adc::AdcComponent::new(adc_mux, Channel::Channel0)
493 .finalize(components::adc_component_static!(Adc));
494
495 let adc_channel_1 = components::adc::AdcComponent::new(adc_mux, Channel::Channel1)
496 .finalize(components::adc_component_static!(Adc));
497
498 let adc_channel_2 = components::adc::AdcComponent::new(adc_mux, Channel::Channel2)
499 .finalize(components::adc_component_static!(Adc));
500
501 let adc_channel_3 = components::adc::AdcComponent::new(adc_mux, Channel::Channel3)
502 .finalize(components::adc_component_static!(Adc));
503
504 let adc_syscall =
505 components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
506 .finalize(components::adc_syscall_component_helper!(
507 adc_channel_0,
508 adc_channel_1,
509 adc_channel_2,
510 adc_channel_3,
511 ));
512 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
514 .finalize(components::process_printer_text_component_static!());
515 PROCESS_PRINTER = Some(process_printer);
516
517 let process_console = components::process_console::ProcessConsoleComponent::new(
518 board_kernel,
519 uart_mux,
520 mux_alarm,
521 process_printer,
522 Some(cortexm0p::support::reset),
523 )
524 .finalize(components::process_console_component_static!(RPTimer));
525 let _ = process_console.start();
526
527 let sda_pin = peripherals.pins.get_pin(RPGpio::GPIO4);
528 let scl_pin = peripherals.pins.get_pin(RPGpio::GPIO5);
529
530 sda_pin.set_function(GpioFunction::I2C);
531 scl_pin.set_function(GpioFunction::I2C);
532
533 sda_pin.set_floating_state(FloatingState::PullUp);
534 scl_pin.set_floating_state(FloatingState::PullUp);
535
536 let i2c_master_buffer = static_init!(
537 [u8; capsules_core::i2c_master::BUFFER_LENGTH],
538 [0; capsules_core::i2c_master::BUFFER_LENGTH]
539 );
540 let i2c0 = &peripherals.i2c0;
541 let i2c = static_init!(
542 I2CMasterDriver<I2c<'static, 'static>>,
543 I2CMasterDriver::new(
544 i2c0,
545 i2c_master_buffer,
546 board_kernel.create_grant(
547 capsules_core::i2c_master::DRIVER_NUM,
548 &memory_allocation_capability
549 ),
550 )
551 );
552 i2c0.init(10 * 1000);
553 i2c0.set_master_client(i2c);
554
555 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
556 .finalize(components::round_robin_component_static!(NUM_PROCS));
557
558 let raspberry_pi_pico = RaspberryPiPico {
559 ipc: kernel::ipc::IPC::new(
560 board_kernel,
561 kernel::ipc::DRIVER_NUM,
562 &memory_allocation_capability,
563 ),
564 alarm,
565 gpio,
566 led,
567 console,
568 adc: adc_syscall,
569 temperature: temp,
570 i2c,
571 date_time,
572
573 scheduler,
574 systick: cortexm0p::systick::SysTick::new_with_calibration(125_000_000),
575 };
576
577 let platform_type = match peripherals.sysinfo.get_platform() {
578 sysinfo::Platform::Asic => "ASIC",
579 sysinfo::Platform::Fpga => "FPGA",
580 };
581
582 debug!(
583 "RP2040 Revision {} {}",
584 peripherals.sysinfo.get_revision(),
585 platform_type
586 );
587
588 debug!("Initialization complete. Enter main loop");
589
590 extern "C" {
592 static _sapps: u8;
594 static _eapps: u8;
596 static mut _sappmem: u8;
598 static _eappmem: u8;
600 }
601
602 kernel::process::load_processes(
603 board_kernel,
604 chip,
605 core::slice::from_raw_parts(
606 core::ptr::addr_of!(_sapps),
607 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
608 ),
609 core::slice::from_raw_parts_mut(
610 core::ptr::addr_of_mut!(_sappmem),
611 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
612 ),
613 &FAULT_RESPONSE,
614 &process_management_capability,
615 )
616 .unwrap_or_else(|err| {
617 debug!("Error loading processes!");
618 debug!("{:?}", err);
619 });
620
621 (board_kernel, raspberry_pi_pico, chip)
622}
623
624#[no_mangle]
626pub unsafe fn main() {
627 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
628
629 let (board_kernel, platform, chip) = start();
630 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
631}