nrf52840dk/
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 Nordic Semiconductor nRF52840 development kit (DK).
6
7#![no_std]
8// Disable this attribute when documenting, as a workaround for
9// https://github.com/rust-lang/rust/issues/62184.
10#![cfg_attr(not(doc), no_main)]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of_mut;
14
15use kernel::debug;
16use kernel::platform::{KernelResources, SyscallDriverLookup};
17use kernel::{capabilities, create_capability};
18use nrf52840dk_lib::{self, PROCESSES};
19
20// State for loading and holding applications.
21// How should the kernel respond when a process faults.
22const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
23    capsules_system::process_policies::PanicFaultPolicy {};
24
25struct Platform {
26    base: nrf52840dk_lib::Platform,
27    eui64_driver: &'static nrf52840dk_lib::Eui64Driver,
28    ieee802154_driver: &'static nrf52840dk_lib::Ieee802154Driver,
29    udp_driver: &'static capsules_extra::net::udp::UDPDriver<'static>,
30}
31
32impl SyscallDriverLookup for Platform {
33    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
34    where
35        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
36    {
37        match driver_num {
38            capsules_extra::eui64::DRIVER_NUM => f(Some(self.eui64_driver)),
39            capsules_extra::net::udp::DRIVER_NUM => f(Some(self.udp_driver)),
40            capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_driver)),
41            _ => self.base.with_driver(driver_num, f),
42        }
43    }
44}
45
46type Chip = nrf52840dk_lib::Chip;
47
48impl KernelResources<Chip> for Platform {
49    type SyscallDriverLookup = Self;
50    type SyscallFilter = <nrf52840dk_lib::Platform as KernelResources<Chip>>::SyscallFilter;
51    type ProcessFault = <nrf52840dk_lib::Platform as KernelResources<Chip>>::ProcessFault;
52    type Scheduler = <nrf52840dk_lib::Platform as KernelResources<Chip>>::Scheduler;
53    type SchedulerTimer = <nrf52840dk_lib::Platform as KernelResources<Chip>>::SchedulerTimer;
54    type WatchDog = <nrf52840dk_lib::Platform as KernelResources<Chip>>::WatchDog;
55    type ContextSwitchCallback =
56        <nrf52840dk_lib::Platform as KernelResources<Chip>>::ContextSwitchCallback;
57
58    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
59        self
60    }
61    fn syscall_filter(&self) -> &Self::SyscallFilter {
62        self.base.syscall_filter()
63    }
64    fn process_fault(&self) -> &Self::ProcessFault {
65        self.base.process_fault()
66    }
67    fn scheduler(&self) -> &Self::Scheduler {
68        self.base.scheduler()
69    }
70    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
71        self.base.scheduler_timer()
72    }
73    fn watchdog(&self) -> &Self::WatchDog {
74        self.base.watchdog()
75    }
76    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
77        self.base.context_switch_callback()
78    }
79}
80
81/// Main function called after RAM initialized.
82#[no_mangle]
83pub unsafe fn main() {
84    let (board_kernel, base_platform, chip, default_peripherals, mux_alarm) =
85        nrf52840dk_lib::start();
86
87    //--------------------------------------------------------------------------
88    // IEEE 802.15.4 and UDP
89    //--------------------------------------------------------------------------
90
91    let (eui64_driver, ieee802154_driver, udp_driver) =
92        nrf52840dk_lib::ieee802154_udp(board_kernel, default_peripherals, mux_alarm);
93
94    let platform = Platform {
95        base: base_platform,
96        eui64_driver,
97        ieee802154_driver,
98        udp_driver,
99    };
100
101    // These symbols are defined in the linker script.
102    extern "C" {
103        /// Beginning of the ROM region containing app images.
104        static _sapps: u8;
105        /// End of the ROM region containing app images.
106        static _eapps: u8;
107        /// Beginning of the RAM region for app memory.
108        static mut _sappmem: u8;
109        /// End of the RAM region for app memory.
110        static _eappmem: u8;
111    }
112
113    let process_management_capability =
114        create_capability!(capabilities::ProcessManagementCapability);
115    kernel::process::load_processes(
116        board_kernel,
117        chip,
118        core::slice::from_raw_parts(
119            core::ptr::addr_of!(_sapps),
120            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
121        ),
122        core::slice::from_raw_parts_mut(
123            core::ptr::addr_of_mut!(_sappmem),
124            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
125        ),
126        &mut *addr_of_mut!(PROCESSES),
127        &FAULT_RESPONSE,
128        &process_management_capability,
129    )
130    .unwrap_or_else(|err| {
131        debug!("Error loading processes!");
132        debug!("{:?}", err);
133    });
134
135    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
136    board_kernel.kernel_loop(
137        &platform,
138        chip,
139        Some(&platform.base.ipc),
140        &main_loop_capability,
141    );
142}