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