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