diff options
-rw-r--r-- | cortex-m-rt/link.x.in | 1 | ||||
-rw-r--r-- | cortex-m-rt/src/lib.rs | 157 |
2 files changed, 141 insertions, 17 deletions
diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in index 30d4af1..4db25fa 100644 --- a/cortex-m-rt/link.x.in +++ b/cortex-m-rt/link.x.in @@ -191,6 +191,7 @@ ASSERT(SIZEOF(.vector_table) > 0x40, " ERROR(cortex-m-rt): The interrupt vectors are missing. Possible solutions, from most likely to less likely: - Link to a svd2rust generated device crate +- Check that you actually use the device/hal/bsp crate in your code - Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency may be enabling it) - Supply the interrupt handlers yourself. Check the documentation for details."); diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 8bfdd69..150ca8e 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -416,33 +416,156 @@ pub use macros::{entry, exception, pre_init}; #[doc(hidden)] pub static __ONCE__: () = (); -/// Registers stacked (pushed into the stack) during an exception +/// Registers stacked (pushed onto the stack) during an exception. #[derive(Clone, Copy)] #[repr(C)] pub struct ExceptionFrame { - /// (General purpose) Register 0 - pub r0: u32, + r0: u32, + r1: u32, + r2: u32, + r3: u32, + r12: u32, + lr: u32, + pc: u32, + xpsr: u32, +} + +impl ExceptionFrame { + /// Returns the value of (general purpose) register 0. + #[inline(always)] + pub fn r0(&self) -> u32 { + self.r0 + } + + /// Returns the value of (general purpose) register 1. + #[inline(always)] + pub fn r1(&self) -> u32 { + self.r1 + } + + /// Returns the value of (general purpose) register 2. + #[inline(always)] + pub fn r2(&self) -> u32 { + self.r2 + } + + /// Returns the value of (general purpose) register 3. + #[inline(always)] + pub fn r3(&self) -> u32 { + self.r3 + } + + /// Returns the value of (general purpose) register 12. + #[inline(always)] + pub fn r12(&self) -> u32 { + self.r12 + } + + /// Returns the value of the Link Register. + #[inline(always)] + pub fn lr(&self) -> u32 { + self.lr + } - /// (General purpose) Register 1 - pub r1: u32, + /// Returns the value of the Program Counter. + #[inline(always)] + pub fn pc(&self) -> u32 { + self.pc + } - /// (General purpose) Register 2 - pub r2: u32, + /// Returns the value of the Program Status Register. + #[inline(always)] + pub fn xpsr(&self) -> u32 { + self.xpsr + } - /// (General purpose) Register 3 - pub r3: u32, + /// Sets the stacked value of (general purpose) register 0. + /// + /// # Safety + /// + /// This affects the `r0` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_r0(&mut self, value: u32) { + self.r0 = value; + } - /// (General purpose) Register 12 - pub r12: u32, + /// Sets the stacked value of (general purpose) register 1. + /// + /// # Safety + /// + /// This affects the `r1` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_r1(&mut self, value: u32) { + self.r1 = value; + } - /// Linker Register - pub lr: u32, + /// Sets the stacked value of (general purpose) register 2. + /// + /// # Safety + /// + /// This affects the `r2` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_r2(&mut self, value: u32) { + self.r2 = value; + } - /// Program Counter - pub pc: u32, + /// Sets the stacked value of (general purpose) register 3. + /// + /// # Safety + /// + /// This affects the `r3` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_r3(&mut self, value: u32) { + self.r3 = value; + } - /// Program Status Register - pub xpsr: u32, + /// Sets the stacked value of (general purpose) register 12. + /// + /// # Safety + /// + /// This affects the `r12` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_r12(&mut self, value: u32) { + self.r12 = value; + } + + /// Sets the stacked value of the Link Register. + /// + /// # Safety + /// + /// This affects the `lr` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_lr(&mut self, value: u32) { + self.lr = value; + } + + /// Sets the stacked value of the Program Counter. + /// + /// # Safety + /// + /// This affects the `pc` register of the preempted code, which must not rely on it getting + /// restored to its previous value. + #[inline(always)] + pub unsafe fn set_pc(&mut self, value: u32) { + self.pc = value; + } + + /// Sets the stacked value of the Program Status Register. + /// + /// # Safety + /// + /// This affects the `xPSR` registers (`IPSR`, `APSR`, and `EPSR`) of the preempted code, which + /// must not rely on them getting restored to their previous value. + #[inline(always)] + pub unsafe fn set_xpsr(&mut self, value: u32) { + self.xpsr = value; + } } impl fmt::Debug for ExceptionFrame { |