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