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