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