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