bern_arch/cortex_m/
core.rs

1//! ARM Cortex-M implementation of [`ICore`].
2
3use crate::core::{ExecMode, ICore};
4use cortex_m::peripheral::scb;
5use cortex_m::peripheral::scb::VectActive;
6use cortex_m::peripheral::syst::SystClkSource;
7use cortex_m::{asm, Peripherals};
8
9pub struct ArchCore {
10    peripherals: Peripherals,
11}
12
13impl ICore for ArchCore {
14    fn new() -> Self {
15        // NOTE(unsafe): we must be able to take the peripherals or else the
16        // system is doomed
17        let mut peripherals = unsafe { Peripherals::steal() };
18        peripherals.SYST.set_clock_source(SystClkSource::Core);
19
20        ArchCore { peripherals }
21    }
22
23    fn set_systick_div(&mut self, divisor: u32) {
24        self.peripherals.SYST.set_reload(divisor - 1);
25        self.peripherals.SYST.clear_current();
26    }
27
28    fn start(&mut self) {
29        self.peripherals.SYST.enable_counter();
30        self.peripherals.SYST.enable_interrupt();
31
32        // enable PendSV interrupt on lowest priority
33        unsafe {
34            self.peripherals
35                .SCB
36                .set_priority(scb::SystemHandler::PendSV, 0xFF);
37        }
38        // todo: move
39        self.peripherals
40            .SCB
41            .enable(scb::Exception::MemoryManagement);
42    }
43
44    fn bkpt() {
45        asm::bkpt();
46    }
47
48    fn execution_mode() -> ExecMode {
49        if cortex_m::register::control::read().spsel().is_msp() {
50            ExecMode::Kernel
51        } else {
52            ExecMode::Thread
53        }
54    }
55
56    fn is_in_interrupt() -> bool {
57        cortex_m::peripheral::SCB::vect_active() != VectActive::ThreadMode
58    }
59
60    #[inline]
61    fn debug_time() -> u32 {
62        cortex_m::peripheral::DWT::cycle_count()
63    }
64}