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