1#![no_std]
14#![no_main]
15#![deny(missing_docs)]
16
17use core::ptr::addr_of;
18
19use capsules_core::virtualizers::virtual_aes_ccm::MuxAES128CCM;
20use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
21use capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice;
22use kernel::component::Component;
23use kernel::deferred_call::DeferredCallClient;
24use kernel::hil::i2c::I2CMaster;
25use kernel::hil::led::LedHigh;
26use kernel::hil::screen::Screen;
27use kernel::hil::symmetric_encryption::AES128;
28use kernel::hil::time::Counter;
29use kernel::platform::{KernelResources, SyscallDriverLookup};
30use kernel::process::ProcessArray;
31use kernel::scheduler::round_robin::RoundRobinSched;
32#[allow(unused_imports)]
33use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
34use nrf52840::gpio::Pin;
35use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
36
37const LED1_PIN: Pin = Pin::P0_08;
39
40const VIBRA1_PIN: Pin = Pin::P0_19;
42
43const BUTTON_PIN: Pin = Pin::P0_17;
45
46const I2C_TEMP_SDA_PIN: Pin = Pin::P1_15;
48const I2C_TEMP_SCL_PIN: Pin = Pin::P0_02;
49
50const SRC_MAC: u16 = 0xf00f;
53const PAN_ID: u16 = 0xABCD;
54const DEFAULT_EXT_SRC_MAC: [u8; 8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77];
55
56pub mod io;
58
59const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
62 capsules_system::process_policies::PanicFaultPolicy {};
63
64const NUM_PROCS: usize = 8;
66
67static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
69
70static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
72static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
74 None;
75
76kernel::stack_size! {0x1000}
77
78type Bmp280Sensor = components::bmp280::Bmp280ComponentType<
79 VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
80 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, nrf52840::i2c::TWI<'static>>,
81>;
82type TemperatureDriver = components::temperature::TemperatureComponentType<Bmp280Sensor>;
83type RngDriver = components::rng::RngComponentType<nrf52840::trng::Trng<'static>>;
84
85type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType<
86 nrf52840::ieee802154_radio::Radio<'static>,
87 nrf52840::aes::AesECB<'static>,
88>;
89
90pub struct Platform {
92 temperature: &'static TemperatureDriver,
93 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
94 'static,
95 nrf52840::ble_radio::Radio<'static>,
96 VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
97 >,
98 ieee802154_radio: &'static Ieee802154Driver,
99 button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
100 pconsole: &'static capsules_core::process_console::ProcessConsole<
101 'static,
102 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
103 VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
104 components::process_console::Capability,
105 >,
106 console: &'static capsules_core::console::Console<'static>,
107 gpio: &'static capsules_core::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
108 led: &'static capsules_core::led::LedDriver<
109 'static,
110 LedHigh<'static, nrf52840::gpio::GPIOPin<'static>>,
111 2,
112 >,
113 rng: &'static RngDriver,
114 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
115 analog_comparator: &'static capsules_extra::analog_comparator::AnalogComparator<
116 'static,
117 nrf52840::acomp::Comparator<'static>,
118 >,
119 alarm: &'static capsules_core::alarm::AlarmDriver<
120 'static,
121 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
122 'static,
123 nrf52840::rtc::Rtc<'static>,
124 >,
125 >,
126 screen: &'static capsules_extra::screen::Screen<'static>,
127 scheduler: &'static RoundRobinSched<'static>,
128 systick: cortexm4::systick::SysTick,
129}
130
131impl SyscallDriverLookup for Platform {
132 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
133 where
134 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
135 {
136 match driver_num {
137 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
138 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
139 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
140 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
141 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
142 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
143 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
144 capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_radio)),
145 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
146 capsules_extra::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
147 capsules_extra::screen::DRIVER_NUM => f(Some(self.screen)),
148 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
149 _ => f(None),
150 }
151 }
152}
153
154impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
155 for Platform
156{
157 type SyscallDriverLookup = Self;
158 type SyscallFilter = ();
159 type ProcessFault = ();
160 type Scheduler = RoundRobinSched<'static>;
161 type SchedulerTimer = cortexm4::systick::SysTick;
162 type WatchDog = ();
163 type ContextSwitchCallback = ();
164
165 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
166 self
167 }
168 fn syscall_filter(&self) -> &Self::SyscallFilter {
169 &()
170 }
171 fn process_fault(&self) -> &Self::ProcessFault {
172 &()
173 }
174 fn scheduler(&self) -> &Self::Scheduler {
175 self.scheduler
176 }
177 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
178 &self.systick
179 }
180 fn watchdog(&self) -> &Self::WatchDog {
181 &()
182 }
183 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
184 &()
185 }
186}
187
188#[inline(never)]
192pub unsafe fn start() -> (
193 &'static kernel::Kernel,
194 Platform,
195 &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>,
196) {
197 nrf52840::init();
198
199 let ieee802154_ack_buf = static_init!(
200 [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
201 [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
202 );
203 let nrf52840_peripherals = static_init!(
205 Nrf52840DefaultPeripherals,
206 Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
207 );
208
209 nrf52840_peripherals.init();
211 let base_peripherals = &nrf52840_peripherals.nrf52;
212
213 let processes = components::process_array::ProcessArrayComponent::new()
215 .finalize(components::process_array_component_static!(NUM_PROCS));
216 PROCESSES = Some(processes);
217
218 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
220
221 let gpio = components::gpio::GpioComponent::new(
223 board_kernel,
224 capsules_core::gpio::DRIVER_NUM,
225 components::gpio_component_helper!(
226 nrf52840::gpio::GPIOPin,
227 0 => &nrf52840_peripherals.gpio_port[Pin::P0_29],
228 ),
229 )
230 .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin));
231
232 let button = components::button::ButtonComponent::new(
233 board_kernel,
234 capsules_core::button::DRIVER_NUM,
235 components::button_component_helper!(
236 nrf52840::gpio::GPIOPin,
237 (
238 &nrf52840_peripherals.gpio_port[BUTTON_PIN],
239 kernel::hil::gpio::ActivationMode::ActiveLow,
240 kernel::hil::gpio::FloatingState::PullUp
241 )
242 ),
243 )
244 .finalize(components::button_component_static!(
245 nrf52840::gpio::GPIOPin
246 ));
247
248 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
249 LedHigh<'static, nrf52840::gpio::GPIOPin>,
250 LedHigh::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
251 LedHigh::new(&nrf52840_peripherals.gpio_port[VIBRA1_PIN]),
252 ));
253
254 let chip = static_init!(
255 nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
256 nrf52840::chip::NRF52::new(nrf52840_peripherals)
257 );
258 CHIP = Some(chip);
259
260 nrf52_components::startup::NrfStartupComponent::new(
261 false,
262 BUTTON_PIN,
266 nrf52840::uicr::Regulator0Output::V3_0,
267 &base_peripherals.nvmc,
268 )
269 .finalize(());
270
271 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
275
276 let gpio_port = &nrf52840_peripherals.gpio_port;
277
278 kernel::debug::assign_gpios(Some(&gpio_port[LED1_PIN]), None, None);
280
281 let rtc = &base_peripherals.rtc;
282 let _ = rtc.start();
283 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
284 .finalize(components::alarm_mux_component_static!(nrf52840::rtc::Rtc));
285 let alarm = components::alarm::AlarmDriverComponent::new(
286 board_kernel,
287 capsules_core::alarm::DRIVER_NUM,
288 mux_alarm,
289 )
290 .finalize(components::alarm_component_static!(nrf52840::rtc::Rtc));
291
292 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
293 .finalize(components::process_printer_text_component_static!());
294 PROCESS_PRINTER = Some(process_printer);
295
296 let uart_channel = {
298 let rtt_memory = components::segger_rtt::SeggerRttMemoryComponent::new()
300 .finalize(components::segger_rtt_memory_component_static!());
301
302 self::io::set_rtt_memory(&*core::ptr::from_mut(rtt_memory.rtt_memory));
306
307 components::segger_rtt::SeggerRttComponent::new(mux_alarm, rtt_memory)
308 .finalize(components::segger_rtt_component_static!(nrf52840::rtc::Rtc))
309 };
310
311 let uart_mux = components::console::UartMuxComponent::new(uart_channel, 115200)
313 .finalize(components::uart_mux_component_static!());
314
315 let pconsole = components::process_console::ProcessConsoleComponent::new(
316 board_kernel,
317 uart_mux,
318 mux_alarm,
319 process_printer,
320 Some(cortexm4::support::reset),
321 )
322 .finalize(components::process_console_component_static!(
323 nrf52840::rtc::Rtc<'static>
324 ));
325
326 let console = components::console::ConsoleComponent::new(
328 board_kernel,
329 capsules_core::console::DRIVER_NUM,
330 uart_mux,
331 )
332 .finalize(components::console_component_static!());
333 components::debug_writer::DebugWriterComponent::new(
335 uart_mux,
336 create_capability!(capabilities::SetDebugWriterCapability),
337 )
338 .finalize(components::debug_writer_component_static!());
339
340 let ble_radio = components::ble::BLEComponent::new(
341 board_kernel,
342 capsules_extra::ble_advertising_driver::DRIVER_NUM,
343 &base_peripherals.ble_radio,
344 mux_alarm,
345 )
346 .finalize(components::ble_component_static!(
347 nrf52840::rtc::Rtc,
348 nrf52840::ble_radio::Radio
349 ));
350
351 let aes_mux = static_init!(
352 MuxAES128CCM<'static, nrf52840::aes::AesECB>,
353 MuxAES128CCM::new(&base_peripherals.ecb,)
354 );
355 base_peripherals.ecb.set_client(aes_mux);
356 aes_mux.register();
357
358 let (ieee802154_radio, _mux_mac) = components::ieee802154::Ieee802154Component::new(
359 board_kernel,
360 capsules_extra::ieee802154::DRIVER_NUM,
361 &nrf52840_peripherals.ieee802154_radio,
362 aes_mux,
363 PAN_ID,
364 SRC_MAC,
365 DEFAULT_EXT_SRC_MAC,
366 )
367 .finalize(components::ieee802154_component_static!(
368 nrf52840::ieee802154_radio::Radio,
369 nrf52840::aes::AesECB<'static>
370 ));
371
372 let _temp = components::temperature::TemperatureComponent::new(
375 board_kernel,
376 capsules_extra::temperature::DRIVER_NUM,
377 &base_peripherals.temp,
378 )
379 .finalize(components::temperature_component_static!(
380 nrf52840::temperature::Temp
381 ));
382
383 let sensors_i2c_bus = static_init!(
384 capsules_core::virtualizers::virtual_i2c::MuxI2C<'static, nrf52840::i2c::TWI>,
385 capsules_core::virtualizers::virtual_i2c::MuxI2C::new(&base_peripherals.twi1, None,)
386 );
387 sensors_i2c_bus.register();
388
389 base_peripherals.twi1.configure(
390 nrf52840::pinmux::Pinmux::new(I2C_TEMP_SCL_PIN as u32),
391 nrf52840::pinmux::Pinmux::new(I2C_TEMP_SDA_PIN as u32),
392 );
393 base_peripherals.twi1.set_master_client(sensors_i2c_bus);
394
395 let bmp280 = components::bmp280::Bmp280Component::new(
396 sensors_i2c_bus,
397 capsules_extra::bmp280::BASE_ADDR,
398 mux_alarm,
399 )
400 .finalize(components::bmp280_component_static!(
401 nrf52840::rtc::Rtc<'static>,
402 nrf52840::i2c::TWI
403 ));
404
405 let temperature = components::temperature::TemperatureComponent::new(
406 board_kernel,
407 capsules_extra::temperature::DRIVER_NUM,
408 bmp280,
409 )
410 .finalize(components::temperature_component_static!(Bmp280Sensor));
411
412 let rng = components::rng::RngComponent::new(
413 board_kernel,
414 capsules_core::rng::DRIVER_NUM,
415 &base_peripherals.trng,
416 )
417 .finalize(components::rng_component_static!(nrf52840::trng::Trng));
418
419 let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
422 &base_peripherals.acomp,
423 components::analog_comparator_component_helper!(
424 nrf52840::acomp::Channel,
425 &*addr_of!(nrf52840::acomp::CHANNEL_AC0)
426 ),
427 board_kernel,
428 capsules_extra::analog_comparator::DRIVER_NUM,
429 )
430 .finalize(components::analog_comparator_component_static!(
431 nrf52840::acomp::Comparator
432 ));
433
434 nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
435
436 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
437 .finalize(components::round_robin_component_static!(NUM_PROCS));
438
439 let periodic_virtual_alarm = static_init!(
440 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc>,
441 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm::new(mux_alarm)
442 );
443 periodic_virtual_alarm.setup();
444
445 let screen = {
446 let mux_spi = components::spi::SpiMuxComponent::new(&base_peripherals.spim2)
447 .finalize(components::spi_mux_component_static!(nrf52840::spi::SPIM));
448
449 use kernel::hil::spi::SpiMaster;
450 base_peripherals
451 .spim2
452 .set_rate(1_000_000)
453 .expect("SPIM2 set rate");
454
455 base_peripherals.spim2.configure(
456 nrf52840::pinmux::Pinmux::new(Pin::P0_27 as u32),
457 nrf52840::pinmux::Pinmux::new(Pin::P0_28 as u32),
458 nrf52840::pinmux::Pinmux::new(Pin::P0_26 as u32),
459 );
460
461 let disp_pin = &nrf52840_peripherals.gpio_port[Pin::P0_07];
462 let cs_pin = &nrf52840_peripherals.gpio_port[Pin::P0_05];
463
464 let display = components::lpm013m126::Lpm013m126Component::new(
465 mux_spi,
466 cs_pin,
467 disp_pin,
468 &nrf52840_peripherals.gpio_port[Pin::P0_06],
469 mux_alarm,
470 )
471 .finalize(components::lpm013m126_component_static!(
472 nrf52840::rtc::Rtc<'static>,
473 nrf52840::gpio::GPIOPin,
474 nrf52840::spi::SPIM
475 ));
476
477 let screen = components::screen::ScreenComponent::new(
478 board_kernel,
479 capsules_extra::screen::DRIVER_NUM,
480 display,
481 None,
482 )
483 .finalize(components::screen_component_static!(4096));
484 let _ = display.set_power(true);
486 screen
487 };
488
489 let platform = Platform {
490 temperature,
491 button,
492 ble_radio,
493 ieee802154_radio,
494 pconsole,
495 console,
496 led,
497 gpio,
498 rng,
499 alarm,
500 analog_comparator,
501 screen,
502 ipc: kernel::ipc::IPC::new(
503 board_kernel,
504 kernel::ipc::DRIVER_NUM,
505 &memory_allocation_capability,
506 ),
507 scheduler,
508 systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
509 };
510
511 fn load_processes(
522 board_kernel: &'static kernel::Kernel,
523 chip: &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>,
524 ) {
525 let process_management_capability =
526 create_capability!(capabilities::ProcessManagementCapability);
527 unsafe {
528 kernel::process::load_processes(
529 board_kernel,
530 chip,
531 core::slice::from_raw_parts(
532 core::ptr::addr_of!(_sapps),
533 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
534 ),
535 core::slice::from_raw_parts_mut(
536 core::ptr::addr_of_mut!(_sappmem),
537 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
538 ),
539 &FAULT_RESPONSE,
540 &process_management_capability,
541 )
542 .unwrap_or_else(|err| {
543 debug!("Error loading processes!");
544 debug!("{:?}", err);
545 });
546 }
547 }
548
549 let _ = platform.pconsole.start();
550 debug!("Initialization complete. Entering main loop\r");
551 debug!("{}", &*addr_of!(nrf52840::ficr::FICR_INSTANCE));
552
553 load_processes(board_kernel, chip);
554 extern "C" {
556 static _sapps: u8;
558 static _eapps: u8;
560 static mut _sappmem: u8;
562 static _eappmem: u8;
564 }
565
566 (board_kernel, platform, chip)
567}
568
569#[no_mangle]
571pub unsafe fn main() {
572 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
573
574 let (board_kernel, platform, chip) = start();
575 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
576}