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