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