1#![no_std]
11#![no_main]
12#![deny(missing_docs)]
13
14use capsules_core::i2c_master_slave_driver::I2CMasterSlaveDriver;
15use capsules_core::virtualizers::virtual_aes_ccm::MuxAES128CCM;
16use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
17use kernel::component::Component;
18use kernel::deferred_call::DeferredCallClient;
19use kernel::hil::gpio::Configure;
20use kernel::hil::gpio::FloatingState;
21use kernel::hil::i2c::{I2CMaster, I2CSlave};
22use kernel::hil::led::LedLow;
23use kernel::hil::symmetric_encryption::AES128;
24use kernel::hil::time::Counter;
25use kernel::platform::{KernelResources, SyscallDriverLookup};
26use kernel::process::ProcessArray;
27use kernel::scheduler::round_robin::RoundRobinSched;
28#[allow(unused_imports)]
29use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
30use nrf52840::gpio::Pin;
31use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
32#[allow(unused_imports)]
33use nrf52_components::{self, UartChannel, UartPins};
34
35const LED_USR_PIN: Pin = Pin::P1_12;
37const LED2_R_PIN: Pin = Pin::P0_13;
38const LED2_G_PIN: Pin = Pin::P0_14;
39const LED2_B_PIN: Pin = Pin::P0_15;
40
41const BUTTON_PIN: Pin = Pin::P0_11;
43const BUTTON_RST_PIN: Pin = Pin::P0_18;
44
45const _UART_RTS: Option<Pin> = Some(Pin::P0_30);
47const _UART_CTS: Option<Pin> = Some(Pin::P0_31);
48const UART_TXD: Pin = Pin::P0_06;
49const UART_RXD: Pin = Pin::P0_08;
50
51const _SPI_MOSI: Pin = Pin::P1_13;
53const _SPI_MISO: Pin = Pin::P1_14;
54const _SPI_CLK: Pin = Pin::P1_15;
55
56const I2C_SDA_PIN: Pin = Pin::P0_26;
58const I2C_SCL_PIN: Pin = Pin::P0_27;
59
60const SRC_MAC: u16 = 0xf00f;
63const PAN_ID: u16 = 0xABCD;
64const DEFAULT_EXT_SRC_MAC: [u8; 8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77];
65
66pub mod io;
68
69const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
72    capsules_system::process_policies::PanicFaultPolicy {};
73
74const NUM_PROCS: usize = 8;
76
77static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
79
80type ChipHw = nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>;
81
82static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
84static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
86    None;
87static mut NRF52_POWER: Option<&'static nrf52840::power::Power> = None;
88
89kernel::stack_size! {0x1000}
90
91type TemperatureDriver =
92    components::temperature::TemperatureComponentType<nrf52840::temperature::Temp<'static>>;
93type RngDriver = components::rng::RngComponentType<nrf52840::trng::Trng<'static>>;
94
95type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType<
96    nrf52840::ieee802154_radio::Radio<'static>,
97    nrf52840::aes::AesECB<'static>,
98>;
99
100pub struct Platform {
102    ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
103        'static,
104        nrf52840::ble_radio::Radio<'static>,
105        VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
106    >,
107    ieee802154_radio: &'static Ieee802154Driver,
108    button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
109    console: &'static capsules_core::console::Console<'static>,
110    gpio: &'static capsules_core::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
111    led: &'static capsules_core::led::LedDriver<
112        'static,
113        LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
114        4,
115    >,
116    adc: &'static capsules_core::adc::AdcVirtualized<'static>,
117    rng: &'static RngDriver,
118    temp: &'static TemperatureDriver,
119    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
120    i2c_master_slave: &'static capsules_core::i2c_master_slave_driver::I2CMasterSlaveDriver<
121        'static,
122        nrf52840::i2c::TWI<'static>,
123    >,
124    alarm: &'static capsules_core::alarm::AlarmDriver<
125        'static,
126        capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
127            'static,
128            nrf52840::rtc::Rtc<'static>,
129        >,
130    >,
131    scheduler: &'static RoundRobinSched<'static>,
132    systick: cortexm4::systick::SysTick,
133}
134
135impl SyscallDriverLookup for Platform {
136    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
137    where
138        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
139    {
140        match driver_num {
141            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
142            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
143            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
144            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
145            capsules_core::button::DRIVER_NUM => f(Some(self.button)),
146            capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
147            capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
148            capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
149            capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_radio)),
150            capsules_extra::temperature::DRIVER_NUM => f(Some(self.temp)),
151            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
152            capsules_core::i2c_master_slave_driver::DRIVER_NUM => f(Some(self.i2c_master_slave)),
153            _ => f(None),
154        }
155    }
156}
157
158impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
159    for Platform
160{
161    type SyscallDriverLookup = Self;
162    type SyscallFilter = ();
163    type ProcessFault = ();
164    type Scheduler = RoundRobinSched<'static>;
165    type SchedulerTimer = cortexm4::systick::SysTick;
166    type WatchDog = ();
167    type ContextSwitchCallback = ();
168
169    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
170        self
171    }
172    fn syscall_filter(&self) -> &Self::SyscallFilter {
173        &()
174    }
175    fn process_fault(&self) -> &Self::ProcessFault {
176        &()
177    }
178    fn scheduler(&self) -> &Self::Scheduler {
179        self.scheduler
180    }
181    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
182        &self.systick
183    }
184    fn watchdog(&self) -> &Self::WatchDog {
185        &()
186    }
187    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
188        &()
189    }
190}
191
192#[inline(never)]
196unsafe fn create_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
197    let ieee802154_ack_buf = static_init!(
198        [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
199        [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
200    );
201    let nrf52840_peripherals = static_init!(
203        Nrf52840DefaultPeripherals,
204        Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
205    );
206
207    nrf52840_peripherals
208}
209
210#[inline(never)]
214pub unsafe fn start_particle_boron() -> (
215    &'static kernel::Kernel,
216    Platform,
217    &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>,
218) {
219    nrf52840::init();
220
221    let nrf52840_peripherals = create_peripherals();
222
223    nrf52840_peripherals.init();
225    let base_peripherals = &nrf52840_peripherals.nrf52;
226
227    NRF52_POWER = Some(&base_peripherals.pwr_clk);
230
231    let processes = components::process_array::ProcessArrayComponent::new()
233        .finalize(components::process_array_component_static!(NUM_PROCS));
234    PROCESSES = Some(processes);
235
236    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
238
239    let process_management_capability =
246        create_capability!(capabilities::ProcessManagementCapability);
247    let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
248
249    let gpio_port = &nrf52840_peripherals.gpio_port;
254    kernel::debug::assign_gpios(Some(&gpio_port[LED2_R_PIN]), None, None);
258
259    let uart_channel = UartChannel::Pins(UartPins::new(None, UART_TXD, None, UART_RXD));
260
261    let gpio = components::gpio::GpioComponent::new(
266        board_kernel,
267        capsules_core::gpio::DRIVER_NUM,
268        components::gpio_component_helper!(
269            nrf52840::gpio::GPIOPin,
270            6 => &nrf52840_peripherals.gpio_port[Pin::P1_15],
285            7 => &nrf52840_peripherals.gpio_port[Pin::P1_13],
287            8 => &nrf52840_peripherals.gpio_port[Pin::P1_14],
289            9 => &nrf52840_peripherals.gpio_port[Pin::P0_08],
291            10 => &nrf52840_peripherals.gpio_port[Pin::P0_06],
293            11 => &nrf52840_peripherals.gpio_port[Pin::P1_03],
296            12 => &nrf52840_peripherals.gpio_port[Pin::P1_12],
298            13 => &nrf52840_peripherals.gpio_port[Pin::P1_11],
300            14 => &nrf52840_peripherals.gpio_port[Pin::P1_10],
302            15 => &nrf52840_peripherals.gpio_port[Pin::P1_08],
304            16 => &nrf52840_peripherals.gpio_port[Pin::P1_02],
306            17 => &nrf52840_peripherals.gpio_port[Pin::P0_01],
308            18 => &nrf52840_peripherals.gpio_port[Pin::P0_27],
310            19 => &nrf52840_peripherals.gpio_port[Pin::P0_26],
312        ),
313    )
314    .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin));
315
316    let button = components::button::ButtonComponent::new(
321        board_kernel,
322        capsules_core::button::DRIVER_NUM,
323        components::button_component_helper!(
324            nrf52840::gpio::GPIOPin,
325            (
326                &nrf52840_peripherals.gpio_port[BUTTON_PIN],
327                kernel::hil::gpio::ActivationMode::ActiveLow,
328                kernel::hil::gpio::FloatingState::PullUp
329            )
330        ),
331    )
332    .finalize(components::button_component_static!(
333        nrf52840::gpio::GPIOPin
334    ));
335
336    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
341        LedLow<'static, nrf52840::gpio::GPIOPin>,
342        LedLow::new(&nrf52840_peripherals.gpio_port[LED_USR_PIN]),
343        LedLow::new(&nrf52840_peripherals.gpio_port[LED2_R_PIN]),
344        LedLow::new(&nrf52840_peripherals.gpio_port[LED2_G_PIN]),
345        LedLow::new(&nrf52840_peripherals.gpio_port[LED2_B_PIN]),
346    ));
347
348    nrf52_components::startup::NrfStartupComponent::new(
349        false,
350        BUTTON_RST_PIN,
351        nrf52840::uicr::Regulator0Output::V3_0,
352        &base_peripherals.nvmc,
353    )
354    .finalize(());
355
356    let rtc = &base_peripherals.rtc;
361    let _ = rtc.start();
362    let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
363        .finalize(components::alarm_mux_component_static!(nrf52840::rtc::Rtc));
364    let alarm = components::alarm::AlarmDriverComponent::new(
365        board_kernel,
366        capsules_core::alarm::DRIVER_NUM,
367        mux_alarm,
368    )
369    .finalize(components::alarm_component_static!(nrf52840::rtc::Rtc));
370
371    let uart_channel = nrf52_components::UartChannelComponent::new(
376        uart_channel,
377        mux_alarm,
378        &base_peripherals.uarte0,
379    )
380    .finalize(nrf52_components::uart_channel_component_static!(
381        nrf52840::rtc::Rtc
382    ));
383
384    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
386        .finalize(components::process_printer_text_component_static!());
387    PROCESS_PRINTER = Some(process_printer);
388
389    let uart_mux = components::console::UartMuxComponent::new(uart_channel, 115200)
391        .finalize(components::uart_mux_component_static!(132));
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!(132, 132));
400    components::debug_writer::DebugWriterComponent::new::<
402        <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
403    >(
404        uart_mux,
405        create_capability!(capabilities::SetDebugWriterCapability),
406    )
407    .finalize(components::debug_writer_component_static!());
408
409    let ble_radio = components::ble::BLEComponent::new(
414        board_kernel,
415        capsules_extra::ble_advertising_driver::DRIVER_NUM,
416        &base_peripherals.ble_radio,
417        mux_alarm,
418    )
419    .finalize(components::ble_component_static!(
420        nrf52840::rtc::Rtc,
421        nrf52840::ble_radio::Radio
422    ));
423
424    let aes_mux = static_init!(
425        MuxAES128CCM<'static, nrf52840::aes::AesECB>,
426        MuxAES128CCM::new(&base_peripherals.ecb,)
427    );
428    base_peripherals.ecb.set_client(aes_mux);
429    aes_mux.register();
430
431    let (ieee802154_radio, _mux_mac) = components::ieee802154::Ieee802154Component::new(
432        board_kernel,
433        capsules_extra::ieee802154::DRIVER_NUM,
434        &nrf52840_peripherals.ieee802154_radio,
435        aes_mux,
436        PAN_ID,
437        SRC_MAC,
438        DEFAULT_EXT_SRC_MAC,
439    )
440    .finalize(components::ieee802154_component_static!(
441        nrf52840::ieee802154_radio::Radio,
442        nrf52840::aes::AesECB<'static>
443    ));
444
445    let temp = components::temperature::TemperatureComponent::new(
450        board_kernel,
451        capsules_extra::temperature::DRIVER_NUM,
452        &base_peripherals.temp,
453    )
454    .finalize(components::temperature_component_static!(
455        nrf52840::temperature::Temp
456    ));
457
458    let rng = components::rng::RngComponent::new(
463        board_kernel,
464        capsules_core::rng::DRIVER_NUM,
465        &base_peripherals.trng,
466    )
467    .finalize(components::rng_component_static!(nrf52840::trng::Trng));
468
469    base_peripherals.adc.calibrate();
474
475    let adc_mux = components::adc::AdcMuxComponent::new(&base_peripherals.adc)
476        .finalize(components::adc_mux_component_static!(nrf52840::adc::Adc));
477
478    let adc_syscall =
479        components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
480            .finalize(components::adc_syscall_component_helper!(
481                components::adc::AdcComponent::new(
483                    adc_mux,
484                    nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput1)
485                )
486                .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
487                components::adc::AdcComponent::new(
489                    adc_mux,
490                    nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput2)
491                )
492                .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
493                components::adc::AdcComponent::new(
495                    adc_mux,
496                    nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput4)
497                )
498                .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
499                components::adc::AdcComponent::new(
501                    adc_mux,
502                    nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput5)
503                )
504                .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
505                components::adc::AdcComponent::new(
507                    adc_mux,
508                    nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput6)
509                )
510                .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
511                components::adc::AdcComponent::new(
513                    adc_mux,
514                    nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput7)
515                )
516                .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
517            ));
518
519    let i2c_master_buffer = static_init!([u8; 128], [0; 128]);
524    let i2c_slave_buffer1 = static_init!([u8; 128], [0; 128]);
525    let i2c_slave_buffer2 = static_init!([u8; 128], [0; 128]);
526
527    let i2c_master_slave = static_init!(
528        I2CMasterSlaveDriver<nrf52840::i2c::TWI<'static>>,
529        I2CMasterSlaveDriver::new(
530            &base_peripherals.twi1,
531            i2c_master_buffer,
532            i2c_slave_buffer1,
533            i2c_slave_buffer2,
534            board_kernel.create_grant(
535                capsules_core::i2c_master_slave_driver::DRIVER_NUM,
536                &memory_allocation_capability
537            ),
538        )
539    );
540    base_peripherals.twi1.configure(
541        nrf52840::pinmux::Pinmux::new(I2C_SCL_PIN as u32),
542        nrf52840::pinmux::Pinmux::new(I2C_SDA_PIN as u32),
543    );
544    base_peripherals.twi1.set_master_client(i2c_master_slave);
545    base_peripherals.twi1.set_slave_client(i2c_master_slave);
546    base_peripherals.twi1.set_speed(nrf52840::i2c::Speed::K400);
549
550    nrf52840_peripherals.gpio_port[I2C_SDA_PIN].set_i2c_pin_cfg();
552    nrf52840_peripherals.gpio_port[I2C_SCL_PIN].set_i2c_pin_cfg();
553    nrf52840_peripherals.gpio_port[I2C_SDA_PIN].set_floating_state(FloatingState::PullUp);
555    nrf52840_peripherals.gpio_port[I2C_SCL_PIN].set_floating_state(FloatingState::PullUp);
556
557    nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
562
563    let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
564        .finalize(components::round_robin_component_static!(NUM_PROCS));
565
566    let platform = Platform {
567        button,
568        ble_radio,
569        ieee802154_radio,
570        console,
571        led,
572        gpio,
573        adc: adc_syscall,
574        rng,
575        temp,
576        alarm,
577        ipc: kernel::ipc::IPC::new(
578            board_kernel,
579            kernel::ipc::DRIVER_NUM,
580            &memory_allocation_capability,
581        ),
582        i2c_master_slave,
583        scheduler,
584        systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
585    };
586
587    let chip = static_init!(
588        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
589        nrf52840::chip::NRF52::new(nrf52840_peripherals)
590    );
591    CHIP = Some(chip);
592
593    debug!("Particle Boron: Initialization complete. Entering main loop\r");
594
595    extern "C" {
601        static _sapps: u8;
603        static _eapps: u8;
605        static mut _sappmem: u8;
607        static _eappmem: u8;
609    }
610
611    kernel::process::load_processes(
612        board_kernel,
613        chip,
614        core::slice::from_raw_parts(
615            core::ptr::addr_of!(_sapps),
616            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
617        ),
618        core::slice::from_raw_parts_mut(
619            core::ptr::addr_of_mut!(_sappmem),
620            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
621        ),
622        &FAULT_RESPONSE,
623        &process_management_capability,
624    )
625    .unwrap_or_else(|err| {
626        debug!("Error loading processes!");
627        debug!("{:?}", err);
628    });
629
630    (board_kernel, platform, chip)
631}
632
633#[no_mangle]
635pub unsafe fn main() {
636    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
637
638    let (board_kernel, platform, chip) = start_particle_boron();
639    board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
640}