1#![no_std]
69#![no_main]
70#![deny(missing_docs)]
71
72use core::ptr::addr_of;
73
74use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
75use kernel::component::Component;
76use kernel::hil::led::LedLow;
77use kernel::hil::time::Counter;
78use kernel::platform::{KernelResources, SyscallDriverLookup};
79use kernel::process::ProcessArray;
80use kernel::scheduler::round_robin::RoundRobinSched;
81#[allow(unused_imports)]
82use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
83use nrf52832::gpio::Pin;
84use nrf52832::interrupt_service::Nrf52832DefaultPeripherals;
85use nrf52832::rtc::Rtc;
86use nrf52_components::{UartChannel, UartPins};
87
88const LED1_PIN: Pin = Pin::P0_17;
90const LED2_PIN: Pin = Pin::P0_18;
91const LED3_PIN: Pin = Pin::P0_19;
92const LED4_PIN: Pin = Pin::P0_20;
93
94const BUTTON1_PIN: Pin = Pin::P0_13;
96const BUTTON2_PIN: Pin = Pin::P0_14;
97const BUTTON3_PIN: Pin = Pin::P0_15;
98const BUTTON4_PIN: Pin = Pin::P0_16;
99const BUTTON_RST_PIN: Pin = Pin::P0_21;
100
101const UART_RTS: Option<Pin> = Some(Pin::P0_05);
102const UART_TXD: Pin = Pin::P0_06;
103const UART_CTS: Option<Pin> = Some(Pin::P0_07);
104const UART_RXD: Pin = Pin::P0_08;
105
106const _SPI_MOSI: Pin = Pin::P0_22;
108const _SPI_MISO: Pin = Pin::P0_23;
109const _SPI_CLK: Pin = Pin::P0_24;
110
111pub mod io;
113
114#[allow(dead_code)]
118mod tests;
119
120const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
123 capsules_system::process_policies::PanicFaultPolicy {};
124
125const NUM_PROCS: usize = 4;
127
128type ChipHw = nrf52832::chip::NRF52<'static, Nrf52832DefaultPeripherals<'static>>;
129
130static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
132static mut CHIP: Option<&'static nrf52832::chip::NRF52<Nrf52832DefaultPeripherals>> = None;
133static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
134 None;
135
136kernel::stack_size! {0x1000}
137
138type TemperatureDriver =
139 components::temperature::TemperatureComponentType<nrf52832::temperature::Temp<'static>>;
140type RngDriver = components::rng::RngComponentType<nrf52832::trng::Trng<'static>>;
141
142pub struct Platform {
144 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
145 'static,
146 nrf52832::ble_radio::Radio<'static>,
147 VirtualMuxAlarm<'static, Rtc<'static>>,
148 >,
149 button: &'static capsules_core::button::Button<'static, nrf52832::gpio::GPIOPin<'static>>,
150 pconsole: &'static capsules_core::process_console::ProcessConsole<
151 'static,
152 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
153 VirtualMuxAlarm<'static, Rtc<'static>>,
154 components::process_console::Capability,
155 >,
156 console: &'static capsules_core::console::Console<'static>,
157 gpio: &'static capsules_core::gpio::GPIO<'static, nrf52832::gpio::GPIOPin<'static>>,
158 led: &'static capsules_core::led::LedDriver<
159 'static,
160 LedLow<'static, nrf52832::gpio::GPIOPin<'static>>,
161 4,
162 >,
163 rng: &'static RngDriver,
164 temp: &'static TemperatureDriver,
165 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
166 analog_comparator: &'static capsules_extra::analog_comparator::AnalogComparator<
167 'static,
168 nrf52832::acomp::Comparator<'static>,
169 >,
170 alarm: &'static capsules_core::alarm::AlarmDriver<
171 'static,
172 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
173 'static,
174 nrf52832::rtc::Rtc<'static>,
175 >,
176 >,
177 scheduler: &'static RoundRobinSched<'static>,
178 systick: cortexm4::systick::SysTick,
179}
180
181impl SyscallDriverLookup for Platform {
182 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
183 where
184 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
185 {
186 match driver_num {
187 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
188 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
189 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
190 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
191 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
192 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
193 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
194 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temp)),
195 capsules_extra::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
196 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
197 _ => f(None),
198 }
199 }
200}
201
202impl KernelResources<nrf52832::chip::NRF52<'static, Nrf52832DefaultPeripherals<'static>>>
203 for Platform
204{
205 type SyscallDriverLookup = Self;
206 type SyscallFilter = ();
207 type ProcessFault = ();
208 type Scheduler = RoundRobinSched<'static>;
209 type SchedulerTimer = cortexm4::systick::SysTick;
210 type WatchDog = ();
211 type ContextSwitchCallback = ();
212
213 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
214 self
215 }
216 fn syscall_filter(&self) -> &Self::SyscallFilter {
217 &()
218 }
219 fn process_fault(&self) -> &Self::ProcessFault {
220 &()
221 }
222 fn scheduler(&self) -> &Self::Scheduler {
223 self.scheduler
224 }
225 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
226 &self.systick
227 }
228 fn watchdog(&self) -> &Self::WatchDog {
229 &()
230 }
231 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
232 &()
233 }
234}
235
236#[inline(never)]
240pub unsafe fn start() -> (
241 &'static kernel::Kernel,
242 Platform,
243 &'static nrf52832::chip::NRF52<'static, Nrf52832DefaultPeripherals<'static>>,
244) {
245 nrf52832::init();
246
247 kernel::deferred_call::initialize_deferred_call_state::<
249 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
250 >();
251
252 let nrf52832_peripherals = static_init!(
253 Nrf52832DefaultPeripherals,
254 Nrf52832DefaultPeripherals::new()
255 );
256
257 nrf52832_peripherals.init();
259 let base_peripherals = &nrf52832_peripherals.nrf52;
260
261 let processes = components::process_array::ProcessArrayComponent::new()
263 .finalize(components::process_array_component_static!(NUM_PROCS));
264 PROCESSES = Some(processes);
265
266 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
268
269 let gpio = components::gpio::GpioComponent::new(
270 board_kernel,
271 capsules_core::gpio::DRIVER_NUM,
272 components::gpio_component_helper!(
273 nrf52832::gpio::GPIOPin,
274 0 => &nrf52832_peripherals.gpio_port[Pin::P0_03],
276 1 => &nrf52832_peripherals.gpio_port[Pin::P0_04],
277 2 => &nrf52832_peripherals.gpio_port[Pin::P0_28],
278 3 => &nrf52832_peripherals.gpio_port[Pin::P0_29],
279 4 => &nrf52832_peripherals.gpio_port[Pin::P0_30],
280 5 => &nrf52832_peripherals.gpio_port[Pin::P0_31],
281 6 => &nrf52832_peripherals.gpio_port[Pin::P0_12],
283 7 => &nrf52832_peripherals.gpio_port[Pin::P0_11],
284 8 => &nrf52832_peripherals.gpio_port[Pin::P0_27],
286 9 => &nrf52832_peripherals.gpio_port[Pin::P0_26],
287 10 => &nrf52832_peripherals.gpio_port[Pin::P0_02],
288 11 => &nrf52832_peripherals.gpio_port[Pin::P0_25]
289 ),
290 )
291 .finalize(components::gpio_component_static!(nrf52832::gpio::GPIOPin));
292
293 let button = components::button::ButtonComponent::new(
294 board_kernel,
295 capsules_core::button::DRIVER_NUM,
296 components::button_component_helper!(
297 nrf52832::gpio::GPIOPin,
298 (
299 &nrf52832_peripherals.gpio_port[BUTTON1_PIN],
300 kernel::hil::gpio::ActivationMode::ActiveLow,
301 kernel::hil::gpio::FloatingState::PullUp
302 ), (
304 &nrf52832_peripherals.gpio_port[BUTTON2_PIN],
305 kernel::hil::gpio::ActivationMode::ActiveLow,
306 kernel::hil::gpio::FloatingState::PullUp
307 ), (
309 &nrf52832_peripherals.gpio_port[BUTTON3_PIN],
310 kernel::hil::gpio::ActivationMode::ActiveLow,
311 kernel::hil::gpio::FloatingState::PullUp
312 ), (
314 &nrf52832_peripherals.gpio_port[BUTTON4_PIN],
315 kernel::hil::gpio::ActivationMode::ActiveLow,
316 kernel::hil::gpio::FloatingState::PullUp
317 ) ),
319 )
320 .finalize(components::button_component_static!(
321 nrf52832::gpio::GPIOPin
322 ));
323
324 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
325 LedLow<'static, nrf52832::gpio::GPIOPin>,
326 LedLow::new(&nrf52832_peripherals.gpio_port[LED1_PIN]),
327 LedLow::new(&nrf52832_peripherals.gpio_port[LED2_PIN]),
328 LedLow::new(&nrf52832_peripherals.gpio_port[LED3_PIN]),
329 LedLow::new(&nrf52832_peripherals.gpio_port[LED4_PIN]),
330 ));
331
332 let chip = static_init!(
333 nrf52832::chip::NRF52<Nrf52832DefaultPeripherals>,
334 nrf52832::chip::NRF52::new(nrf52832_peripherals)
335 );
336 CHIP = Some(chip);
337
338 nrf52_components::startup::NrfStartupComponent::new(
339 false,
340 BUTTON_RST_PIN,
341 nrf52832::uicr::Regulator0Output::DEFAULT,
342 &base_peripherals.nvmc,
343 )
344 .finalize(());
345
346 let process_management_capability =
349 create_capability!(capabilities::ProcessManagementCapability);
350 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
351
352 let gpio_port = &nrf52832_peripherals.gpio_port;
353 let debug_gpios = static_init!(
355 [&'static dyn kernel::hil::gpio::Pin; 3],
356 [
357 &gpio_port[LED1_PIN],
358 &gpio_port[LED2_PIN],
359 &gpio_port[LED3_PIN]
360 ]
361 );
362 kernel::debug::initialize_debug_gpio::<
363 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
364 >();
365 kernel::debug::assign_gpios(debug_gpios);
366
367 let rtc = &base_peripherals.rtc;
368 let _ = rtc.start();
369 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
370 .finalize(components::alarm_mux_component_static!(nrf52832::rtc::Rtc));
371 let alarm = components::alarm::AlarmDriverComponent::new(
372 board_kernel,
373 capsules_core::alarm::DRIVER_NUM,
374 mux_alarm,
375 )
376 .finalize(components::alarm_component_static!(nrf52832::rtc::Rtc));
377 let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
378 let channel = nrf52_components::UartChannelComponent::new(
379 uart_channel,
380 mux_alarm,
381 &base_peripherals.uarte0,
382 )
383 .finalize(nrf52_components::uart_channel_component_static!(
384 nrf52832::rtc::Rtc
385 ));
386
387 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
388 .finalize(components::process_printer_text_component_static!());
389 PROCESS_PRINTER = Some(process_printer);
390
391 let uart_mux = components::console::UartMuxComponent::new(channel, 115200)
393 .finalize(components::uart_mux_component_static!());
394
395 let pconsole = components::process_console::ProcessConsoleComponent::new(
396 board_kernel,
397 uart_mux,
398 mux_alarm,
399 process_printer,
400 Some(cortexm4::support::reset),
401 )
402 .finalize(components::process_console_component_static!(Rtc<'static>));
403
404 let console = components::console::ConsoleComponent::new(
406 board_kernel,
407 capsules_core::console::DRIVER_NUM,
408 uart_mux,
409 )
410 .finalize(components::console_component_static!());
411 components::debug_writer::DebugWriterComponent::new::<
413 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
414 >(
415 uart_mux,
416 create_capability!(capabilities::SetDebugWriterCapability),
417 )
418 .finalize(components::debug_writer_component_static!());
419
420 let ble_radio = components::ble::BLEComponent::new(
421 board_kernel,
422 capsules_extra::ble_advertising_driver::DRIVER_NUM,
423 &base_peripherals.ble_radio,
424 mux_alarm,
425 )
426 .finalize(components::ble_component_static!(
427 nrf52832::rtc::Rtc,
428 nrf52832::ble_radio::Radio
429 ));
430
431 let temp = components::temperature::TemperatureComponent::new(
432 board_kernel,
433 capsules_extra::temperature::DRIVER_NUM,
434 &base_peripherals.temp,
435 )
436 .finalize(components::temperature_component_static!(
437 nrf52832::temperature::Temp
438 ));
439
440 let rng = components::rng::RngComponent::new(
441 board_kernel,
442 capsules_core::rng::DRIVER_NUM,
443 &base_peripherals.trng,
444 )
445 .finalize(components::rng_component_static!(nrf52832::trng::Trng));
446
447 let analog_comparator_channel = static_init!(
450 nrf52832::acomp::Channel,
451 nrf52832::acomp::Channel::new(nrf52832::acomp::ChannelNumber::AC0)
452 );
453 let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
454 &base_peripherals.acomp,
455 components::analog_comparator_component_helper!(
456 nrf52832::acomp::Channel,
457 analog_comparator_channel,
458 ),
459 board_kernel,
460 capsules_extra::analog_comparator::DRIVER_NUM,
461 )
462 .finalize(components::analog_comparator_component_static!(
463 nrf52832::acomp::Comparator
464 ));
465
466 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 button,
473 ble_radio,
474 pconsole,
475 console,
476 led,
477 gpio,
478 rng,
479 temp,
480 alarm,
481 analog_comparator,
482 ipc: kernel::ipc::IPC::new(
483 board_kernel,
484 kernel::ipc::DRIVER_NUM,
485 &memory_allocation_capability,
486 ),
487 scheduler,
488 systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
489 };
490
491 let _ = platform.pconsole.start();
492 debug!("Initialization complete. Entering main loop\r");
493 debug!("{}", &*addr_of!(nrf52832::ficr::FICR_INSTANCE));
494
495 extern "C" {
497 static _sapps: u8;
499 static _eapps: u8;
501 static mut _sappmem: u8;
503 static _eappmem: u8;
505 }
506
507 kernel::process::load_processes(
508 board_kernel,
509 chip,
510 core::slice::from_raw_parts(
511 core::ptr::addr_of!(_sapps),
512 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
513 ),
514 core::slice::from_raw_parts_mut(
515 core::ptr::addr_of_mut!(_sappmem),
516 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
517 ),
518 &FAULT_RESPONSE,
519 &process_management_capability,
520 )
521 .unwrap_or_else(|err| {
522 debug!("Error loading processes!");
523 debug!("{:?}", err);
524 });
525
526 (board_kernel, platform, chip)
527}
528
529#[no_mangle]
531pub unsafe fn main() {
532 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
533
534 let (board_kernel, platform, chip) = start();
535 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
536}