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