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