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