microbit_v2_test_dynamic_app_load/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Tock kernel for the Micro:bit v2.
6//!
7//! It is based on nRF52833 SoC (Cortex M4 core with a BLE).
8
9#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of;
14
15use kernel::capabilities;
16use kernel::component::Component;
17use kernel::hil::time::Counter;
18use kernel::platform::{KernelResources, SyscallDriverLookup};
19use kernel::process::ProcessArray;
20use kernel::scheduler::round_robin::RoundRobinSched;
21
22#[allow(unused_imports)]
23use kernel::{create_capability, debug, debug_gpio, debug_verbose, static_init};
24
25use nrf52833::gpio::Pin;
26use nrf52833::interrupt_service::Nrf52833DefaultPeripherals;
27
28// Kernel LED (same as microphone LED)
29const LED_KERNEL_PIN: Pin = Pin::P0_20;
30const LED_MICROPHONE_PIN: Pin = Pin::P0_20;
31
32// Buttons
33const BUTTON_A: Pin = Pin::P0_14;
34const BUTTON_B: Pin = Pin::P0_23;
35const TOUCH_LOGO: Pin = Pin::P1_04;
36
37// GPIOs
38
39// P0, P1 and P2 are used as ADC, comment them in the ADC section to use them as GPIO
40const _GPIO_P0: Pin = Pin::P0_02;
41const _GPIO_P1: Pin = Pin::P0_03;
42const _GPIO_P2: Pin = Pin::P0_04;
43const GPIO_P8: Pin = Pin::P0_10;
44const GPIO_P9: Pin = Pin::P0_09;
45const GPIO_P16: Pin = Pin::P1_02;
46
47const UART_TX_PIN: Pin = Pin::P0_06;
48const UART_RX_PIN: Pin = Pin::P1_08;
49
50/// LED matrix
51const LED_MATRIX_COLS: [Pin; 5] = [Pin::P0_28, Pin::P0_11, Pin::P0_31, Pin::P1_05, Pin::P0_30];
52const LED_MATRIX_ROWS: [Pin; 5] = [Pin::P0_21, Pin::P0_22, Pin::P0_15, Pin::P0_24, Pin::P0_19];
53
54// Speaker
55
56const SPEAKER_PIN: Pin = Pin::P0_00;
57
58/// I2C pins for all of the sensors.
59const I2C_SDA_PIN: Pin = Pin::P0_16;
60const I2C_SCL_PIN: Pin = Pin::P0_08;
61
62/// UART Writer for panic!()s.
63pub mod io;
64
65// State for loading and holding applications.
66// How should the kernel respond when a process faults.
67const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
68    capsules_system::process_policies::PanicFaultPolicy {};
69
70// Number of concurrent processes this platform supports.
71const NUM_PROCS: usize = 4;
72
73type ChipHw = nrf52833::chip::NRF52<'static, Nrf52833DefaultPeripherals<'static>>;
74
75/// Static variables used by io.rs.
76static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
77static mut CHIP: Option<&'static nrf52833::chip::NRF52<Nrf52833DefaultPeripherals>> = None;
78static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
79    None;
80
81kernel::stack_size! {0x2000}
82
83type TemperatureDriver =
84    components::temperature::TemperatureComponentType<nrf52::temperature::Temp<'static>>;
85type RngDriver = components::rng::RngComponentType<nrf52833::trng::Trng<'static>>;
86type Ieee802154RawDriver =
87    components::ieee802154::Ieee802154RawComponentType<nrf52833::ieee802154_radio::Radio<'static>>;
88type NonVolatilePages = components::dynamic_binary_storage::NVPages<nrf52833::nvmc::Nvmc>;
89type DynamicBinaryStorage<'a> = kernel::dynamic_binary_storage::SequentialDynamicBinaryStorage<
90    'static,
91    'static,
92    nrf52833::chip::NRF52<'a, Nrf52833DefaultPeripherals<'a>>,
93    kernel::process::ProcessStandardDebugFull,
94    NonVolatilePages,
95>;
96/// Supported drivers by the platform
97pub struct MicroBit {
98    ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
99        'static,
100        nrf52::ble_radio::Radio<'static>,
101        capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
102            'static,
103            nrf52::rtc::Rtc<'static>,
104        >,
105    >,
106    eui64: &'static capsules_extra::eui64::Eui64,
107    ieee802154: &'static Ieee802154RawDriver,
108    console: &'static capsules_core::console::Console<'static>,
109    gpio: &'static capsules_core::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>,
110    led: &'static capsules_core::led::LedDriver<
111        'static,
112        capsules_extra::led_matrix::LedMatrixLed<
113            'static,
114            nrf52::gpio::GPIOPin<'static>,
115            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
116                'static,
117                nrf52::rtc::Rtc<'static>,
118            >,
119        >,
120        25,
121    >,
122    button: &'static capsules_core::button::Button<'static, nrf52::gpio::GPIOPin<'static>>,
123    rng: &'static RngDriver,
124    ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
125    lsm303agr: &'static capsules_extra::lsm303agr::Lsm303agrI2C<
126        'static,
127        capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, nrf52833::i2c::TWI<'static>>,
128    >,
129    temperature: &'static TemperatureDriver,
130    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
131    adc: &'static capsules_core::adc::AdcVirtualized<'static>,
132    alarm: &'static capsules_core::alarm::AlarmDriver<
133        'static,
134        capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
135            'static,
136            nrf52::rtc::Rtc<'static>,
137        >,
138    >,
139    buzzer_driver: &'static capsules_extra::buzzer_driver::Buzzer<
140        'static,
141        capsules_extra::buzzer_pwm::PwmBuzzer<
142            'static,
143            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
144                'static,
145                nrf52833::rtc::Rtc<'static>,
146            >,
147            capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, nrf52833::pwm::Pwm>,
148        >,
149    >,
150    pwm: &'static capsules_extra::pwm::Pwm<'static, 1>,
151    app_flash: &'static capsules_extra::app_flash_driver::AppFlash<'static>,
152    sound_pressure: &'static capsules_extra::sound_pressure::SoundPressureSensor<'static>,
153    dynamic_app_loader: &'static capsules_extra::app_loader::AppLoader<
154        DynamicBinaryStorage<'static>,
155        DynamicBinaryStorage<'static>,
156    >,
157
158    scheduler: &'static RoundRobinSched<'static>,
159    systick: cortexm4::systick::SysTick,
160}
161
162impl SyscallDriverLookup for MicroBit {
163    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
164    where
165        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
166    {
167        match driver_num {
168            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
169            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
170            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
171            capsules_core::button::DRIVER_NUM => f(Some(self.button)),
172            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
173            capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
174            capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
175            capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
176            capsules_extra::lsm303agr::DRIVER_NUM => f(Some(self.lsm303agr)),
177            capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
178            capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
179            capsules_extra::buzzer_driver::DRIVER_NUM => f(Some(self.buzzer_driver)),
180            capsules_extra::pwm::DRIVER_NUM => f(Some(self.pwm)),
181            capsules_extra::app_flash_driver::DRIVER_NUM => f(Some(self.app_flash)),
182            capsules_extra::sound_pressure::DRIVER_NUM => f(Some(self.sound_pressure)),
183            capsules_extra::eui64::DRIVER_NUM => f(Some(self.eui64)),
184            capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154)),
185            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
186            capsules_extra::app_loader::DRIVER_NUM => f(Some(self.dynamic_app_loader)),
187            _ => f(None),
188        }
189    }
190}
191
192impl KernelResources<nrf52833::chip::NRF52<'static, Nrf52833DefaultPeripherals<'static>>>
193    for MicroBit
194{
195    type SyscallDriverLookup = Self;
196    type SyscallFilter = ();
197    type ProcessFault = ();
198    type Scheduler = RoundRobinSched<'static>;
199    type SchedulerTimer = cortexm4::systick::SysTick;
200    type WatchDog = ();
201    type ContextSwitchCallback = ();
202
203    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
204        self
205    }
206    fn syscall_filter(&self) -> &Self::SyscallFilter {
207        &()
208    }
209    fn process_fault(&self) -> &Self::ProcessFault {
210        &()
211    }
212    fn scheduler(&self) -> &Self::Scheduler {
213        self.scheduler
214    }
215    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
216        &self.systick
217    }
218    fn watchdog(&self) -> &Self::WatchDog {
219        &()
220    }
221    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
222        &()
223    }
224}
225
226/// This is in a separate, inline(never) function so that its stack frame is
227/// removed when this function returns. Otherwise, the stack space used for
228/// these static_inits is wasted.
229#[inline(never)]
230unsafe fn start() -> (
231    &'static kernel::Kernel,
232    MicroBit,
233    &'static nrf52833::chip::NRF52<'static, Nrf52833DefaultPeripherals<'static>>,
234) {
235    nrf52833::init();
236
237    let ieee802154_ack_buf = static_init!(
238        [u8; nrf52833::ieee802154_radio::ACK_BUF_SIZE],
239        [0; nrf52833::ieee802154_radio::ACK_BUF_SIZE]
240    );
241    // Initialize chip peripheral drivers
242    let nrf52833_peripherals = static_init!(
243        Nrf52833DefaultPeripherals,
244        Nrf52833DefaultPeripherals::new(ieee802154_ack_buf)
245    );
246
247    // set up circular peripheral dependencies
248    nrf52833_peripherals.init();
249
250    let base_peripherals = &nrf52833_peripherals.nrf52;
251
252    // Create an array to hold process references.
253    let processes = components::process_array::ProcessArrayComponent::new()
254        .finalize(components::process_array_component_static!(NUM_PROCS));
255    PROCESSES = Some(processes);
256
257    // Setup space to store the core kernel data structure.
258    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
259
260    //--------------------------------------------------------------------------
261    // RAW 802.15.4
262    //--------------------------------------------------------------------------
263
264    let device_id = (*addr_of!(nrf52833::ficr::FICR_INSTANCE)).id();
265
266    let eui64 = components::eui64::Eui64Component::new(u64::from_le_bytes(device_id))
267        .finalize(components::eui64_component_static!());
268
269    let ieee802154 = components::ieee802154::Ieee802154RawComponent::new(
270        board_kernel,
271        capsules_extra::ieee802154::DRIVER_NUM,
272        &nrf52833_peripherals.ieee802154_radio,
273    )
274    .finalize(components::ieee802154_raw_component_static!(
275        nrf52833::ieee802154_radio::Radio,
276    ));
277    //--------------------------------------------------------------------------
278    // CAPABILITIES
279    //--------------------------------------------------------------------------
280
281    // Create capabilities that the board needs to call certain protected kernel
282    // functions.
283    let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
284
285    //--------------------------------------------------------------------------
286    // DEBUG GPIO
287    //--------------------------------------------------------------------------
288
289    // Configure kernel debug GPIOs as early as possible. These are used by the
290    // `debug_gpio!(0, toggle)` macro. We uconfigure these early so that the
291    // macro is available during most of the setup code and kernel exection.
292    kernel::debug::assign_gpios(
293        Some(&nrf52833_peripherals.gpio_port[LED_KERNEL_PIN]),
294        None,
295        None,
296    );
297
298    //--------------------------------------------------------------------------
299    // GPIO
300    //--------------------------------------------------------------------------
301
302    let gpio = components::gpio::GpioComponent::new(
303        board_kernel,
304        capsules_core::gpio::DRIVER_NUM,
305        components::gpio_component_helper!(
306            nrf52833::gpio::GPIOPin,
307            // Used as ADC, comment them out in the ADC section to use them as GPIO
308            // 0 => &nrf52833_peripherals.gpio_port[GPIO_P0],
309            // 1 => &nrf52833_peripherals.gpio_port[_GPIO_P1],
310            // 2 => &nrf52833_peripherals.gpio_port[_GPIO_P2],
311            // Used as PWM, comment them out in the PWM section to use them as GPIO
312            //8 => &nrf52833_peripherals.gpio_port[GPIO_P8],
313            9 => &nrf52833_peripherals.gpio_port[GPIO_P9],
314            16 => &nrf52833_peripherals.gpio_port[GPIO_P16],
315        ),
316    )
317    .finalize(components::gpio_component_static!(nrf52833::gpio::GPIOPin));
318
319    //--------------------------------------------------------------------------
320    // Buttons
321    //--------------------------------------------------------------------------
322    let button = components::button::ButtonComponent::new(
323        board_kernel,
324        capsules_core::button::DRIVER_NUM,
325        components::button_component_helper!(
326            nrf52833::gpio::GPIOPin,
327            (
328                &nrf52833_peripherals.gpio_port[BUTTON_A],
329                kernel::hil::gpio::ActivationMode::ActiveLow,
330                kernel::hil::gpio::FloatingState::PullNone
331            ), // A
332            (
333                &nrf52833_peripherals.gpio_port[BUTTON_B],
334                kernel::hil::gpio::ActivationMode::ActiveLow,
335                kernel::hil::gpio::FloatingState::PullNone
336            ), // B
337            (
338                &nrf52833_peripherals.gpio_port[TOUCH_LOGO],
339                kernel::hil::gpio::ActivationMode::ActiveLow,
340                kernel::hil::gpio::FloatingState::PullNone
341            ), // Touch Logo
342        ),
343    )
344    .finalize(components::button_component_static!(
345        nrf52833::gpio::GPIOPin
346    ));
347
348    //--------------------------------------------------------------------------
349    // ALARM & TIMER
350    //--------------------------------------------------------------------------
351
352    let rtc = &base_peripherals.rtc;
353    let _ = rtc.start();
354
355    let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
356        .finalize(components::alarm_mux_component_static!(nrf52::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!(nrf52::rtc::Rtc));
363
364    //--------------------------------------------------------------------------
365    // PWM & BUZZER
366    //--------------------------------------------------------------------------
367
368    use kernel::hil::buzzer::Buzzer;
369    use kernel::hil::time::Alarm;
370
371    let mux_pwm = components::pwm::PwmMuxComponent::new(&base_peripherals.pwm0)
372        .finalize(components::pwm_mux_component_static!(nrf52833::pwm::Pwm));
373
374    let virtual_pwm_buzzer = components::pwm::PwmPinUserComponent::new(
375        mux_pwm,
376        nrf52833::pinmux::Pinmux::new(SPEAKER_PIN as u32),
377    )
378    .finalize(components::pwm_pin_user_component_static!(
379        nrf52833::pwm::Pwm
380    ));
381
382    let virtual_alarm_buzzer = static_init!(
383        capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52833::rtc::Rtc>,
384        capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm::new(mux_alarm)
385    );
386    virtual_alarm_buzzer.setup();
387
388    let pwm_buzzer = static_init!(
389        capsules_extra::buzzer_pwm::PwmBuzzer<
390            'static,
391            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
392                'static,
393                nrf52833::rtc::Rtc,
394            >,
395            capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, nrf52833::pwm::Pwm>,
396        >,
397        capsules_extra::buzzer_pwm::PwmBuzzer::new(
398            virtual_pwm_buzzer,
399            virtual_alarm_buzzer,
400            capsules_extra::buzzer_pwm::DEFAULT_MAX_BUZZ_TIME_MS,
401        )
402    );
403
404    let buzzer_driver = static_init!(
405        capsules_extra::buzzer_driver::Buzzer<
406            'static,
407            capsules_extra::buzzer_pwm::PwmBuzzer<
408                'static,
409                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
410                    'static,
411                    nrf52833::rtc::Rtc,
412                >,
413                capsules_core::virtualizers::virtual_pwm::PwmPinUser<'static, nrf52833::pwm::Pwm>,
414            >,
415        >,
416        capsules_extra::buzzer_driver::Buzzer::new(
417            pwm_buzzer,
418            capsules_extra::buzzer_driver::DEFAULT_MAX_BUZZ_TIME_MS,
419            board_kernel.create_grant(
420                capsules_extra::buzzer_driver::DRIVER_NUM,
421                &memory_allocation_capability
422            )
423        )
424    );
425
426    pwm_buzzer.set_client(buzzer_driver);
427
428    virtual_alarm_buzzer.set_alarm_client(pwm_buzzer);
429
430    let virtual_pwm_driver = components::pwm::PwmPinUserComponent::new(
431        mux_pwm,
432        nrf52833::pinmux::Pinmux::new(GPIO_P8 as u32),
433    )
434    .finalize(components::pwm_pin_user_component_static!(
435        nrf52833::pwm::Pwm
436    ));
437
438    let pwm =
439        components::pwm::PwmDriverComponent::new(board_kernel, capsules_extra::pwm::DRIVER_NUM)
440            .finalize(components::pwm_driver_component_helper!(virtual_pwm_driver));
441
442    //--------------------------------------------------------------------------
443    // UART & CONSOLE & DEBUG
444    //--------------------------------------------------------------------------
445
446    base_peripherals.uarte0.initialize(
447        nrf52::pinmux::Pinmux::new(UART_TX_PIN as u32),
448        nrf52::pinmux::Pinmux::new(UART_RX_PIN as u32),
449        None,
450        None,
451    );
452
453    // Create a shared UART channel for the console and for kernel debug.
454    let uart_mux = components::console::UartMuxComponent::new(&base_peripherals.uarte0, 115200)
455        .finalize(components::uart_mux_component_static!());
456
457    // Setup the console.
458    let console = components::console::ConsoleComponent::new(
459        board_kernel,
460        capsules_core::console::DRIVER_NUM,
461        uart_mux,
462    )
463    .finalize(components::console_component_static!());
464    // Create the debugger object that handles calls to `debug!()`.
465    components::debug_writer::DebugWriterComponent::new::<
466        <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
467    >(
468        uart_mux,
469        create_capability!(capabilities::SetDebugWriterCapability),
470    )
471    .finalize(components::debug_writer_component_static!());
472
473    //--------------------------------------------------------------------------
474    // RANDOM NUMBERS
475    //--------------------------------------------------------------------------
476
477    let rng = components::rng::RngComponent::new(
478        board_kernel,
479        capsules_core::rng::DRIVER_NUM,
480        &base_peripherals.trng,
481    )
482    .finalize(components::rng_component_static!(nrf52833::trng::Trng));
483
484    //--------------------------------------------------------------------------
485    // SENSORS
486    //--------------------------------------------------------------------------
487
488    base_peripherals.twi1.configure(
489        nrf52833::pinmux::Pinmux::new(I2C_SCL_PIN as u32),
490        nrf52833::pinmux::Pinmux::new(I2C_SDA_PIN as u32),
491    );
492
493    let sensors_i2c_bus = components::i2c::I2CMuxComponent::new(&base_peripherals.twi1, None)
494        .finalize(components::i2c_mux_component_static!(
495            nrf52833::i2c::TWI<'static>
496        ));
497
498    // LSM303AGR
499
500    let lsm303agr = components::lsm303agr::Lsm303agrI2CComponent::new(
501        sensors_i2c_bus,
502        None,
503        None,
504        board_kernel,
505        capsules_extra::lsm303agr::DRIVER_NUM,
506    )
507    .finalize(components::lsm303agr_component_static!(
508        nrf52833::i2c::TWI<'static>
509    ));
510
511    if let Err(error) = lsm303agr.configure(
512        capsules_extra::lsm303xx::Lsm303AccelDataRate::DataRate25Hz,
513        false,
514        capsules_extra::lsm303xx::Lsm303Scale::Scale2G,
515        false,
516        true,
517        capsules_extra::lsm303xx::Lsm303MagnetoDataRate::DataRate3_0Hz,
518        capsules_extra::lsm303xx::Lsm303Range::Range1_9G,
519    ) {
520        debug!("Failed to configure LSM303AGR sensor ({:?})", error);
521    }
522
523    let ninedof = components::ninedof::NineDofComponent::new(
524        board_kernel,
525        capsules_extra::ninedof::DRIVER_NUM,
526    )
527    .finalize(components::ninedof_component_static!(lsm303agr));
528
529    // Temperature
530
531    let temperature = components::temperature::TemperatureComponent::new(
532        board_kernel,
533        capsules_extra::temperature::DRIVER_NUM,
534        &base_peripherals.temp,
535    )
536    .finalize(components::temperature_component_static!(
537        nrf52833::temperature::Temp
538    ));
539
540    //--------------------------------------------------------------------------
541    // ADC
542    //--------------------------------------------------------------------------
543    base_peripherals.adc.calibrate();
544
545    let adc_mux = components::adc::AdcMuxComponent::new(&base_peripherals.adc)
546        .finalize(components::adc_mux_component_static!(nrf52833::adc::Adc));
547
548    // Comment out the following to use P0, P1 and P2 as GPIO
549    let adc_syscall =
550        components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
551            .finalize(components::adc_syscall_component_helper!(
552                // ADC Ring 0 (P0)
553                components::adc::AdcComponent::new(
554                    adc_mux,
555                    nrf52833::adc::AdcChannelSetup::new(nrf52833::adc::AdcChannel::AnalogInput0)
556                )
557                .finalize(components::adc_component_static!(nrf52833::adc::Adc)),
558                // ADC Ring 1 (P1)
559                components::adc::AdcComponent::new(
560                    adc_mux,
561                    nrf52833::adc::AdcChannelSetup::new(nrf52833::adc::AdcChannel::AnalogInput1)
562                )
563                .finalize(components::adc_component_static!(nrf52833::adc::Adc)),
564                // ADC Ring 2 (P2)
565                components::adc::AdcComponent::new(
566                    adc_mux,
567                    nrf52833::adc::AdcChannelSetup::new(nrf52833::adc::AdcChannel::AnalogInput2)
568                )
569                .finalize(components::adc_component_static!(nrf52833::adc::Adc))
570            ));
571
572    // Microphone
573
574    let adc_microphone = components::adc_microphone::AdcMicrophoneComponent::new(
575        adc_mux,
576        nrf52833::adc::AdcChannelSetup::setup(
577            nrf52833::adc::AdcChannel::AnalogInput3,
578            nrf52833::adc::AdcChannelGain::Gain4,
579            nrf52833::adc::AdcChannelResistor::Bypass,
580            nrf52833::adc::AdcChannelResistor::Pulldown,
581            nrf52833::adc::AdcChannelSamplingTime::us3,
582        ),
583        Some(&nrf52833_peripherals.gpio_port[LED_MICROPHONE_PIN]),
584    )
585    .finalize(components::adc_microphone_component_static!(
586        // adc
587        nrf52833::adc::Adc,
588        // buffer size
589        50,
590        // gpio
591        nrf52833::gpio::GPIOPin
592    ));
593
594    nrf52833_peripherals.gpio_port[LED_MICROPHONE_PIN].set_high_drive(true);
595
596    let sound_pressure = components::sound_pressure::SoundPressureComponent::new(
597        board_kernel,
598        capsules_extra::sound_pressure::DRIVER_NUM,
599        adc_microphone,
600    )
601    .finalize(components::sound_pressure_component_static!());
602
603    //--------------------------------------------------------------------------
604    // STORAGE
605    //--------------------------------------------------------------------------
606
607    let mux_flash = components::flash::FlashMuxComponent::new(&base_peripherals.nvmc).finalize(
608        components::flash_mux_component_static!(nrf52833::nvmc::Nvmc),
609    );
610
611    // App Flash
612
613    let virtual_app_flash = components::flash::FlashUserComponent::new(mux_flash).finalize(
614        components::flash_user_component_static!(nrf52833::nvmc::Nvmc),
615    );
616
617    let app_flash = components::app_flash_driver::AppFlashComponent::new(
618        board_kernel,
619        capsules_extra::app_flash_driver::DRIVER_NUM,
620        virtual_app_flash,
621    )
622    .finalize(components::app_flash_component_static!(
623        capsules_core::virtualizers::virtual_flash::FlashUser<'static, nrf52833::nvmc::Nvmc>,
624        512
625    ));
626
627    //--------------------------------------------------------------------------
628    // WIRELESS
629    //--------------------------------------------------------------------------
630
631    let ble_radio = components::ble::BLEComponent::new(
632        board_kernel,
633        capsules_extra::ble_advertising_driver::DRIVER_NUM,
634        &base_peripherals.ble_radio,
635        mux_alarm,
636    )
637    .finalize(components::ble_component_static!(
638        nrf52833::rtc::Rtc,
639        nrf52833::ble_radio::Radio
640    ));
641
642    //--------------------------------------------------------------------------
643    // LED Matrix
644    //--------------------------------------------------------------------------
645
646    let led_matrix = components::led_matrix::LedMatrixComponent::new(
647        mux_alarm,
648        components::led_line_component_static!(
649            nrf52833::gpio::GPIOPin,
650            &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[0]],
651            &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[1]],
652            &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[2]],
653            &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[3]],
654            &nrf52833_peripherals.gpio_port[LED_MATRIX_COLS[4]],
655        ),
656        components::led_line_component_static!(
657            nrf52833::gpio::GPIOPin,
658            &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[0]],
659            &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[1]],
660            &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[2]],
661            &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[3]],
662            &nrf52833_peripherals.gpio_port[LED_MATRIX_ROWS[4]],
663        ),
664        kernel::hil::gpio::ActivationMode::ActiveLow,
665        kernel::hil::gpio::ActivationMode::ActiveHigh,
666        60,
667    )
668    .finalize(components::led_matrix_component_static!(
669        nrf52833::gpio::GPIOPin,
670        nrf52::rtc::Rtc<'static>,
671        5,
672        5
673    ));
674
675    let led = static_init!(
676        capsules_core::led::LedDriver<
677            'static,
678            capsules_extra::led_matrix::LedMatrixLed<
679                'static,
680                nrf52::gpio::GPIOPin<'static>,
681                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
682                    'static,
683                    nrf52::rtc::Rtc<'static>,
684                >,
685            >,
686            25,
687        >,
688        capsules_core::led::LedDriver::new(components::led_matrix_leds!(
689            nrf52::gpio::GPIOPin<'static>,
690            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
691                'static,
692                nrf52::rtc::Rtc<'static>,
693            >,
694            led_matrix,
695            (0, 0),
696            (1, 0),
697            (2, 0),
698            (3, 0),
699            (4, 0),
700            (0, 1),
701            (1, 1),
702            (2, 1),
703            (3, 1),
704            (4, 1),
705            (0, 2),
706            (1, 2),
707            (2, 2),
708            (3, 2),
709            (4, 2),
710            (0, 3),
711            (1, 3),
712            (2, 3),
713            (3, 3),
714            (4, 3),
715            (0, 4),
716            (1, 4),
717            (2, 4),
718            (3, 4),
719            (4, 4)
720        )),
721    );
722
723    //--------------------------------------------------------------------------
724    // Process Console
725    //--------------------------------------------------------------------------
726    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
727        .finalize(components::process_printer_text_component_static!());
728    PROCESS_PRINTER = Some(process_printer);
729
730    let _process_console = components::process_console::ProcessConsoleComponent::new(
731        board_kernel,
732        uart_mux,
733        mux_alarm,
734        process_printer,
735        Some(cortexm4::support::reset),
736    )
737    .finalize(components::process_console_component_static!(
738        nrf52833::rtc::Rtc
739    ));
740    let _ = _process_console.start();
741
742    let chip = static_init!(
743        nrf52833::chip::NRF52<Nrf52833DefaultPeripherals>,
744        nrf52833::chip::NRF52::new(nrf52833_peripherals)
745    );
746    CHIP = Some(chip);
747
748    //--------------------------------------------------------------------------
749    // Credential Checking
750    //--------------------------------------------------------------------------
751
752    // Create the credential checker.
753    let checking_policy = components::appid::checker_null::AppCheckerNullComponent::new()
754        .finalize(components::app_checker_null_component_static!());
755
756    // Create the AppID assigner.
757    let assigner = components::appid::assigner_tbf::AppIdAssignerTbfHeaderComponent::new()
758        .finalize(components::appid_assigner_tbf_header_component_static!());
759
760    // Create the process checking machine.
761    let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
762        .finalize(components::process_checker_machine_component_static!());
763
764    //--------------------------------------------------------------------------
765    // STORAGE PERMISSIONS
766    //--------------------------------------------------------------------------
767
768    let storage_permissions_policy =
769        components::storage_permissions::null::StoragePermissionsNullComponent::new().finalize(
770            components::storage_permissions_null_component_static!(
771                nrf52833::chip::NRF52<Nrf52833DefaultPeripherals>,
772                kernel::process::ProcessStandardDebugFull,
773            ),
774        );
775
776    // These symbols are defined in the standard Tock linker script.
777    extern "C" {
778        /// Beginning of the ROM region containing app images.
779        static _sapps: u8;
780        /// End of the ROM region containing app images.
781        static _eapps: u8;
782        /// Beginning of the RAM region for app memory.
783        static mut _sappmem: u8;
784        /// End of the RAM region for app memory.
785        static _eappmem: u8;
786    }
787
788    let app_flash_slice = core::slice::from_raw_parts(
789        core::ptr::addr_of!(_sapps),
790        core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
791    );
792    let app_memory_slice = core::slice::from_raw_parts_mut(
793        core::ptr::addr_of_mut!(_sappmem),
794        core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
795    );
796
797    // Create and start the asynchronous process loader.
798    let loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
799        checker,
800        board_kernel,
801        chip,
802        &FAULT_RESPONSE,
803        assigner,
804        storage_permissions_policy,
805        app_flash_slice,
806        app_memory_slice,
807    )
808    .finalize(components::process_loader_sequential_component_static!(
809        nrf52833::chip::NRF52<Nrf52833DefaultPeripherals>,
810        kernel::process::ProcessStandardDebugFull,
811        NUM_PROCS
812    ));
813
814    //--------------------------------------------------------------------------
815    // Dynamic App Loading
816    //--------------------------------------------------------------------------
817
818    // Create the dynamic binary flasher.
819    let dynamic_binary_storage =
820        components::dynamic_binary_storage::SequentialBinaryStorageComponent::new(
821            &base_peripherals.nvmc,
822            loader,
823        )
824        .finalize(components::sequential_binary_storage_component_static!(
825            nrf52833::nvmc::Nvmc,
826            nrf52833::chip::NRF52<Nrf52833DefaultPeripherals>,
827            kernel::process::ProcessStandardDebugFull,
828        ));
829
830    // Create the dynamic app loader capsule.
831    let dynamic_app_loader = components::app_loader::AppLoaderComponent::new(
832        board_kernel,
833        capsules_extra::app_loader::DRIVER_NUM,
834        dynamic_binary_storage,
835        dynamic_binary_storage,
836    )
837    .finalize(components::app_loader_component_static!(
838        DynamicBinaryStorage<'static>,
839        DynamicBinaryStorage<'static>,
840    ));
841
842    //--------------------------------------------------------------------------
843    // FINAL SETUP AND BOARD BOOT
844    //--------------------------------------------------------------------------
845
846    // it seems that microbit v2 has no external clock
847    base_peripherals.clock.low_stop();
848    base_peripherals.clock.high_stop();
849    base_peripherals.clock.low_start();
850    base_peripherals.clock.high_start();
851    while !base_peripherals.clock.low_started() {}
852    while !base_peripherals.clock.high_started() {}
853
854    let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
855        .finalize(components::round_robin_component_static!(NUM_PROCS));
856
857    let microbit = MicroBit {
858        ble_radio,
859        ieee802154,
860        eui64,
861        console,
862        gpio,
863        button,
864        led,
865        rng,
866        temperature,
867        lsm303agr,
868        ninedof,
869        buzzer_driver,
870        pwm,
871        sound_pressure,
872        adc: adc_syscall,
873        alarm,
874        app_flash,
875        ipc: kernel::ipc::IPC::new(
876            board_kernel,
877            kernel::ipc::DRIVER_NUM,
878            &memory_allocation_capability,
879        ),
880        dynamic_app_loader,
881
882        scheduler,
883        systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
884    };
885
886    debug!("Initialization complete. Entering main loop.");
887
888    (board_kernel, microbit, chip)
889}
890
891/// Main function called after RAM initialized.
892#[no_mangle]
893pub unsafe fn main() {
894    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
895
896    let (board_kernel, board, chip) = start();
897    board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
898}