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