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
134#[no_mangle]
136#[link_section = ".stack_buffer"]
137static 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 processes = components::process_array::ProcessArrayComponent::new()
259 .finalize(components::process_array_component_static!(NUM_PROCS));
260 PROCESSES = Some(processes);
261
262 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
264
265 let gpio = components::gpio::GpioComponent::new(
266 board_kernel,
267 capsules_core::gpio::DRIVER_NUM,
268 components::gpio_component_helper!(
269 nrf52832::gpio::GPIOPin,
270 0 => &nrf52832_peripherals.gpio_port[Pin::P0_03],
272 1 => &nrf52832_peripherals.gpio_port[Pin::P0_04],
273 2 => &nrf52832_peripherals.gpio_port[Pin::P0_28],
274 3 => &nrf52832_peripherals.gpio_port[Pin::P0_29],
275 4 => &nrf52832_peripherals.gpio_port[Pin::P0_30],
276 5 => &nrf52832_peripherals.gpio_port[Pin::P0_31],
277 6 => &nrf52832_peripherals.gpio_port[Pin::P0_12],
279 7 => &nrf52832_peripherals.gpio_port[Pin::P0_11],
280 8 => &nrf52832_peripherals.gpio_port[Pin::P0_27],
282 9 => &nrf52832_peripherals.gpio_port[Pin::P0_26],
283 10 => &nrf52832_peripherals.gpio_port[Pin::P0_02],
284 11 => &nrf52832_peripherals.gpio_port[Pin::P0_25]
285 ),
286 )
287 .finalize(components::gpio_component_static!(nrf52832::gpio::GPIOPin));
288
289 let button = components::button::ButtonComponent::new(
290 board_kernel,
291 capsules_core::button::DRIVER_NUM,
292 components::button_component_helper!(
293 nrf52832::gpio::GPIOPin,
294 (
295 &nrf52832_peripherals.gpio_port[BUTTON1_PIN],
296 kernel::hil::gpio::ActivationMode::ActiveLow,
297 kernel::hil::gpio::FloatingState::PullUp
298 ), (
300 &nrf52832_peripherals.gpio_port[BUTTON2_PIN],
301 kernel::hil::gpio::ActivationMode::ActiveLow,
302 kernel::hil::gpio::FloatingState::PullUp
303 ), (
305 &nrf52832_peripherals.gpio_port[BUTTON3_PIN],
306 kernel::hil::gpio::ActivationMode::ActiveLow,
307 kernel::hil::gpio::FloatingState::PullUp
308 ), (
310 &nrf52832_peripherals.gpio_port[BUTTON4_PIN],
311 kernel::hil::gpio::ActivationMode::ActiveLow,
312 kernel::hil::gpio::FloatingState::PullUp
313 ) ),
315 )
316 .finalize(components::button_component_static!(
317 nrf52832::gpio::GPIOPin
318 ));
319
320 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
321 LedLow<'static, nrf52832::gpio::GPIOPin>,
322 LedLow::new(&nrf52832_peripherals.gpio_port[LED1_PIN]),
323 LedLow::new(&nrf52832_peripherals.gpio_port[LED2_PIN]),
324 LedLow::new(&nrf52832_peripherals.gpio_port[LED3_PIN]),
325 LedLow::new(&nrf52832_peripherals.gpio_port[LED4_PIN]),
326 ));
327
328 let chip = static_init!(
329 nrf52832::chip::NRF52<Nrf52832DefaultPeripherals>,
330 nrf52832::chip::NRF52::new(nrf52832_peripherals)
331 );
332 CHIP = Some(chip);
333
334 nrf52_components::startup::NrfStartupComponent::new(
335 false,
336 BUTTON_RST_PIN,
337 nrf52832::uicr::Regulator0Output::DEFAULT,
338 &base_peripherals.nvmc,
339 )
340 .finalize(());
341
342 let process_management_capability =
345 create_capability!(capabilities::ProcessManagementCapability);
346 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
347
348 let gpio_port = &nrf52832_peripherals.gpio_port;
349 kernel::debug::assign_gpios(
351 Some(&gpio_port[LED1_PIN]),
352 Some(&gpio_port[LED2_PIN]),
353 Some(&gpio_port[LED3_PIN]),
354 );
355
356 let rtc = &base_peripherals.rtc;
357 let _ = rtc.start();
358 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
359 .finalize(components::alarm_mux_component_static!(nrf52832::rtc::Rtc));
360 let alarm = components::alarm::AlarmDriverComponent::new(
361 board_kernel,
362 capsules_core::alarm::DRIVER_NUM,
363 mux_alarm,
364 )
365 .finalize(components::alarm_component_static!(nrf52832::rtc::Rtc));
366 let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
367 let channel = nrf52_components::UartChannelComponent::new(
368 uart_channel,
369 mux_alarm,
370 &base_peripherals.uarte0,
371 )
372 .finalize(nrf52_components::uart_channel_component_static!(
373 nrf52832::rtc::Rtc
374 ));
375
376 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
377 .finalize(components::process_printer_text_component_static!());
378 PROCESS_PRINTER = Some(process_printer);
379
380 let uart_mux = components::console::UartMuxComponent::new(channel, 115200)
382 .finalize(components::uart_mux_component_static!());
383
384 let pconsole = components::process_console::ProcessConsoleComponent::new(
385 board_kernel,
386 uart_mux,
387 mux_alarm,
388 process_printer,
389 Some(cortexm4::support::reset),
390 )
391 .finalize(components::process_console_component_static!(Rtc<'static>));
392
393 let console = components::console::ConsoleComponent::new(
395 board_kernel,
396 capsules_core::console::DRIVER_NUM,
397 uart_mux,
398 )
399 .finalize(components::console_component_static!());
400 components::debug_writer::DebugWriterComponent::new(
402 uart_mux,
403 create_capability!(capabilities::SetDebugWriterCapability),
404 )
405 .finalize(components::debug_writer_component_static!());
406
407 let ble_radio = components::ble::BLEComponent::new(
408 board_kernel,
409 capsules_extra::ble_advertising_driver::DRIVER_NUM,
410 &base_peripherals.ble_radio,
411 mux_alarm,
412 )
413 .finalize(components::ble_component_static!(
414 nrf52832::rtc::Rtc,
415 nrf52832::ble_radio::Radio
416 ));
417
418 let temp = components::temperature::TemperatureComponent::new(
419 board_kernel,
420 capsules_extra::temperature::DRIVER_NUM,
421 &base_peripherals.temp,
422 )
423 .finalize(components::temperature_component_static!(
424 nrf52832::temperature::Temp
425 ));
426
427 let rng = components::rng::RngComponent::new(
428 board_kernel,
429 capsules_core::rng::DRIVER_NUM,
430 &base_peripherals.trng,
431 )
432 .finalize(components::rng_component_static!(nrf52832::trng::Trng));
433
434 let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
437 &base_peripherals.acomp,
438 components::analog_comparator_component_helper!(
439 nrf52832::acomp::Channel,
440 &*addr_of!(nrf52832::acomp::CHANNEL_AC0)
441 ),
442 board_kernel,
443 capsules_extra::analog_comparator::DRIVER_NUM,
444 )
445 .finalize(components::analog_comparator_component_static!(
446 nrf52832::acomp::Comparator
447 ));
448
449 nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
450
451 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
452 .finalize(components::round_robin_component_static!(NUM_PROCS));
453
454 let platform = Platform {
455 button,
456 ble_radio,
457 pconsole,
458 console,
459 led,
460 gpio,
461 rng,
462 temp,
463 alarm,
464 analog_comparator,
465 ipc: kernel::ipc::IPC::new(
466 board_kernel,
467 kernel::ipc::DRIVER_NUM,
468 &memory_allocation_capability,
469 ),
470 scheduler,
471 systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
472 };
473
474 let _ = platform.pconsole.start();
475 debug!("Initialization complete. Entering main loop\r");
476 debug!("{}", &*addr_of!(nrf52832::ficr::FICR_INSTANCE));
477
478 extern "C" {
480 static _sapps: u8;
482 static _eapps: u8;
484 static mut _sappmem: u8;
486 static _eappmem: u8;
488 }
489
490 kernel::process::load_processes(
491 board_kernel,
492 chip,
493 core::slice::from_raw_parts(
494 core::ptr::addr_of!(_sapps),
495 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
496 ),
497 core::slice::from_raw_parts_mut(
498 core::ptr::addr_of_mut!(_sappmem),
499 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
500 ),
501 &FAULT_RESPONSE,
502 &process_management_capability,
503 )
504 .unwrap_or_else(|err| {
505 debug!("Error loading processes!");
506 debug!("{:?}", err);
507 });
508
509 (board_kernel, platform, chip)
510}
511
512#[no_mangle]
514pub unsafe fn main() {
515 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
516
517 let (board_kernel, platform, chip) = start();
518 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
519}