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