1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of_mut;
14
15use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
16use components::gpio::GpioComponent;
17use components::led::LedsComponent;
18use enum_primitive::cast::FromPrimitive;
19use kernel::component::Component;
20use kernel::debug;
21use kernel::hil::led::LedHigh;
22use kernel::hil::usb::Client;
23use kernel::platform::{KernelResources, SyscallDriverLookup};
24use kernel::process::ProcessArray;
25use kernel::scheduler::round_robin::RoundRobinSched;
26use kernel::syscall::SyscallDriver;
27use kernel::{capabilities, create_capability, static_init};
28use rp2040::adc::{Adc, Channel};
29use rp2040::chip::{Rp2040, Rp2040DefaultPeripherals};
30use rp2040::clocks::{
31 AdcAuxiliaryClockSource, PeripheralAuxiliaryClockSource, PllClock,
32 ReferenceAuxiliaryClockSource, ReferenceClockSource, RtcAuxiliaryClockSource,
33 SystemAuxiliaryClockSource, SystemClockSource, UsbAuxiliaryClockSource,
34};
35use rp2040::gpio::{GpioFunction, RPGpio, RPGpioPin};
36use rp2040::resets::Peripheral;
37use rp2040::timer::RPTimer;
38mod io;
39
40use rp2040::sysinfo;
41
42mod flash_bootloader;
43
44kernel::stack_size! {0x1500}
45
46#[used]
48#[link_section = ".flash_bootloader"]
49static FLASH_BOOTLOADER: [u8; 256] = flash_bootloader::FLASH_BOOTLOADER;
50
51const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
54 capsules_system::process_policies::PanicFaultPolicy {};
55
56const NUM_PROCS: usize = 4;
58
59static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
61static mut CHIP: Option<&'static Rp2040<Rp2040DefaultPeripherals>> = None;
62static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
63 None;
64
65type TemperatureRp2040Sensor = components::temperature_rp2040::TemperatureRp2040ComponentType<
66 capsules_core::virtualizers::virtual_adc::AdcDevice<'static, rp2040::adc::Adc<'static>>,
67>;
68type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureRp2040Sensor>;
69
70pub struct NanoRP2040Connect {
72 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
73 console: &'static capsules_core::console::Console<'static>,
74 alarm: &'static capsules_core::alarm::AlarmDriver<
75 'static,
76 VirtualMuxAlarm<'static, rp2040::timer::RPTimer<'static>>,
77 >,
78 gpio: &'static capsules_core::gpio::GPIO<'static, RPGpioPin<'static>>,
79 led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, RPGpioPin<'static>>, 1>,
80 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
81 temperature: &'static TemperatureDriver,
82 ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
83 lsm6dsoxtr: &'static capsules_extra::lsm6dsoxtr::Lsm6dsoxtrI2C<
84 'static,
85 capsules_core::virtualizers::virtual_i2c::I2CDevice<
86 'static,
87 rp2040::i2c::I2c<'static, 'static>,
88 >,
89 >,
90
91 scheduler: &'static RoundRobinSched<'static>,
92 systick: cortexm0p::systick::SysTick,
93}
94
95impl SyscallDriverLookup for NanoRP2040Connect {
96 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
97 where
98 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
99 {
100 match driver_num {
101 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
102 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
103 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
104 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
105 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
106 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
107 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
108 capsules_extra::lsm6dsoxtr::DRIVER_NUM => f(Some(self.lsm6dsoxtr)),
109 capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
110 _ => f(None),
111 }
112 }
113}
114
115impl KernelResources<Rp2040<'static, Rp2040DefaultPeripherals<'static>>> for NanoRP2040Connect {
116 type SyscallDriverLookup = Self;
117 type SyscallFilter = ();
118 type ProcessFault = ();
119 type Scheduler = RoundRobinSched<'static>;
120 type SchedulerTimer = cortexm0p::systick::SysTick;
121 type WatchDog = ();
122 type ContextSwitchCallback = ();
123
124 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
125 self
126 }
127 fn syscall_filter(&self) -> &Self::SyscallFilter {
128 &()
129 }
130 fn process_fault(&self) -> &Self::ProcessFault {
131 &()
132 }
133 fn scheduler(&self) -> &Self::Scheduler {
134 self.scheduler
135 }
136 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
137 &self.systick
138 }
139 fn watchdog(&self) -> &Self::WatchDog {
140 &()
141 }
142 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
143 &()
144 }
145}
146
147#[no_mangle]
158#[unsafe(naked)]
159pub unsafe extern "C" fn jump_to_bootloader() {
160 use core::arch::naked_asm;
161 naked_asm!(
162 "
163 movs r0, #0
164 ldr r1, =(0xe0000000 + 0x0000ed08)
165 str r0, [r1]
166 ldmia r0!, {{r1, r2}}
167 msr msp, r1
168 bx r2
169 "
170 );
171}
172
173fn init_clocks(peripherals: &Rp2040DefaultPeripherals) {
174 peripherals.watchdog.start_tick(12);
176
177 peripherals.clocks.disable_resus();
179
180 peripherals.xosc.init();
182
183 peripherals.clocks.disable_sys_aux();
185 peripherals.clocks.disable_ref_aux();
186
187 peripherals
188 .resets
189 .reset(&[Peripheral::PllSys, Peripheral::PllUsb]);
190 peripherals
191 .resets
192 .unreset(&[Peripheral::PllSys, Peripheral::PllUsb], true);
193
194 peripherals
202 .clocks
203 .pll_init(PllClock::Sys, 12, 1, 1500 * 1000000, 6, 2);
204 peripherals
205 .clocks
206 .pll_init(PllClock::Usb, 12, 1, 480 * 1000000, 5, 2);
207
208 peripherals.clocks.configure_reference(
210 ReferenceClockSource::Xosc,
211 ReferenceAuxiliaryClockSource::PllUsb,
212 12000000,
213 12000000,
214 );
215 peripherals.clocks.configure_system(
217 SystemClockSource::Auxiliary,
218 SystemAuxiliaryClockSource::PllSys,
219 125000000,
220 125000000,
221 );
222 peripherals
224 .clocks
225 .configure_usb(UsbAuxiliaryClockSource::PllSys, 48000000, 48000000);
226 peripherals
228 .clocks
229 .configure_adc(AdcAuxiliaryClockSource::PllUsb, 48000000, 48000000);
230 peripherals
232 .clocks
233 .configure_rtc(RtcAuxiliaryClockSource::PllSys, 48000000, 46875);
234 peripherals
238 .clocks
239 .configure_peripheral(PeripheralAuxiliaryClockSource::System, 125000000);
240}
241
242#[inline(never)]
246pub unsafe fn start() -> (
247 &'static kernel::Kernel,
248 NanoRP2040Connect,
249 &'static rp2040::chip::Rp2040<'static, Rp2040DefaultPeripherals<'static>>,
250) {
251 rp2040::init();
253
254 let peripherals = static_init!(Rp2040DefaultPeripherals, Rp2040DefaultPeripherals::new());
255 peripherals.resolve_dependencies();
256
257 peripherals.resets.reset_all_except(&[
259 Peripheral::IOQSpi,
260 Peripheral::PadsQSpi,
261 Peripheral::PllUsb,
262 Peripheral::PllSys,
263 ]);
264
265 peripherals.resets.unreset_all_except(
268 &[
269 Peripheral::Adc,
270 Peripheral::Rtc,
271 Peripheral::Spi0,
272 Peripheral::Spi1,
273 Peripheral::Uart0,
274 Peripheral::Uart1,
275 Peripheral::UsbCtrl,
276 ],
277 true,
278 );
279
280 init_clocks(peripherals);
281
282 peripherals.resets.unreset_all_except(&[], true);
284
285 (*addr_of_mut!(io::WRITER)).set_uart(&peripherals.uart0);
287
288 let gpio_tx = peripherals.pins.get_pin(RPGpio::GPIO0);
290 let gpio_rx = peripherals.pins.get_pin(RPGpio::GPIO1);
291 gpio_rx.set_function(GpioFunction::UART);
292 gpio_tx.set_function(GpioFunction::UART);
293
294 for pin in 26..30 {
296 peripherals
297 .pins
298 .get_pin(RPGpio::from_usize(pin).unwrap())
299 .deactivate_pads();
300 }
301
302 let chip = static_init!(
303 Rp2040<Rp2040DefaultPeripherals>,
304 Rp2040::new(peripherals, &peripherals.sio)
305 );
306
307 CHIP = Some(chip);
308
309 let processes = components::process_array::ProcessArrayComponent::new()
311 .finalize(components::process_array_component_static!(NUM_PROCS));
312 PROCESSES = Some(processes);
313
314 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
316
317 let process_management_capability =
318 create_capability!(capabilities::ProcessManagementCapability);
319 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
320
321 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.timer)
322 .finalize(components::alarm_mux_component_static!(RPTimer));
323
324 let alarm = components::alarm::AlarmDriverComponent::new(
325 board_kernel,
326 capsules_core::alarm::DRIVER_NUM,
327 mux_alarm,
328 )
329 .finalize(components::alarm_component_static!(RPTimer));
330
331 let strings = static_init!(
333 [&str; 3],
334 [
335 "Arduino", "Nano RP2040 Connect - TockOS", "00000000000000000", ]
339 );
340
341 let cdc = components::cdc::CdcAcmComponent::new(
342 &peripherals.usb,
343 64,
345 0x0,
346 0x1,
347 strings,
348 mux_alarm,
349 None,
350 )
351 .finalize(components::cdc_acm_component_static!(
352 rp2040::usb::UsbCtrl,
353 rp2040::timer::RPTimer
354 ));
355
356 let uart_mux = components::console::UartMuxComponent::new(cdc, 115200)
359 .finalize(components::uart_mux_component_static!());
360
361 let console = components::console::ConsoleComponent::new(
370 board_kernel,
371 capsules_core::console::DRIVER_NUM,
372 uart_mux,
373 )
374 .finalize(components::console_component_static!());
375 components::debug_writer::DebugWriterComponent::new(
377 uart_mux,
378 create_capability!(capabilities::SetDebugWriterCapability),
379 )
380 .finalize(components::debug_writer_component_static!());
381
382 cdc.enable();
383 cdc.attach();
384
385 let gpio = GpioComponent::new(
386 board_kernel,
387 capsules_core::gpio::DRIVER_NUM,
388 components::gpio_component_helper!(
389 RPGpioPin,
390 2 => peripherals.pins.get_pin(RPGpio::GPIO2),
394 3 => peripherals.pins.get_pin(RPGpio::GPIO3),
395 5 => peripherals.pins.get_pin(RPGpio::GPIO5),
397 8 => peripherals.pins.get_pin(RPGpio::GPIO8),
400 9 => peripherals.pins.get_pin(RPGpio::GPIO9),
401 10 => peripherals.pins.get_pin(RPGpio::GPIO10),
402 11 => peripherals.pins.get_pin(RPGpio::GPIO11),
403 14 => peripherals.pins.get_pin(RPGpio::GPIO14),
406 15 => peripherals.pins.get_pin(RPGpio::GPIO15),
407 16 => peripherals.pins.get_pin(RPGpio::GPIO16),
408 17 => peripherals.pins.get_pin(RPGpio::GPIO17),
409 18 => peripherals.pins.get_pin(RPGpio::GPIO18),
410 19 => peripherals.pins.get_pin(RPGpio::GPIO19),
411 20 => peripherals.pins.get_pin(RPGpio::GPIO20),
412 21 => peripherals.pins.get_pin(RPGpio::GPIO21),
413 22 => peripherals.pins.get_pin(RPGpio::GPIO22),
414 23 => peripherals.pins.get_pin(RPGpio::GPIO23),
415 24 => peripherals.pins.get_pin(RPGpio::GPIO24),
416 ),
425 )
426 .finalize(components::gpio_component_static!(RPGpioPin<'static>));
427
428 let led = LedsComponent::new().finalize(components::led_component_static!(
429 LedHigh<'static, RPGpioPin<'static>>,
430 LedHigh::new(peripherals.pins.get_pin(RPGpio::GPIO6))
431 ));
432
433 peripherals.adc.init();
434
435 let adc_mux = components::adc::AdcMuxComponent::new(&peripherals.adc)
436 .finalize(components::adc_mux_component_static!(Adc));
437
438 let temp_sensor = components::temperature_rp2040::TemperatureRp2040Component::new(
439 adc_mux,
440 Channel::Channel4,
441 1.721,
442 0.706,
443 )
444 .finalize(components::temperature_rp2040_adc_component_static!(
445 rp2040::adc::Adc
446 ));
447
448 peripherals.i2c0.init(100 * 1000);
449 let gpio_sda = peripherals.pins.get_pin(RPGpio::GPIO12);
451 let gpio_scl = peripherals.pins.get_pin(RPGpio::GPIO13);
452 gpio_sda.set_function(GpioFunction::I2C);
453 gpio_scl.set_function(GpioFunction::I2C);
454 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.i2c0, None).finalize(
455 components::i2c_mux_component_static!(rp2040::i2c::I2c<'static, 'static>),
456 );
457
458 let lsm6dsoxtr = components::lsm6dsox::Lsm6dsoxtrI2CComponent::new(
459 mux_i2c,
460 capsules_extra::lsm6dsoxtr::ACCELEROMETER_BASE_ADDRESS,
461 board_kernel,
462 capsules_extra::lsm6dsoxtr::DRIVER_NUM,
463 )
464 .finalize(components::lsm6ds_i2c_component_static!(
465 rp2040::i2c::I2c<'static, 'static>
466 ));
467
468 let ninedof = components::ninedof::NineDofComponent::new(
469 board_kernel,
470 capsules_extra::ninedof::DRIVER_NUM,
471 )
472 .finalize(components::ninedof_component_static!(lsm6dsoxtr));
473
474 let temp = components::temperature::TemperatureComponent::new(
475 board_kernel,
476 capsules_extra::temperature::DRIVER_NUM,
477 temp_sensor,
478 )
479 .finalize(components::temperature_component_static!(
480 TemperatureRp2040Sensor
481 ));
482
483 let _ = lsm6dsoxtr
484 .configure(
485 capsules_extra::lsm6dsoxtr::LSM6DSOXGyroDataRate::LSM6DSOX_GYRO_RATE_12_5_HZ,
486 capsules_extra::lsm6dsoxtr::LSM6DSOXAccelDataRate::LSM6DSOX_ACCEL_RATE_12_5_HZ,
487 capsules_extra::lsm6dsoxtr::LSM6DSOXAccelRange::LSM6DSOX_ACCEL_RANGE_2_G,
488 capsules_extra::lsm6dsoxtr::LSM6DSOXTRGyroRange::LSM6DSOX_GYRO_RANGE_250_DPS,
489 true,
490 )
491 .map_err(|e| {
492 panic!(
493 "ERROR Failed to start LSM6DSOXTR sensor configuration ({:?})",
494 e
495 )
496 });
497
498 kernel::hil::sensors::TemperatureDriver::set_client(temp_sensor, temp);
508
509 let adc_channel_0 = components::adc::AdcComponent::new(adc_mux, Channel::Channel0)
510 .finalize(components::adc_component_static!(Adc));
511
512 let adc_channel_1 = components::adc::AdcComponent::new(adc_mux, Channel::Channel1)
513 .finalize(components::adc_component_static!(Adc));
514
515 let adc_channel_2 = components::adc::AdcComponent::new(adc_mux, Channel::Channel2)
516 .finalize(components::adc_component_static!(Adc));
517
518 let adc_channel_3 = components::adc::AdcComponent::new(adc_mux, Channel::Channel3)
519 .finalize(components::adc_component_static!(Adc));
520
521 let adc_syscall =
522 components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
523 .finalize(components::adc_syscall_component_helper!(
524 adc_channel_0,
525 adc_channel_1,
526 adc_channel_2,
527 adc_channel_3,
528 ));
529
530 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
531 .finalize(components::process_printer_text_component_static!());
532 PROCESS_PRINTER = Some(process_printer);
533
534 let process_console = components::process_console::ProcessConsoleComponent::new(
536 board_kernel,
537 uart_mux,
538 mux_alarm,
539 process_printer,
540 Some(cortexm0p::support::reset),
541 )
542 .finalize(components::process_console_component_static!(RPTimer));
543 let _ = process_console.start();
544
545 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
546 .finalize(components::round_robin_component_static!(NUM_PROCS));
547
548 let nano_rp2040_connect = NanoRP2040Connect {
549 ipc: kernel::ipc::IPC::new(
550 board_kernel,
551 kernel::ipc::DRIVER_NUM,
552 &memory_allocation_capability,
553 ),
554 alarm,
555 gpio,
556 led,
557 console,
558 adc: adc_syscall,
559 temperature: temp,
560
561 lsm6dsoxtr,
562 ninedof,
563
564 scheduler,
565 systick: cortexm0p::systick::SysTick::new_with_calibration(125_000_000),
566 };
567
568 let platform_type = match peripherals.sysinfo.get_platform() {
569 sysinfo::Platform::Asic => "ASIC",
570 sysinfo::Platform::Fpga => "FPGA",
571 };
572
573 debug!(
574 "RP2040 Revision {} {}",
575 peripherals.sysinfo.get_revision(),
576 platform_type
577 );
578 debug!("Initialization complete. Enter main loop");
579
580 extern "C" {
582 static _sapps: u8;
584 static _eapps: u8;
586 static mut _sappmem: u8;
588 static _eappmem: u8;
590 }
591
592 kernel::process::load_processes(
593 board_kernel,
594 chip,
595 core::slice::from_raw_parts(
596 core::ptr::addr_of!(_sapps),
597 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
598 ),
599 core::slice::from_raw_parts_mut(
600 core::ptr::addr_of_mut!(_sappmem),
601 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
602 ),
603 &FAULT_RESPONSE,
604 &process_management_capability,
605 )
606 .unwrap_or_else(|err| {
607 debug!("Error loading processes!");
608 debug!("{:?}", err);
609 });
610
611 (board_kernel, nano_rp2040_connect, chip)
612}
613
614#[no_mangle]
616pub unsafe fn main() {
617 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
618
619 let (board_kernel, platform, chip) = start();
620 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
621}