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#[used]
54#[link_section = ".flash_bootloader"]
55static FLASH_BOOTLOADER: [u8; 256] = flash_bootloader::FLASH_BOOTLOADER;
56
57const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
60 capsules_system::process_policies::PanicFaultPolicy {};
61
62const NUM_PROCS: usize = 4;
64
65static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
67
68static mut CHIP: Option<&'static Rp2040<Rp2040DefaultPeripherals>> = None;
69static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
70 None;
71
72type TemperatureRp2040Sensor = components::temperature_rp2040::TemperatureRp2040ComponentType<
73 capsules_core::virtualizers::virtual_adc::AdcDevice<'static, rp2040::adc::Adc<'static>>,
74>;
75type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureRp2040Sensor>;
76
77pub struct RaspberryPiPico {
79 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
80 console: &'static capsules_core::console::Console<'static>,
81 alarm: &'static capsules_core::alarm::AlarmDriver<
82 'static,
83 VirtualMuxAlarm<'static, rp2040::timer::RPTimer<'static>>,
84 >,
85 gpio: &'static capsules_core::gpio::GPIO<'static, RPGpioPin<'static>>,
86 led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, RPGpioPin<'static>>, 1>,
87 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
88 temperature: &'static TemperatureDriver,
89 i2c: &'static capsules_core::i2c_master::I2CMasterDriver<'static, I2c<'static, 'static>>,
90
91 date_time:
92 &'static capsules_extra::date_time::DateTimeCapsule<'static, rp2040::rtc::Rtc<'static>>,
93 scheduler: &'static RoundRobinSched<'static>,
94 systick: cortexm0p::systick::SysTick,
95}
96
97impl SyscallDriverLookup for RaspberryPiPico {
98 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
99 where
100 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
101 {
102 match driver_num {
103 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
104 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
105 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
106 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
107 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
108 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
109 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
110 capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c)),
111 capsules_extra::date_time::DRIVER_NUM => f(Some(self.date_time)),
112 _ => f(None),
113 }
114 }
115}
116
117impl KernelResources<Rp2040<'static, Rp2040DefaultPeripherals<'static>>> for RaspberryPiPico {
118 type SyscallDriverLookup = Self;
119 type SyscallFilter = ();
120 type ProcessFault = ();
121 type Scheduler = RoundRobinSched<'static>;
122 type SchedulerTimer = cortexm0p::systick::SysTick;
123 type WatchDog = ();
124 type ContextSwitchCallback = ();
125
126 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
127 self
128 }
129 fn syscall_filter(&self) -> &Self::SyscallFilter {
130 &()
131 }
132 fn process_fault(&self) -> &Self::ProcessFault {
133 &()
134 }
135 fn scheduler(&self) -> &Self::Scheduler {
136 self.scheduler
137 }
138 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
139 &self.systick
140 }
141 fn watchdog(&self) -> &Self::WatchDog {
142 &()
143 }
144 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
145 &()
146 }
147}
148
149#[no_mangle]
160#[unsafe(naked)]
161pub unsafe extern "C" fn jump_to_bootloader() {
162 use core::arch::naked_asm;
163 naked_asm!(
164 "
165 movs r0, #0
166 ldr r1, =(0xe0000000 + 0x0000ed08)
167 str r0, [r1]
168 ldmia r0!, {{r1, r2}}
169 msr msp, r1
170 bx r2
171 "
172 );
173}
174
175fn init_clocks(peripherals: &Rp2040DefaultPeripherals) {
176 peripherals.watchdog.start_tick(12);
178
179 peripherals.clocks.disable_resus();
181
182 peripherals.xosc.init();
184
185 peripherals.clocks.disable_sys_aux();
187 peripherals.clocks.disable_ref_aux();
188
189 peripherals
190 .resets
191 .reset(&[Peripheral::PllSys, Peripheral::PllUsb]);
192 peripherals
193 .resets
194 .unreset(&[Peripheral::PllSys, Peripheral::PllUsb], true);
195
196 peripherals
204 .clocks
205 .pll_init(PllClock::Sys, 12, 1, 1500 * 1000000, 6, 2);
206 peripherals
207 .clocks
208 .pll_init(PllClock::Usb, 12, 1, 480 * 1000000, 5, 2);
209
210 peripherals.clocks.configure_reference(
212 ReferenceClockSource::Xosc,
213 ReferenceAuxiliaryClockSource::PllUsb,
214 12000000,
215 12000000,
216 );
217 peripherals.clocks.configure_system(
219 SystemClockSource::Auxiliary,
220 SystemAuxiliaryClockSource::PllSys,
221 125000000,
222 125000000,
223 );
224 peripherals
226 .clocks
227 .configure_usb(UsbAuxiliaryClockSource::PllSys, 48000000, 48000000);
228 peripherals
230 .clocks
231 .configure_adc(AdcAuxiliaryClockSource::PllUsb, 48000000, 48000000);
232 peripherals
234 .clocks
235 .configure_rtc(RtcAuxiliaryClockSource::PllSys, 48000000, 46875);
236 peripherals
240 .clocks
241 .configure_peripheral(PeripheralAuxiliaryClockSource::System, 125000000);
242}
243
244#[inline(never)]
248pub unsafe fn start() -> (
249 &'static kernel::Kernel,
250 RaspberryPiPico,
251 &'static rp2040::chip::Rp2040<'static, Rp2040DefaultPeripherals<'static>>,
252) {
253 rp2040::init();
255
256 let peripherals = static_init!(Rp2040DefaultPeripherals, Rp2040DefaultPeripherals::new());
257 peripherals.resolve_dependencies();
258
259 peripherals.resets.reset_all_except(&[
261 Peripheral::IOQSpi,
262 Peripheral::PadsQSpi,
263 Peripheral::PllUsb,
264 Peripheral::PllSys,
265 ]);
266
267 peripherals.resets.unreset_all_except(
270 &[
271 Peripheral::Adc,
272 Peripheral::Rtc,
273 Peripheral::Spi0,
274 Peripheral::Spi1,
275 Peripheral::Uart0,
276 Peripheral::Uart1,
277 Peripheral::UsbCtrl,
278 ],
279 true,
280 );
281
282 init_clocks(peripherals);
283
284 peripherals.resets.unreset_all_except(&[], true);
286
287 (*addr_of_mut!(io::WRITER)).set_uart(&peripherals.uart0);
289
290 let gpio_tx = peripherals.pins.get_pin(RPGpio::GPIO0);
292 let gpio_rx = peripherals.pins.get_pin(RPGpio::GPIO1);
293 gpio_rx.set_function(GpioFunction::UART);
294 gpio_tx.set_function(GpioFunction::UART);
295
296 for pin in 26..30 {
298 peripherals
299 .pins
300 .get_pin(RPGpio::from_usize(pin).unwrap())
301 .deactivate_pads();
302 }
303
304 let chip = static_init!(
305 Rp2040<Rp2040DefaultPeripherals>,
306 Rp2040::new(peripherals, &peripherals.sio)
307 );
308
309 CHIP = Some(chip);
310
311 let processes = components::process_array::ProcessArrayComponent::new()
313 .finalize(components::process_array_component_static!(NUM_PROCS));
314 PROCESSES = Some(processes);
315
316 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
318
319 let process_management_capability =
320 create_capability!(capabilities::ProcessManagementCapability);
321 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
322
323 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.timer)
324 .finalize(components::alarm_mux_component_static!(RPTimer));
325
326 let alarm = components::alarm::AlarmDriverComponent::new(
327 board_kernel,
328 capsules_core::alarm::DRIVER_NUM,
329 mux_alarm,
330 )
331 .finalize(components::alarm_component_static!(RPTimer));
332
333 let strings = static_init!(
335 [&str; 3],
336 [
337 "Raspberry Pi", "Pico - TockOS", "00000000000000000", ]
341 );
342
343 let cdc = components::cdc::CdcAcmComponent::new(
344 &peripherals.usb,
345 64,
347 peripherals.sysinfo.get_manufacturer_rp2040() as u16,
348 peripherals.sysinfo.get_part() as u16,
349 strings,
350 mux_alarm,
351 None,
352 )
353 .finalize(components::cdc_acm_component_static!(
354 rp2040::usb::UsbCtrl,
355 rp2040::timer::RPTimer
356 ));
357
358 let uart_mux = components::console::UartMuxComponent::new(cdc, 115200)
361 .finalize(components::uart_mux_component_static!());
362
363 let console = components::console::ConsoleComponent::new(
372 board_kernel,
373 capsules_core::console::DRIVER_NUM,
374 uart_mux,
375 )
376 .finalize(components::console_component_static!());
377 components::debug_writer::DebugWriterComponent::new(
379 uart_mux,
380 create_capability!(capabilities::SetDebugWriterCapability),
381 )
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(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 &FAULT_RESPONSE,
598 &process_management_capability,
599 )
600 .unwrap_or_else(|err| {
601 debug!("Error loading processes!");
602 debug!("{:?}", err);
603 });
604
605 (board_kernel, raspberry_pi_pico, chip)
606}
607
608#[no_mangle]
610pub unsafe fn main() {
611 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
612
613 let (board_kernel, platform, chip) = start();
614 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
615}