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