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