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