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
50#[no_mangle]
52#[link_section = ".stack_buffer"]
53static mut STACK_MEMORY: [u8; 0x1500] = [0; 0x1500];
54
55#[used]
57#[link_section = ".flash_bootloader"]
58static FLASH_BOOTLOADER: [u8; 256] = flash_bootloader::FLASH_BOOTLOADER;
59
60const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
63 capsules_system::process_policies::PanicFaultPolicy {};
64
65const NUM_PROCS: usize = 4;
67
68static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
70
71static mut CHIP: Option<&'static Rp2040<Rp2040DefaultPeripherals>> = None;
72static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
73 None;
74
75type TemperatureRp2040Sensor = components::temperature_rp2040::TemperatureRp2040ComponentType<
76 capsules_core::virtualizers::virtual_adc::AdcDevice<'static, rp2040::adc::Adc<'static>>,
77>;
78type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureRp2040Sensor>;
79
80pub struct RaspberryPiPico {
82 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
83 console: &'static capsules_core::console::Console<'static>,
84 alarm: &'static capsules_core::alarm::AlarmDriver<
85 'static,
86 VirtualMuxAlarm<'static, rp2040::timer::RPTimer<'static>>,
87 >,
88 gpio: &'static capsules_core::gpio::GPIO<'static, RPGpioPin<'static>>,
89 led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, RPGpioPin<'static>>, 1>,
90 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
91 temperature: &'static TemperatureDriver,
92 i2c: &'static capsules_core::i2c_master::I2CMasterDriver<'static, I2c<'static, 'static>>,
93
94 date_time:
95 &'static capsules_extra::date_time::DateTimeCapsule<'static, rp2040::rtc::Rtc<'static>>,
96 scheduler: &'static RoundRobinSched<'static>,
97 systick: cortexm0p::systick::SysTick,
98}
99
100impl SyscallDriverLookup for RaspberryPiPico {
101 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
102 where
103 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
104 {
105 match driver_num {
106 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
107 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
108 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
109 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
110 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
111 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
112 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
113 capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c)),
114 capsules_extra::date_time::DRIVER_NUM => f(Some(self.date_time)),
115 _ => f(None),
116 }
117 }
118}
119
120impl KernelResources<Rp2040<'static, Rp2040DefaultPeripherals<'static>>> for RaspberryPiPico {
121 type SyscallDriverLookup = Self;
122 type SyscallFilter = ();
123 type ProcessFault = ();
124 type Scheduler = RoundRobinSched<'static>;
125 type SchedulerTimer = cortexm0p::systick::SysTick;
126 type WatchDog = ();
127 type ContextSwitchCallback = ();
128
129 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
130 self
131 }
132 fn syscall_filter(&self) -> &Self::SyscallFilter {
133 &()
134 }
135 fn process_fault(&self) -> &Self::ProcessFault {
136 &()
137 }
138 fn scheduler(&self) -> &Self::Scheduler {
139 self.scheduler
140 }
141 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
142 &self.systick
143 }
144 fn watchdog(&self) -> &Self::WatchDog {
145 &()
146 }
147 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
148 &()
149 }
150}
151
152#[no_mangle]
163#[unsafe(naked)]
164pub unsafe extern "C" fn jump_to_bootloader() {
165 use core::arch::naked_asm;
166 naked_asm!(
167 "
168 movs r0, #0
169 ldr r1, =(0xe0000000 + 0x0000ed08)
170 str r0, [r1]
171 ldmia r0!, {{r1, r2}}
172 msr msp, r1
173 bx r2
174 ",
175 );
176}
177
178fn init_clocks(peripherals: &Rp2040DefaultPeripherals) {
179 peripherals.watchdog.start_tick(12);
181
182 peripherals.clocks.disable_resus();
184
185 peripherals.xosc.init();
187
188 peripherals.clocks.disable_sys_aux();
190 peripherals.clocks.disable_ref_aux();
191
192 peripherals
193 .resets
194 .reset(&[Peripheral::PllSys, Peripheral::PllUsb]);
195 peripherals
196 .resets
197 .unreset(&[Peripheral::PllSys, Peripheral::PllUsb], true);
198
199 peripherals
207 .clocks
208 .pll_init(PllClock::Sys, 12, 1, 1500 * 1000000, 6, 2);
209 peripherals
210 .clocks
211 .pll_init(PllClock::Usb, 12, 1, 480 * 1000000, 5, 2);
212
213 peripherals.clocks.configure_reference(
215 ReferenceClockSource::Xosc,
216 ReferenceAuxiliaryClockSource::PllUsb,
217 12000000,
218 12000000,
219 );
220 peripherals.clocks.configure_system(
222 SystemClockSource::Auxiliary,
223 SystemAuxiliaryClockSource::PllSys,
224 125000000,
225 125000000,
226 );
227 peripherals
229 .clocks
230 .configure_usb(UsbAuxiliaryClockSource::PllSys, 48000000, 48000000);
231 peripherals
233 .clocks
234 .configure_adc(AdcAuxiliaryClockSource::PllUsb, 48000000, 48000000);
235 peripherals
237 .clocks
238 .configure_rtc(RtcAuxiliaryClockSource::PllSys, 48000000, 46875);
239 peripherals
243 .clocks
244 .configure_peripheral(PeripheralAuxiliaryClockSource::System, 125000000);
245}
246
247#[inline(never)]
251pub unsafe fn start() -> (
252 &'static kernel::Kernel,
253 RaspberryPiPico,
254 &'static rp2040::chip::Rp2040<'static, Rp2040DefaultPeripherals<'static>>,
255) {
256 rp2040::init();
258
259 let peripherals = static_init!(Rp2040DefaultPeripherals, Rp2040DefaultPeripherals::new());
260 peripherals.resolve_dependencies();
261
262 peripherals.resets.reset_all_except(&[
264 Peripheral::IOQSpi,
265 Peripheral::PadsQSpi,
266 Peripheral::PllUsb,
267 Peripheral::PllSys,
268 ]);
269
270 peripherals.resets.unreset_all_except(
273 &[
274 Peripheral::Adc,
275 Peripheral::Rtc,
276 Peripheral::Spi0,
277 Peripheral::Spi1,
278 Peripheral::Uart0,
279 Peripheral::Uart1,
280 Peripheral::UsbCtrl,
281 ],
282 true,
283 );
284
285 init_clocks(peripherals);
286
287 peripherals.resets.unreset_all_except(&[], true);
289
290 (*addr_of_mut!(io::WRITER)).set_uart(&peripherals.uart0);
292
293 let gpio_tx = peripherals.pins.get_pin(RPGpio::GPIO0);
295 let gpio_rx = peripherals.pins.get_pin(RPGpio::GPIO1);
296 gpio_rx.set_function(GpioFunction::UART);
297 gpio_tx.set_function(GpioFunction::UART);
298
299 for pin in 26..30 {
301 peripherals
302 .pins
303 .get_pin(RPGpio::from_usize(pin).unwrap())
304 .deactivate_pads();
305 }
306
307 let chip = static_init!(
308 Rp2040<Rp2040DefaultPeripherals>,
309 Rp2040::new(peripherals, &peripherals.sio)
310 );
311
312 CHIP = Some(chip);
313
314 let processes = components::process_array::ProcessArrayComponent::new()
316 .finalize(components::process_array_component_static!(NUM_PROCS));
317 PROCESSES = Some(processes);
318
319 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
321
322 let process_management_capability =
323 create_capability!(capabilities::ProcessManagementCapability);
324 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
325
326 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.timer)
327 .finalize(components::alarm_mux_component_static!(RPTimer));
328
329 let alarm = components::alarm::AlarmDriverComponent::new(
330 board_kernel,
331 capsules_core::alarm::DRIVER_NUM,
332 mux_alarm,
333 )
334 .finalize(components::alarm_component_static!(RPTimer));
335
336 let strings = static_init!(
338 [&str; 3],
339 [
340 "Raspberry Pi", "Pico - TockOS", "00000000000000000", ]
344 );
345
346 let cdc = components::cdc::CdcAcmComponent::new(
347 &peripherals.usb,
348 64,
350 peripherals.sysinfo.get_manufacturer_rp2040() as u16,
351 peripherals.sysinfo.get_part() as u16,
352 strings,
353 mux_alarm,
354 None,
355 )
356 .finalize(components::cdc_acm_component_static!(
357 rp2040::usb::UsbCtrl,
358 rp2040::timer::RPTimer
359 ));
360
361 let uart_mux = components::console::UartMuxComponent::new(cdc, 115200)
364 .finalize(components::uart_mux_component_static!());
365
366 let console = components::console::ConsoleComponent::new(
375 board_kernel,
376 capsules_core::console::DRIVER_NUM,
377 uart_mux,
378 )
379 .finalize(components::console_component_static!());
380 components::debug_writer::DebugWriterComponent::new(
382 uart_mux,
383 create_capability!(capabilities::SetDebugWriterCapability),
384 )
385 .finalize(components::debug_writer_component_static!());
386
387 cdc.enable();
388 cdc.attach();
389
390 let gpio = GpioComponent::new(
391 board_kernel,
392 capsules_core::gpio::DRIVER_NUM,
393 components::gpio_component_helper!(
394 RPGpioPin,
395 2 => peripherals.pins.get_pin(RPGpio::GPIO2),
399 3 => peripherals.pins.get_pin(RPGpio::GPIO3),
400 6 => peripherals.pins.get_pin(RPGpio::GPIO6),
404 7 => peripherals.pins.get_pin(RPGpio::GPIO7),
405 8 => peripherals.pins.get_pin(RPGpio::GPIO8),
406 9 => peripherals.pins.get_pin(RPGpio::GPIO9),
407 10 => peripherals.pins.get_pin(RPGpio::GPIO10),
408 11 => peripherals.pins.get_pin(RPGpio::GPIO11),
409 12 => peripherals.pins.get_pin(RPGpio::GPIO12),
410 13 => peripherals.pins.get_pin(RPGpio::GPIO13),
411 14 => peripherals.pins.get_pin(RPGpio::GPIO14),
412 15 => peripherals.pins.get_pin(RPGpio::GPIO15),
413 16 => peripherals.pins.get_pin(RPGpio::GPIO16),
414 17 => peripherals.pins.get_pin(RPGpio::GPIO17),
415 18 => peripherals.pins.get_pin(RPGpio::GPIO18),
416 19 => peripherals.pins.get_pin(RPGpio::GPIO19),
417 20 => peripherals.pins.get_pin(RPGpio::GPIO20),
418 21 => peripherals.pins.get_pin(RPGpio::GPIO21),
419 22 => peripherals.pins.get_pin(RPGpio::GPIO22),
420 23 => peripherals.pins.get_pin(RPGpio::GPIO23),
421 24 => peripherals.pins.get_pin(RPGpio::GPIO24),
422 ),
431 )
432 .finalize(components::gpio_component_static!(RPGpioPin<'static>));
433
434 let led = LedsComponent::new().finalize(components::led_component_static!(
435 LedHigh<'static, RPGpioPin<'static>>,
436 LedHigh::new(peripherals.pins.get_pin(RPGpio::GPIO25))
437 ));
438
439 peripherals.adc.init();
440
441 let adc_mux = components::adc::AdcMuxComponent::new(&peripherals.adc)
442 .finalize(components::adc_mux_component_static!(Adc));
443
444 let temp_sensor = components::temperature_rp2040::TemperatureRp2040Component::new(
445 adc_mux,
446 Channel::Channel4,
447 1.721,
448 0.706,
449 )
450 .finalize(components::temperature_rp2040_adc_component_static!(
451 rp2040::adc::Adc
452 ));
453
454 match peripherals.rtc.rtc_init() {
457 Ok(()) => {}
458 Err(e) => {
459 debug!("error starting rtc {:?}", e)
460 }
461 }
462
463 let date_time = components::date_time::DateTimeComponent::new(
464 board_kernel,
465 capsules_extra::date_time::DRIVER_NUM,
466 &peripherals.rtc,
467 )
468 .finalize(date_time_component_static!(rp2040::rtc::Rtc<'static>));
469
470 let temp = components::temperature::TemperatureComponent::new(
471 board_kernel,
472 capsules_extra::temperature::DRIVER_NUM,
473 temp_sensor,
474 )
475 .finalize(components::temperature_component_static!(
476 TemperatureRp2040Sensor
477 ));
478
479 let adc_channel_0 = components::adc::AdcComponent::new(adc_mux, Channel::Channel0)
480 .finalize(components::adc_component_static!(Adc));
481
482 let adc_channel_1 = components::adc::AdcComponent::new(adc_mux, Channel::Channel1)
483 .finalize(components::adc_component_static!(Adc));
484
485 let adc_channel_2 = components::adc::AdcComponent::new(adc_mux, Channel::Channel2)
486 .finalize(components::adc_component_static!(Adc));
487
488 let adc_channel_3 = components::adc::AdcComponent::new(adc_mux, Channel::Channel3)
489 .finalize(components::adc_component_static!(Adc));
490
491 let adc_syscall =
492 components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
493 .finalize(components::adc_syscall_component_helper!(
494 adc_channel_0,
495 adc_channel_1,
496 adc_channel_2,
497 adc_channel_3,
498 ));
499 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
501 .finalize(components::process_printer_text_component_static!());
502 PROCESS_PRINTER = Some(process_printer);
503
504 let process_console = components::process_console::ProcessConsoleComponent::new(
505 board_kernel,
506 uart_mux,
507 mux_alarm,
508 process_printer,
509 Some(cortexm0p::support::reset),
510 )
511 .finalize(components::process_console_component_static!(RPTimer));
512 let _ = process_console.start();
513
514 let sda_pin = peripherals.pins.get_pin(RPGpio::GPIO4);
515 let scl_pin = peripherals.pins.get_pin(RPGpio::GPIO5);
516
517 sda_pin.set_function(GpioFunction::I2C);
518 scl_pin.set_function(GpioFunction::I2C);
519
520 sda_pin.set_floating_state(FloatingState::PullUp);
521 scl_pin.set_floating_state(FloatingState::PullUp);
522
523 let i2c_master_buffer = static_init!(
524 [u8; capsules_core::i2c_master::BUFFER_LENGTH],
525 [0; capsules_core::i2c_master::BUFFER_LENGTH]
526 );
527 let i2c0 = &peripherals.i2c0;
528 let i2c = static_init!(
529 I2CMasterDriver<I2c<'static, 'static>>,
530 I2CMasterDriver::new(
531 i2c0,
532 i2c_master_buffer,
533 board_kernel.create_grant(
534 capsules_core::i2c_master::DRIVER_NUM,
535 &memory_allocation_capability
536 ),
537 )
538 );
539 i2c0.init(10 * 1000);
540 i2c0.set_master_client(i2c);
541
542 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
543 .finalize(components::round_robin_component_static!(NUM_PROCS));
544
545 let raspberry_pi_pico = RaspberryPiPico {
546 ipc: kernel::ipc::IPC::new(
547 board_kernel,
548 kernel::ipc::DRIVER_NUM,
549 &memory_allocation_capability,
550 ),
551 alarm,
552 gpio,
553 led,
554 console,
555 adc: adc_syscall,
556 temperature: temp,
557 i2c,
558 date_time,
559
560 scheduler,
561 systick: cortexm0p::systick::SysTick::new_with_calibration(125_000_000),
562 };
563
564 let platform_type = match peripherals.sysinfo.get_platform() {
565 sysinfo::Platform::Asic => "ASIC",
566 sysinfo::Platform::Fpga => "FPGA",
567 };
568
569 debug!(
570 "RP2040 Revision {} {}",
571 peripherals.sysinfo.get_revision(),
572 platform_type
573 );
574
575 debug!("Initialization complete. Enter main loop");
576
577 extern "C" {
579 static _sapps: u8;
581 static _eapps: u8;
583 static mut _sappmem: u8;
585 static _eappmem: u8;
587 }
588
589 kernel::process::load_processes(
590 board_kernel,
591 chip,
592 core::slice::from_raw_parts(
593 core::ptr::addr_of!(_sapps),
594 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
595 ),
596 core::slice::from_raw_parts_mut(
597 core::ptr::addr_of_mut!(_sappmem),
598 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
599 ),
600 &FAULT_RESPONSE,
601 &process_management_capability,
602 )
603 .unwrap_or_else(|err| {
604 debug!("Error loading processes!");
605 debug!("{:?}", err);
606 });
607
608 (board_kernel, raspberry_pi_pico, chip)
609}
610
611#[no_mangle]
613pub unsafe fn main() {
614 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
615
616 let (board_kernel, platform, chip) = start();
617 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
618}