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
128static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
130static mut CHIP: Option<&'static nrf52832::chip::NRF52<Nrf52832DefaultPeripherals>> = None;
131static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
132 None;
133
134kernel::stack_size! {0x1000}
135
136type TemperatureDriver =
137 components::temperature::TemperatureComponentType<nrf52832::temperature::Temp<'static>>;
138type RngDriver = components::rng::RngComponentType<nrf52832::trng::Trng<'static>>;
139
140pub struct Platform {
142 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
143 'static,
144 nrf52832::ble_radio::Radio<'static>,
145 VirtualMuxAlarm<'static, Rtc<'static>>,
146 >,
147 button: &'static capsules_core::button::Button<'static, nrf52832::gpio::GPIOPin<'static>>,
148 pconsole: &'static capsules_core::process_console::ProcessConsole<
149 'static,
150 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
151 VirtualMuxAlarm<'static, Rtc<'static>>,
152 components::process_console::Capability,
153 >,
154 console: &'static capsules_core::console::Console<'static>,
155 gpio: &'static capsules_core::gpio::GPIO<'static, nrf52832::gpio::GPIOPin<'static>>,
156 led: &'static capsules_core::led::LedDriver<
157 'static,
158 LedLow<'static, nrf52832::gpio::GPIOPin<'static>>,
159 4,
160 >,
161 rng: &'static RngDriver,
162 temp: &'static TemperatureDriver,
163 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
164 analog_comparator: &'static capsules_extra::analog_comparator::AnalogComparator<
165 'static,
166 nrf52832::acomp::Comparator<'static>,
167 >,
168 alarm: &'static capsules_core::alarm::AlarmDriver<
169 'static,
170 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
171 'static,
172 nrf52832::rtc::Rtc<'static>,
173 >,
174 >,
175 scheduler: &'static RoundRobinSched<'static>,
176 systick: cortexm4::systick::SysTick,
177}
178
179impl SyscallDriverLookup for Platform {
180 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
181 where
182 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
183 {
184 match driver_num {
185 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
186 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
187 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
188 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
189 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
190 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
191 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
192 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temp)),
193 capsules_extra::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
194 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
195 _ => f(None),
196 }
197 }
198}
199
200impl KernelResources<nrf52832::chip::NRF52<'static, Nrf52832DefaultPeripherals<'static>>>
201 for Platform
202{
203 type SyscallDriverLookup = Self;
204 type SyscallFilter = ();
205 type ProcessFault = ();
206 type Scheduler = RoundRobinSched<'static>;
207 type SchedulerTimer = cortexm4::systick::SysTick;
208 type WatchDog = ();
209 type ContextSwitchCallback = ();
210
211 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
212 self
213 }
214 fn syscall_filter(&self) -> &Self::SyscallFilter {
215 &()
216 }
217 fn process_fault(&self) -> &Self::ProcessFault {
218 &()
219 }
220 fn scheduler(&self) -> &Self::Scheduler {
221 self.scheduler
222 }
223 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
224 &self.systick
225 }
226 fn watchdog(&self) -> &Self::WatchDog {
227 &()
228 }
229 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
230 &()
231 }
232}
233
234#[inline(never)]
238pub unsafe fn start() -> (
239 &'static kernel::Kernel,
240 Platform,
241 &'static nrf52832::chip::NRF52<'static, Nrf52832DefaultPeripherals<'static>>,
242) {
243 nrf52832::init();
244
245 let nrf52832_peripherals = static_init!(
246 Nrf52832DefaultPeripherals,
247 Nrf52832DefaultPeripherals::new()
248 );
249
250 nrf52832_peripherals.init();
252 let base_peripherals = &nrf52832_peripherals.nrf52;
253
254 let processes = components::process_array::ProcessArrayComponent::new()
256 .finalize(components::process_array_component_static!(NUM_PROCS));
257 PROCESSES = Some(processes);
258
259 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
261
262 let gpio = components::gpio::GpioComponent::new(
263 board_kernel,
264 capsules_core::gpio::DRIVER_NUM,
265 components::gpio_component_helper!(
266 nrf52832::gpio::GPIOPin,
267 0 => &nrf52832_peripherals.gpio_port[Pin::P0_03],
269 1 => &nrf52832_peripherals.gpio_port[Pin::P0_04],
270 2 => &nrf52832_peripherals.gpio_port[Pin::P0_28],
271 3 => &nrf52832_peripherals.gpio_port[Pin::P0_29],
272 4 => &nrf52832_peripherals.gpio_port[Pin::P0_30],
273 5 => &nrf52832_peripherals.gpio_port[Pin::P0_31],
274 6 => &nrf52832_peripherals.gpio_port[Pin::P0_12],
276 7 => &nrf52832_peripherals.gpio_port[Pin::P0_11],
277 8 => &nrf52832_peripherals.gpio_port[Pin::P0_27],
279 9 => &nrf52832_peripherals.gpio_port[Pin::P0_26],
280 10 => &nrf52832_peripherals.gpio_port[Pin::P0_02],
281 11 => &nrf52832_peripherals.gpio_port[Pin::P0_25]
282 ),
283 )
284 .finalize(components::gpio_component_static!(nrf52832::gpio::GPIOPin));
285
286 let button = components::button::ButtonComponent::new(
287 board_kernel,
288 capsules_core::button::DRIVER_NUM,
289 components::button_component_helper!(
290 nrf52832::gpio::GPIOPin,
291 (
292 &nrf52832_peripherals.gpio_port[BUTTON1_PIN],
293 kernel::hil::gpio::ActivationMode::ActiveLow,
294 kernel::hil::gpio::FloatingState::PullUp
295 ), (
297 &nrf52832_peripherals.gpio_port[BUTTON2_PIN],
298 kernel::hil::gpio::ActivationMode::ActiveLow,
299 kernel::hil::gpio::FloatingState::PullUp
300 ), (
302 &nrf52832_peripherals.gpio_port[BUTTON3_PIN],
303 kernel::hil::gpio::ActivationMode::ActiveLow,
304 kernel::hil::gpio::FloatingState::PullUp
305 ), (
307 &nrf52832_peripherals.gpio_port[BUTTON4_PIN],
308 kernel::hil::gpio::ActivationMode::ActiveLow,
309 kernel::hil::gpio::FloatingState::PullUp
310 ) ),
312 )
313 .finalize(components::button_component_static!(
314 nrf52832::gpio::GPIOPin
315 ));
316
317 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
318 LedLow<'static, nrf52832::gpio::GPIOPin>,
319 LedLow::new(&nrf52832_peripherals.gpio_port[LED1_PIN]),
320 LedLow::new(&nrf52832_peripherals.gpio_port[LED2_PIN]),
321 LedLow::new(&nrf52832_peripherals.gpio_port[LED3_PIN]),
322 LedLow::new(&nrf52832_peripherals.gpio_port[LED4_PIN]),
323 ));
324
325 let chip = static_init!(
326 nrf52832::chip::NRF52<Nrf52832DefaultPeripherals>,
327 nrf52832::chip::NRF52::new(nrf52832_peripherals)
328 );
329 CHIP = Some(chip);
330
331 nrf52_components::startup::NrfStartupComponent::new(
332 false,
333 BUTTON_RST_PIN,
334 nrf52832::uicr::Regulator0Output::DEFAULT,
335 &base_peripherals.nvmc,
336 )
337 .finalize(());
338
339 let process_management_capability =
342 create_capability!(capabilities::ProcessManagementCapability);
343 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
344
345 let gpio_port = &nrf52832_peripherals.gpio_port;
346 kernel::debug::assign_gpios(
348 Some(&gpio_port[LED1_PIN]),
349 Some(&gpio_port[LED2_PIN]),
350 Some(&gpio_port[LED3_PIN]),
351 );
352
353 let rtc = &base_peripherals.rtc;
354 let _ = rtc.start();
355 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
356 .finalize(components::alarm_mux_component_static!(nrf52832::rtc::Rtc));
357 let alarm = components::alarm::AlarmDriverComponent::new(
358 board_kernel,
359 capsules_core::alarm::DRIVER_NUM,
360 mux_alarm,
361 )
362 .finalize(components::alarm_component_static!(nrf52832::rtc::Rtc));
363 let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
364 let channel = nrf52_components::UartChannelComponent::new(
365 uart_channel,
366 mux_alarm,
367 &base_peripherals.uarte0,
368 )
369 .finalize(nrf52_components::uart_channel_component_static!(
370 nrf52832::rtc::Rtc
371 ));
372
373 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
374 .finalize(components::process_printer_text_component_static!());
375 PROCESS_PRINTER = Some(process_printer);
376
377 let uart_mux = components::console::UartMuxComponent::new(channel, 115200)
379 .finalize(components::uart_mux_component_static!());
380
381 let pconsole = components::process_console::ProcessConsoleComponent::new(
382 board_kernel,
383 uart_mux,
384 mux_alarm,
385 process_printer,
386 Some(cortexm4::support::reset),
387 )
388 .finalize(components::process_console_component_static!(Rtc<'static>));
389
390 let console = components::console::ConsoleComponent::new(
392 board_kernel,
393 capsules_core::console::DRIVER_NUM,
394 uart_mux,
395 )
396 .finalize(components::console_component_static!());
397 components::debug_writer::DebugWriterComponent::new(
399 uart_mux,
400 create_capability!(capabilities::SetDebugWriterCapability),
401 )
402 .finalize(components::debug_writer_component_static!());
403
404 let ble_radio = components::ble::BLEComponent::new(
405 board_kernel,
406 capsules_extra::ble_advertising_driver::DRIVER_NUM,
407 &base_peripherals.ble_radio,
408 mux_alarm,
409 )
410 .finalize(components::ble_component_static!(
411 nrf52832::rtc::Rtc,
412 nrf52832::ble_radio::Radio
413 ));
414
415 let temp = components::temperature::TemperatureComponent::new(
416 board_kernel,
417 capsules_extra::temperature::DRIVER_NUM,
418 &base_peripherals.temp,
419 )
420 .finalize(components::temperature_component_static!(
421 nrf52832::temperature::Temp
422 ));
423
424 let rng = components::rng::RngComponent::new(
425 board_kernel,
426 capsules_core::rng::DRIVER_NUM,
427 &base_peripherals.trng,
428 )
429 .finalize(components::rng_component_static!(nrf52832::trng::Trng));
430
431 let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
434 &base_peripherals.acomp,
435 components::analog_comparator_component_helper!(
436 nrf52832::acomp::Channel,
437 &*addr_of!(nrf52832::acomp::CHANNEL_AC0)
438 ),
439 board_kernel,
440 capsules_extra::analog_comparator::DRIVER_NUM,
441 )
442 .finalize(components::analog_comparator_component_static!(
443 nrf52832::acomp::Comparator
444 ));
445
446 nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
447
448 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
449 .finalize(components::round_robin_component_static!(NUM_PROCS));
450
451 let platform = Platform {
452 button,
453 ble_radio,
454 pconsole,
455 console,
456 led,
457 gpio,
458 rng,
459 temp,
460 alarm,
461 analog_comparator,
462 ipc: kernel::ipc::IPC::new(
463 board_kernel,
464 kernel::ipc::DRIVER_NUM,
465 &memory_allocation_capability,
466 ),
467 scheduler,
468 systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
469 };
470
471 let _ = platform.pconsole.start();
472 debug!("Initialization complete. Entering main loop\r");
473 debug!("{}", &*addr_of!(nrf52832::ficr::FICR_INSTANCE));
474
475 extern "C" {
477 static _sapps: u8;
479 static _eapps: u8;
481 static mut _sappmem: u8;
483 static _eappmem: u8;
485 }
486
487 kernel::process::load_processes(
488 board_kernel,
489 chip,
490 core::slice::from_raw_parts(
491 core::ptr::addr_of!(_sapps),
492 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
493 ),
494 core::slice::from_raw_parts_mut(
495 core::ptr::addr_of_mut!(_sappmem),
496 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
497 ),
498 &FAULT_RESPONSE,
499 &process_management_capability,
500 )
501 .unwrap_or_else(|err| {
502 debug!("Error loading processes!");
503 debug!("{:?}", err);
504 });
505
506 (board_kernel, platform, chip)
507}
508
509#[no_mangle]
511pub unsafe fn main() {
512 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
513
514 let (board_kernel, platform, chip) = start();
515 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
516}