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