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