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