nrf52840dk_test_appid_sha256/
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, addr_of_mut};
14
15use kernel::component::Component;
16use kernel::hil::led::LedLow;
17use kernel::hil::time::Counter;
18use kernel::platform::{KernelResources, SyscallDriverLookup};
19use kernel::scheduler::round_robin::RoundRobinSched;
20use kernel::{capabilities, create_capability, static_init};
21use nrf52840::gpio::Pin;
22use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
23use nrf52_components::{UartChannel, UartPins};
24
25// The nRF52840DK LEDs (see back of board)
26const LED1_PIN: Pin = Pin::P0_13;
27const LED2_PIN: Pin = Pin::P0_14;
28const LED3_PIN: Pin = Pin::P0_15;
29const LED4_PIN: Pin = Pin::P0_16;
30
31const BUTTON_RST_PIN: Pin = Pin::P0_18;
32
33const UART_RTS: Option<Pin> = Some(Pin::P0_05);
34const UART_TXD: Pin = Pin::P0_06;
35const UART_CTS: Option<Pin> = Some(Pin::P0_07);
36const UART_RXD: Pin = Pin::P0_08;
37
38/// Debug Writer
39pub mod io;
40
41// State for loading and holding applications.
42// How should the kernel respond when a process faults.
43const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
44    capsules_system::process_policies::PanicFaultPolicy {};
45
46// Number of concurrent processes this platform supports.
47const NUM_PROCS: usize = 8;
48
49static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
50    [None; NUM_PROCS];
51
52static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
53
54/// Dummy buffer that causes the linker to reserve enough space for the stack.
55#[no_mangle]
56#[link_section = ".stack_buffer"]
57pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
58
59//------------------------------------------------------------------------------
60// SYSCALL DRIVER TYPE DEFINITIONS
61//------------------------------------------------------------------------------
62
63type AlarmDriver = components::alarm::AlarmDriverComponentType<nrf52840::rtc::Rtc<'static>>;
64
65/// Supported drivers by the platform
66pub struct Platform {
67    console: &'static capsules_core::console::Console<'static>,
68    led: &'static capsules_core::led::LedDriver<
69        'static,
70        kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
71        4,
72    >,
73    alarm: &'static AlarmDriver,
74    scheduler: &'static RoundRobinSched<'static>,
75    systick: cortexm4::systick::SysTick,
76}
77
78impl SyscallDriverLookup for Platform {
79    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
80    where
81        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
82    {
83        match driver_num {
84            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
85            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
86            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
87            _ => f(None),
88        }
89    }
90}
91
92/// This is in a separate, inline(never) function so that its stack frame is
93/// removed when this function returns. Otherwise, the stack space used for
94/// these static_inits is wasted.
95#[inline(never)]
96unsafe fn create_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
97    let ieee802154_ack_buf = static_init!(
98        [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
99        [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
100    );
101    // Initialize chip peripheral drivers
102    let nrf52840_peripherals = static_init!(
103        Nrf52840DefaultPeripherals,
104        Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
105    );
106
107    nrf52840_peripherals
108}
109
110impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
111    for Platform
112{
113    type SyscallDriverLookup = Self;
114    type SyscallFilter = ();
115    type ProcessFault = ();
116    type Scheduler = RoundRobinSched<'static>;
117    type SchedulerTimer = cortexm4::systick::SysTick;
118    type WatchDog = ();
119    type ContextSwitchCallback = ();
120
121    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
122        self
123    }
124    fn syscall_filter(&self) -> &Self::SyscallFilter {
125        &()
126    }
127    fn process_fault(&self) -> &Self::ProcessFault {
128        &()
129    }
130    fn scheduler(&self) -> &Self::Scheduler {
131        self.scheduler
132    }
133    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
134        &self.systick
135    }
136    fn watchdog(&self) -> &Self::WatchDog {
137        &()
138    }
139    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
140        &()
141    }
142}
143
144/// Main function called after RAM initialized.
145#[no_mangle]
146pub unsafe fn main() {
147    //--------------------------------------------------------------------------
148    // INITIAL SETUP
149    //--------------------------------------------------------------------------
150
151    // Apply errata fixes and enable interrupts.
152    nrf52840::init();
153
154    // Set up peripheral drivers. Called in separate function to reduce stack
155    // usage.
156    let nrf52840_peripherals = create_peripherals();
157
158    // Set up circular peripheral dependencies.
159    nrf52840_peripherals.init();
160    let base_peripherals = &nrf52840_peripherals.nrf52;
161
162    // Choose the channel for serial output. This board can be configured to use
163    // either the Segger RTT channel or via UART with traditional TX/RX GPIO
164    // pins.
165    let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
166
167    // Setup space to store the core kernel data structure.
168    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
169
170    // Create (and save for panic debugging) a chip object to setup low-level
171    // resources (e.g. MPU, systick).
172    let chip = static_init!(
173        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
174        nrf52840::chip::NRF52::new(nrf52840_peripherals)
175    );
176    CHIP = Some(chip);
177
178    // Do nRF configuration and setup. This is shared code with other nRF-based
179    // platforms.
180    nrf52_components::startup::NrfStartupComponent::new(
181        false,
182        BUTTON_RST_PIN,
183        nrf52840::uicr::Regulator0Output::DEFAULT,
184        &base_peripherals.nvmc,
185    )
186    .finalize(());
187
188    //--------------------------------------------------------------------------
189    // CAPABILITIES
190    //--------------------------------------------------------------------------
191
192    // Create capabilities that the board needs to call certain protected kernel
193    // functions.
194    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
195
196    //--------------------------------------------------------------------------
197    // LEDs
198    //--------------------------------------------------------------------------
199
200    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
201        LedLow<'static, nrf52840::gpio::GPIOPin>,
202        LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
203        LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]),
204        LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]),
205        LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]),
206    ));
207
208    //--------------------------------------------------------------------------
209    // TIMER
210    //--------------------------------------------------------------------------
211
212    let rtc = &base_peripherals.rtc;
213    let _ = rtc.start();
214    let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
215        .finalize(components::alarm_mux_component_static!(nrf52840::rtc::Rtc));
216    let alarm = components::alarm::AlarmDriverComponent::new(
217        board_kernel,
218        capsules_core::alarm::DRIVER_NUM,
219        mux_alarm,
220    )
221    .finalize(components::alarm_component_static!(nrf52840::rtc::Rtc));
222
223    //--------------------------------------------------------------------------
224    // UART & CONSOLE & DEBUG
225    //--------------------------------------------------------------------------
226
227    let uart_channel = nrf52_components::UartChannelComponent::new(
228        uart_channel,
229        mux_alarm,
230        &base_peripherals.uarte0,
231    )
232    .finalize(nrf52_components::uart_channel_component_static!(
233        nrf52840::rtc::Rtc
234    ));
235
236    // Virtualize the UART channel for the console and for kernel debug.
237    let uart_mux = components::console::UartMuxComponent::new(uart_channel, 115200)
238        .finalize(components::uart_mux_component_static!());
239
240    // Setup the serial console for userspace.
241    let console = components::console::ConsoleComponent::new(
242        board_kernel,
243        capsules_core::console::DRIVER_NUM,
244        uart_mux,
245    )
246    .finalize(components::console_component_static!());
247
248    //--------------------------------------------------------------------------
249    // NRF CLOCK SETUP
250    //--------------------------------------------------------------------------
251
252    nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
253
254    //--------------------------------------------------------------------------
255    // Credential Checking
256    //--------------------------------------------------------------------------
257
258    // Create the software-based SHA engine.
259    let sha = components::sha::ShaSoftware256Component::new()
260        .finalize(components::sha_software_256_component_static!());
261
262    // Create the credential checker.
263    let checking_policy = components::appid::checker_sha::AppCheckerSha256Component::new(sha)
264        .finalize(components::app_checker_sha256_component_static!());
265
266    // Create the AppID assigner.
267    let assigner = components::appid::assigner_name::AppIdAssignerNamesComponent::new()
268        .finalize(components::appid_assigner_names_component_static!());
269
270    // Create the process checking machine.
271    let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
272        .finalize(components::process_checker_machine_component_static!());
273
274    //--------------------------------------------------------------------------
275    // STORAGE PERMISSIONS
276    //--------------------------------------------------------------------------
277
278    let storage_permissions_policy =
279        components::storage_permissions::null::StoragePermissionsNullComponent::new().finalize(
280            components::storage_permissions_null_component_static!(
281                nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
282                kernel::process::ProcessStandardDebugFull,
283            ),
284        );
285
286    //--------------------------------------------------------------------------
287    // PROCESS LOADING
288    //--------------------------------------------------------------------------
289
290    // Create and start the asynchronous process loader.
291    let _loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
292        checker,
293        &mut *addr_of_mut!(PROCESSES),
294        board_kernel,
295        chip,
296        &FAULT_RESPONSE,
297        assigner,
298        storage_permissions_policy,
299    )
300    .finalize(components::process_loader_sequential_component_static!(
301        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
302        kernel::process::ProcessStandardDebugFull,
303        NUM_PROCS
304    ));
305
306    //--------------------------------------------------------------------------
307    // PLATFORM SETUP, SCHEDULER, AND START KERNEL LOOP
308    //--------------------------------------------------------------------------
309
310    let scheduler = components::sched::round_robin::RoundRobinComponent::new(&*addr_of!(PROCESSES))
311        .finalize(components::round_robin_component_static!(NUM_PROCS));
312
313    let platform = Platform {
314        console,
315        led,
316        alarm,
317        scheduler,
318        systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
319    };
320
321    board_kernel.kernel_loop(
322        &platform,
323        chip,
324        None::<&kernel::ipc::IPC<0>>,
325        &main_loop_capability,
326    );
327}