1#![no_std]
10#![cfg_attr(not(doc), no_main)]
13#![deny(missing_docs)]
14
15use core::ptr::addr_of;
16use core::ptr::addr_of_mut;
17
18use kernel::capabilities;
19use kernel::component::Component;
20use kernel::hil;
21use kernel::hil::gpio::Configure;
22use kernel::hil::gpio::Output;
23use kernel::hil::led::LedHigh;
24use kernel::hil::spi::SpiMaster;
25use kernel::hil::time::Counter;
26use kernel::platform::{KernelResources, SyscallDriverLookup};
27use kernel::scheduler::round_robin::RoundRobinSched;
28#[allow(unused_imports)]
29use kernel::{create_capability, debug, debug_gpio, debug_verbose, static_init};
30
31use nrf52840::gpio::Pin;
32use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
33
34const LED_RED_PIN: Pin = Pin::P0_14;
36const LED_GREEN_PIN: Pin = Pin::P0_13;
37
38const BUTTON_RST_PIN: Pin = Pin::P0_18;
39
40const GPIO_D2: Pin = Pin::P0_17;
41const GPIO_D3: Pin = Pin::P0_16;
42const GPIO_D4: Pin = Pin::P0_15;
43const GPIO_D5: Pin = Pin::P1_09;
44const GPIO_D6: Pin = Pin::P1_04;
45const GPIO_D7: Pin = Pin::P1_03;
46
47const UART_TX_PIN: Pin = Pin::P0_24;
48const UART_RX_PIN: Pin = Pin::P0_22;
49
50const I2C_SDA_PIN: Pin = Pin::P0_27;
52const I2C_SCL_PIN: Pin = Pin::P0_26;
53
54const SPI_CS_PIN: Pin = Pin::P1_12;
56const SPI_SCK_PIN: Pin = Pin::P1_13;
57const SPI_MOSI_PIN: Pin = Pin::P1_14;
58const SPI_MISO_PIN: Pin = Pin::P1_15;
59const RADIO_BUSY_PIN: Pin = Pin::P1_11;
60const RADIO_RESET_PIN: Pin = Pin::P1_10;
61
62const LR_DIO9: Pin = Pin::P1_08;
63
64const I2C_PWR: Pin = Pin::P0_07;
66
67const LORA_SPI_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhySPI as usize;
68const LORA_GPIO_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhyGPIO as usize;
69
70pub mod io;
72
73const FAULT_RESPONSE: capsules_system::process_policies::StopWithDebugFaultPolicy =
76 capsules_system::process_policies::StopWithDebugFaultPolicy {};
77
78const NUM_PROCS: usize = 8;
80
81static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
83 [None; NUM_PROCS];
84
85static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
86static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
87 None;
88
89#[no_mangle]
91#[link_section = ".stack_buffer"]
92pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
93
94type SHT4xSensor = components::sht4x::SHT4xComponentType<
95 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
96 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, nrf52840::i2c::TWI<'static>>,
97>;
98type TemperatureDriver = components::temperature::TemperatureComponentType<SHT4xSensor>;
99type HumidityDriver = components::humidity::HumidityComponentType<SHT4xSensor>;
100type RngDriver = components::rng::RngComponentType<nrf52840::trng::Trng<'static>>;
101
102type NonvolatileDriver = components::nonvolatile_storage::NonvolatileStorageComponentType;
103
104pub struct Platform {
106 console: &'static capsules_core::console::Console<'static>,
107 gpio: &'static capsules_core::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>,
108 led: &'static capsules_core::led::LedDriver<
109 'static,
110 LedHigh<'static, nrf52::gpio::GPIOPin<'static>>,
111 2,
112 >,
113 rng: &'static RngDriver,
114 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
115 nonvolatile_storage: &'static NonvolatileDriver,
116 alarm: &'static capsules_core::alarm::AlarmDriver<
117 'static,
118 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
119 'static,
120 nrf52::rtc::Rtc<'static>,
121 >,
122 >,
123 temperature: &'static TemperatureDriver,
124 humidity: &'static HumidityDriver,
125 lr1110_gpio: &'static capsules_core::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
126 lr1110_spi: &'static capsules_core::spi_controller::Spi<
127 'static,
128 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
129 'static,
130 nrf52840::spi::SPIM<'static>,
131 >,
132 >,
133 scheduler: &'static RoundRobinSched<'static>,
134 systick: cortexm4::systick::SysTick,
135}
136
137impl SyscallDriverLookup for Platform {
138 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
139 where
140 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
141 {
142 match driver_num {
143 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
144 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
145 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
146 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
147 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
148 capsules_extra::nonvolatile_storage_driver::DRIVER_NUM => {
149 f(Some(self.nonvolatile_storage))
150 }
151 LORA_SPI_DRIVER_NUM => f(Some(self.lr1110_spi)),
152 LORA_GPIO_DRIVER_NUM => f(Some(self.lr1110_gpio)),
153 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
154 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
155 capsules_extra::humidity::DRIVER_NUM => f(Some(self.humidity)),
156 _ => f(None),
157 }
158 }
159}
160
161impl KernelResources<nrf52::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
162 for Platform
163{
164 type SyscallDriverLookup = Self;
165 type SyscallFilter = ();
166 type ProcessFault = ();
167 type Scheduler = RoundRobinSched<'static>;
168 type SchedulerTimer = cortexm4::systick::SysTick;
169 type WatchDog = ();
170 type ContextSwitchCallback = ();
171
172 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
173 self
174 }
175 fn syscall_filter(&self) -> &Self::SyscallFilter {
176 &()
177 }
178 fn process_fault(&self) -> &Self::ProcessFault {
179 &()
180 }
181 fn scheduler(&self) -> &Self::Scheduler {
182 self.scheduler
183 }
184 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
185 &self.systick
186 }
187 fn watchdog(&self) -> &Self::WatchDog {
188 &()
189 }
190 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
191 &()
192 }
193}
194
195#[inline(never)]
199pub unsafe fn start() -> (
200 &'static kernel::Kernel,
201 Platform,
202 &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>,
203) {
204 nrf52840::init();
205
206 let ieee802154_ack_buf = static_init!(
207 [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
208 [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
209 );
210
211 let nrf52840_peripherals = static_init!(
213 Nrf52840DefaultPeripherals,
214 Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
215 );
216
217 nrf52840_peripherals.init();
219 let base_peripherals = &nrf52840_peripherals.nrf52;
220
221 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
222
223 nrf52_components::startup::NrfStartupComponent::new(
224 false,
225 BUTTON_RST_PIN,
226 nrf52840::uicr::Regulator0Output::DEFAULT,
227 &base_peripherals.nvmc,
228 )
229 .finalize(());
230
231 let process_management_capability =
238 create_capability!(capabilities::ProcessManagementCapability);
239 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
240
241 kernel::debug::assign_gpios(
249 Some(&nrf52840_peripherals.gpio_port[LED_GREEN_PIN]),
250 Some(&nrf52840_peripherals.gpio_port[LED_RED_PIN]),
251 None,
252 );
253
254 let gpio = components::gpio::GpioComponent::new(
259 board_kernel,
260 capsules_core::gpio::DRIVER_NUM,
261 components::gpio_component_helper!(
262 nrf52840::gpio::GPIOPin,
263 2 => &nrf52840_peripherals.gpio_port[GPIO_D2],
264 3 => &nrf52840_peripherals.gpio_port[GPIO_D3],
265 4 => &nrf52840_peripherals.gpio_port[GPIO_D4],
266 5 => &nrf52840_peripherals.gpio_port[GPIO_D5],
267 6 => &nrf52840_peripherals.gpio_port[GPIO_D6],
268 7 => &nrf52840_peripherals.gpio_port[GPIO_D7],
269 ),
270 )
271 .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin));
272
273 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
278 LedHigh<'static, nrf52840::gpio::GPIOPin>,
279 LedHigh::new(&nrf52840_peripherals.gpio_port[LED_GREEN_PIN]),
280 LedHigh::new(&nrf52840_peripherals.gpio_port[LED_RED_PIN]),
281 ));
282
283 let rtc = &base_peripherals.rtc;
288 let _ = rtc.start();
289
290 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
291 .finalize(components::alarm_mux_component_static!(nrf52::rtc::Rtc));
292 let alarm = components::alarm::AlarmDriverComponent::new(
293 board_kernel,
294 capsules_core::alarm::DRIVER_NUM,
295 mux_alarm,
296 )
297 .finalize(components::alarm_component_static!(nrf52::rtc::Rtc));
298
299 base_peripherals.uarte0.initialize(
304 nrf52::pinmux::Pinmux::new(UART_TX_PIN as u32),
305 nrf52::pinmux::Pinmux::new(UART_RX_PIN as u32),
306 None,
307 None,
308 );
309
310 let uart_mux = components::console::UartMuxComponent::new(&base_peripherals.uarte0, 115200)
312 .finalize(components::uart_mux_component_static!());
313
314 let console = components::console::ConsoleComponent::new(
316 board_kernel,
317 capsules_core::console::DRIVER_NUM,
318 uart_mux,
319 )
320 .finalize(components::console_component_static!());
321
322 components::debug_writer::DebugWriterComponent::new(uart_mux)
324 .finalize(components::debug_writer_component_static!());
325
326 nrf52840_peripherals.gpio_port[I2C_PWR].make_output();
332 nrf52840_peripherals.gpio_port[I2C_PWR].set();
333
334 let mux_i2c = components::i2c::I2CMuxComponent::new(&base_peripherals.twi1, None)
335 .finalize(components::i2c_mux_component_static!(nrf52840::i2c::TWI));
336 base_peripherals.twi1.configure(
337 nrf52840::pinmux::Pinmux::new(I2C_SCL_PIN as u32),
338 nrf52840::pinmux::Pinmux::new(I2C_SDA_PIN as u32),
339 );
340
341 let sht4x = components::sht4x::SHT4xComponent::new(
342 mux_i2c,
343 capsules_extra::sht4x::BASE_ADDR,
344 mux_alarm,
345 )
346 .finalize(components::sht4x_component_static!(
347 nrf52::rtc::Rtc<'static>,
348 nrf52840::i2c::TWI
349 ));
350
351 let temperature = components::temperature::TemperatureComponent::new(
352 board_kernel,
353 capsules_extra::temperature::DRIVER_NUM,
354 sht4x,
355 )
356 .finalize(components::temperature_component_static!(SHT4xSensor));
357
358 let humidity = components::humidity::HumidityComponent::new(
359 board_kernel,
360 capsules_extra::humidity::DRIVER_NUM,
361 sht4x,
362 )
363 .finalize(components::humidity_component_static!(SHT4xSensor));
364
365 let mux_spi = components::spi::SpiMuxComponent::new(&base_peripherals.spim0)
370 .finalize(components::spi_mux_component_static!(nrf52840::spi::SPIM));
371
372 let lr1110_spi = components::spi::SpiSyscallComponent::new(
374 board_kernel,
375 mux_spi,
376 hil::spi::cs::IntoChipSelect::<_, hil::spi::cs::ActiveLow>::into_cs(
377 &nrf52840_peripherals.gpio_port[SPI_CS_PIN],
378 ),
379 LORA_SPI_DRIVER_NUM,
380 )
381 .finalize(components::spi_syscall_component_static!(
382 nrf52840::spi::SPIM
383 ));
384
385 base_peripherals.spim0.configure(
386 nrf52840::pinmux::Pinmux::new(SPI_MOSI_PIN as u32),
387 nrf52840::pinmux::Pinmux::new(SPI_MISO_PIN as u32),
388 nrf52840::pinmux::Pinmux::new(SPI_SCK_PIN as u32),
389 );
390
391 base_peripherals
392 .spim0
393 .specify_chip_select(
394 hil::spi::cs::IntoChipSelect::<_, hil::spi::cs::ActiveLow>::into_cs(
395 &nrf52840_peripherals.gpio_port[SPI_CS_PIN],
396 ),
397 )
398 .unwrap();
399
400 let lr1110_gpio = components::gpio::GpioComponent::new(
402 board_kernel,
403 LORA_GPIO_DRIVER_NUM,
404 components::gpio_component_helper!(
405 nrf52840::gpio::GPIOPin,
406 40 => &nrf52840_peripherals.gpio_port[LR_DIO9],
407 42 => &nrf52840_peripherals.gpio_port[RADIO_RESET_PIN],
408 43 => &nrf52840_peripherals.gpio_port[RADIO_BUSY_PIN],
409 ),
410 )
411 .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin));
412
413 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
418 .finalize(components::process_printer_text_component_static!());
419 PROCESS_PRINTER = Some(process_printer);
420
421 let _process_console = components::process_console::ProcessConsoleComponent::new(
422 board_kernel,
423 uart_mux,
424 mux_alarm,
425 process_printer,
426 Some(cortexm4::support::reset),
427 )
428 .finalize(components::process_console_component_static!(
429 nrf52840::rtc::Rtc
430 ));
431
432 let rng = components::rng::RngComponent::new(
437 board_kernel,
438 capsules_core::rng::DRIVER_NUM,
439 &base_peripherals.trng,
440 )
441 .finalize(components::rng_component_static!(nrf52840::trng::Trng));
442
443 let nonvolatile_storage = components::nonvolatile_storage::NonvolatileStorageComponent::new(
448 board_kernel,
449 capsules_extra::nonvolatile_storage_driver::DRIVER_NUM,
450 &base_peripherals.nvmc,
451 0xFC000, 4096 * 4, 0, 0,
455 )
456 .finalize(components::nonvolatile_storage_component_static!(
457 nrf52840::nvmc::Nvmc
458 ));
459
460 nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
467
468 let scheduler = components::sched::round_robin::RoundRobinComponent::new(&*addr_of!(PROCESSES))
469 .finalize(components::round_robin_component_static!(NUM_PROCS));
470
471 let platform = Platform {
472 console,
473 led,
474 gpio,
475 rng,
476 alarm,
477 nonvolatile_storage,
478 ipc: kernel::ipc::IPC::new(
479 board_kernel,
480 kernel::ipc::DRIVER_NUM,
481 &memory_allocation_capability,
482 ),
483 scheduler,
484 systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
485 temperature,
486 humidity,
487 lr1110_spi,
488 lr1110_gpio,
489 };
490
491 let chip = static_init!(
492 nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
493 nrf52840::chip::NRF52::new(nrf52840_peripherals)
494 );
495 CHIP = Some(chip);
496
497 debug!("Initialization complete. Entering main loop.");
506 let _ = _process_console.start();
507
508 extern "C" {
514 static _sapps: u8;
516 static _eapps: u8;
518 static mut _sappmem: u8;
520 static _eappmem: u8;
522 }
523
524 kernel::process::load_processes(
525 board_kernel,
526 chip,
527 core::slice::from_raw_parts(
528 core::ptr::addr_of!(_sapps),
529 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
530 ),
531 core::slice::from_raw_parts_mut(
532 core::ptr::addr_of_mut!(_sappmem),
533 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
534 ),
535 &mut *addr_of_mut!(PROCESSES),
536 &FAULT_RESPONSE,
537 &process_management_capability,
538 )
539 .unwrap_or_else(|err| {
540 debug!("Error loading processes!");
541 debug!("{:?}", err);
542 });
543
544 (board_kernel, platform, chip)
545}
546
547#[no_mangle]
549pub unsafe fn main() {
550 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
551
552 let (board_kernel, platform, chip) = start();
553 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
554}