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