1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use kernel::capabilities;
14use kernel::component::Component;
15use kernel::hil;
16use kernel::hil::gpio::Configure;
17use kernel::hil::gpio::Output;
18use kernel::hil::led::LedHigh;
19use kernel::hil::spi::SpiMaster;
20use kernel::hil::time::Counter;
21use kernel::platform::{KernelResources, SyscallDriverLookup};
22use kernel::process::ProcessArray;
23use kernel::scheduler::round_robin::RoundRobinSched;
24#[allow(unused_imports)]
25use kernel::{create_capability, debug, debug_gpio, debug_verbose, static_init};
26
27use nrf52840::gpio::Pin;
28use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
29
30const LED_RED_PIN: Pin = Pin::P0_14;
32const LED_GREEN_PIN: Pin = Pin::P0_13;
33
34const BUTTON_RST_PIN: Pin = Pin::P0_18;
35
36const GPIO_D2: Pin = Pin::P0_17;
37const GPIO_D3: Pin = Pin::P0_16;
38const GPIO_D4: Pin = Pin::P0_15;
39const GPIO_D5: Pin = Pin::P1_09;
40const GPIO_D6: Pin = Pin::P1_04;
41const GPIO_D7: Pin = Pin::P1_03;
42
43const UART_TX_PIN: Pin = Pin::P0_24;
44const UART_RX_PIN: Pin = Pin::P0_22;
45
46const I2C_SDA_PIN: Pin = Pin::P0_27;
48const I2C_SCL_PIN: Pin = Pin::P0_26;
49
50const SPI_CS_PIN: Pin = Pin::P1_12;
52const SPI_SCK_PIN: Pin = Pin::P1_13;
53const SPI_MOSI_PIN: Pin = Pin::P1_14;
54const SPI_MISO_PIN: Pin = Pin::P1_15;
55const RADIO_BUSY_PIN: Pin = Pin::P1_11;
56const RADIO_RESET_PIN: Pin = Pin::P1_10;
57
58const LR_DIO9: Pin = Pin::P1_08;
59
60const I2C_PWR: Pin = Pin::P0_07;
62
63const LORA_SPI_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhySPI as usize;
64const LORA_GPIO_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhyGPIO as usize;
65
66pub mod io;
68
69const FAULT_RESPONSE: capsules_system::process_policies::StopWithDebugFaultPolicy =
72 capsules_system::process_policies::StopWithDebugFaultPolicy {};
73
74const NUM_PROCS: usize = 8;
76
77static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
79static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
80static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
81 None;
82
83kernel::stack_size! {0x1000}
84
85type SHT4xSensor = components::sht4x::SHT4xComponentType<
86 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
87 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, nrf52840::i2c::TWI<'static>>,
88>;
89type TemperatureDriver = components::temperature::TemperatureComponentType<SHT4xSensor>;
90type HumidityDriver = components::humidity::HumidityComponentType<SHT4xSensor>;
91type RngDriver = components::rng::RngComponentType<nrf52840::trng::Trng<'static>>;
92
93type NonvolatileDriver = components::nonvolatile_storage::NonvolatileStorageComponentType;
94
95pub struct Platform {
97 console: &'static capsules_core::console::Console<'static>,
98 gpio: &'static capsules_core::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>,
99 led: &'static capsules_core::led::LedDriver<
100 'static,
101 LedHigh<'static, nrf52::gpio::GPIOPin<'static>>,
102 2,
103 >,
104 rng: &'static RngDriver,
105 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
106 nonvolatile_storage: &'static NonvolatileDriver,
107 alarm: &'static capsules_core::alarm::AlarmDriver<
108 'static,
109 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
110 'static,
111 nrf52::rtc::Rtc<'static>,
112 >,
113 >,
114 temperature: &'static TemperatureDriver,
115 humidity: &'static HumidityDriver,
116 lr1110_gpio: &'static capsules_core::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
117 lr1110_spi: &'static capsules_core::spi_controller::Spi<
118 'static,
119 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
120 'static,
121 nrf52840::spi::SPIM<'static>,
122 >,
123 >,
124 scheduler: &'static RoundRobinSched<'static>,
125 systick: cortexm4::systick::SysTick,
126}
127
128impl SyscallDriverLookup for Platform {
129 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
130 where
131 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
132 {
133 match driver_num {
134 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
135 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
136 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
137 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
138 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
139 capsules_extra::nonvolatile_storage_driver::DRIVER_NUM => {
140 f(Some(self.nonvolatile_storage))
141 }
142 LORA_SPI_DRIVER_NUM => f(Some(self.lr1110_spi)),
143 LORA_GPIO_DRIVER_NUM => f(Some(self.lr1110_gpio)),
144 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
145 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
146 capsules_extra::humidity::DRIVER_NUM => f(Some(self.humidity)),
147 _ => f(None),
148 }
149 }
150}
151
152impl KernelResources<nrf52::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
153 for Platform
154{
155 type SyscallDriverLookup = Self;
156 type SyscallFilter = ();
157 type ProcessFault = ();
158 type Scheduler = RoundRobinSched<'static>;
159 type SchedulerTimer = cortexm4::systick::SysTick;
160 type WatchDog = ();
161 type ContextSwitchCallback = ();
162
163 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
164 self
165 }
166 fn syscall_filter(&self) -> &Self::SyscallFilter {
167 &()
168 }
169 fn process_fault(&self) -> &Self::ProcessFault {
170 &()
171 }
172 fn scheduler(&self) -> &Self::Scheduler {
173 self.scheduler
174 }
175 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
176 &self.systick
177 }
178 fn watchdog(&self) -> &Self::WatchDog {
179 &()
180 }
181 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
182 &()
183 }
184}
185
186#[inline(never)]
190pub unsafe fn start() -> (
191 &'static kernel::Kernel,
192 Platform,
193 &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>,
194) {
195 nrf52840::init();
196
197 let ieee802154_ack_buf = static_init!(
198 [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
199 [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
200 );
201
202 let nrf52840_peripherals = static_init!(
204 Nrf52840DefaultPeripherals,
205 Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
206 );
207
208 nrf52840_peripherals.init();
210 let base_peripherals = &nrf52840_peripherals.nrf52;
211
212 let processes = components::process_array::ProcessArrayComponent::new()
214 .finalize(components::process_array_component_static!(NUM_PROCS));
215 PROCESSES = Some(processes);
216
217 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
219
220 nrf52_components::startup::NrfStartupComponent::new(
221 false,
222 BUTTON_RST_PIN,
223 nrf52840::uicr::Regulator0Output::DEFAULT,
224 &base_peripherals.nvmc,
225 )
226 .finalize(());
227
228 let process_management_capability =
235 create_capability!(capabilities::ProcessManagementCapability);
236 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
237
238 kernel::debug::assign_gpios(
246 Some(&nrf52840_peripherals.gpio_port[LED_GREEN_PIN]),
247 Some(&nrf52840_peripherals.gpio_port[LED_RED_PIN]),
248 None,
249 );
250
251 let gpio = components::gpio::GpioComponent::new(
256 board_kernel,
257 capsules_core::gpio::DRIVER_NUM,
258 components::gpio_component_helper!(
259 nrf52840::gpio::GPIOPin,
260 2 => &nrf52840_peripherals.gpio_port[GPIO_D2],
261 3 => &nrf52840_peripherals.gpio_port[GPIO_D3],
262 4 => &nrf52840_peripherals.gpio_port[GPIO_D4],
263 5 => &nrf52840_peripherals.gpio_port[GPIO_D5],
264 6 => &nrf52840_peripherals.gpio_port[GPIO_D6],
265 7 => &nrf52840_peripherals.gpio_port[GPIO_D7],
266 ),
267 )
268 .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin));
269
270 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
275 LedHigh<'static, nrf52840::gpio::GPIOPin>,
276 LedHigh::new(&nrf52840_peripherals.gpio_port[LED_GREEN_PIN]),
277 LedHigh::new(&nrf52840_peripherals.gpio_port[LED_RED_PIN]),
278 ));
279
280 let rtc = &base_peripherals.rtc;
285 let _ = rtc.start();
286
287 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
288 .finalize(components::alarm_mux_component_static!(nrf52::rtc::Rtc));
289 let alarm = components::alarm::AlarmDriverComponent::new(
290 board_kernel,
291 capsules_core::alarm::DRIVER_NUM,
292 mux_alarm,
293 )
294 .finalize(components::alarm_component_static!(nrf52::rtc::Rtc));
295
296 base_peripherals.uarte0.initialize(
301 nrf52::pinmux::Pinmux::new(UART_TX_PIN as u32),
302 nrf52::pinmux::Pinmux::new(UART_RX_PIN as u32),
303 None,
304 None,
305 );
306
307 let uart_mux = components::console::UartMuxComponent::new(&base_peripherals.uarte0, 115200)
309 .finalize(components::uart_mux_component_static!());
310
311 let console = components::console::ConsoleComponent::new(
313 board_kernel,
314 capsules_core::console::DRIVER_NUM,
315 uart_mux,
316 )
317 .finalize(components::console_component_static!());
318
319 components::debug_writer::DebugWriterComponent::new(
321 uart_mux,
322 create_capability!(capabilities::SetDebugWriterCapability),
323 )
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(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 &FAULT_RESPONSE,
536 &process_management_capability,
537 )
538 .unwrap_or_else(|err| {
539 debug!("Error loading processes!");
540 debug!("{:?}", err);
541 });
542
543 (board_kernel, platform, chip)
544}
545
546#[no_mangle]
548pub unsafe fn main() {
549 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
550
551 let (board_kernel, platform, chip) = start();
552 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
553}