diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/peripheral/icb.rs | 30 | ||||
-rw-r--r-- | src/peripheral/itm.rs | 13 | ||||
-rw-r--r-- | src/peripheral/mod.rs | 49 | ||||
-rw-r--r-- | src/peripheral/mpu.rs | 37 |
4 files changed, 126 insertions, 3 deletions
diff --git a/src/peripheral/icb.rs b/src/peripheral/icb.rs new file mode 100644 index 0000000..77ffd5d --- /dev/null +++ b/src/peripheral/icb.rs @@ -0,0 +1,30 @@ +//! Implementation Control Block + +use volatile_register::{RO, RW}; + +/// Register block +#[repr(C)] +pub struct RegisterBlock { + /// Interrupt Controller Type Register + /// + /// The bottom four bits of this register give the number of implemented + /// interrupt lines, divided by 32. So a value of `0b0010` indicates 64 + /// interrupts. + #[cfg(any(armv7m, armv8m, target_arch = "x86_64"))] + pub ictr: RO<u32>, + + /// The ICTR is not defined in the ARMv6-M Architecture Reference manual, so + /// we replace it with this. + #[cfg(not(any(armv7m, armv8m, target_arch = "x86_64")))] + _reserved: u32, + + /// Auxiliary Control Register + /// + /// This register is entirely implementation defined -- the standard gives + /// it an address, but does not define its role or contents. + pub actlr: RW<u32>, + + /// Coprocessor Power Control Register + #[cfg(armv8m)] + pub cppwr: RW<u32>, +} diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 57d2ff8..c0d560f 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -53,8 +53,19 @@ impl Stim { } /// Returns `true` if the stimulus port is ready to accept more data + #[cfg(not(armv8m))] #[inline] pub fn is_fifo_ready(&self) -> bool { - unsafe { ptr::read_volatile(self.register.get()) & 1 == 1 } + unsafe { ptr::read_volatile(self.register.get()) & 0b1 == 1 } + } + + /// Returns `true` if the stimulus port is ready to accept more data + #[cfg(armv8m)] + #[inline] + pub fn is_fifo_ready(&self) -> bool { + // ARMv8-M adds a disabled bit; we indicate that we are ready to + // proceed with a stimulus write if the port is either ready (bit 0) or + // disabled (bit 1). + unsafe { ptr::read_volatile(self.register.get()) & 0b11 != 0 } } } diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 04fae31..0838dca 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -55,7 +55,7 @@ //! //! - ARMv7-M Architecture Reference Manual (Issue E.b) - Chapter B3 -// TODO stand-alone registers: ICTR, ACTLR and STIR +// TODO stand-alone register: STIR use core::marker::PhantomData; use core::ops; @@ -72,6 +72,7 @@ pub mod fpb; // NOTE(target_arch) is for documentation purposes #[cfg(any(has_fpu, target_arch = "x86_64"))] pub mod fpu; +pub mod icb; #[cfg(all(not(armv6m), not(armv8m_base)))] pub mod itm; pub mod mpu; @@ -90,6 +91,7 @@ mod test; /// Core peripherals #[allow(non_snake_case)] +#[allow(clippy::manual_non_exhaustive)] pub struct Peripherals { /// Cache and branch predictor maintenance operations. /// Not available on Armv6-M. @@ -111,6 +113,12 @@ pub struct Peripherals { /// Floating Point Unit. pub FPU: FPU, + /// Implementation Control Block. + /// + /// The name is from the v8-M spec, but the block existed in earlier + /// revisions, without a name. + pub ICB: ICB, + /// Instrumentation Trace Macrocell. /// Not available on Armv6-M and Armv8-M Baseline. pub ITM: ITM, @@ -181,6 +189,9 @@ impl Peripherals { FPU: FPU { _marker: PhantomData, }, + ICB: ICB { + _marker: PhantomData, + }, ITM: ITM { _marker: PhantomData, }, @@ -364,6 +375,42 @@ impl ops::Deref for FPU { } } +/// Implementation Control Block. +/// +/// This block contains implementation-defined registers like `ictr` and +/// `actlr`. It's called the "implementation control block" in the ARMv8-M +/// standard, but earlier standards contained the registers, just without a +/// name. +pub struct ICB { + _marker: PhantomData<*const ()>, +} + +unsafe impl Send for ICB {} + +impl ICB { + /// Returns a pointer to the register block + #[inline(always)] + pub fn ptr() -> *mut icb::RegisterBlock { + 0xE000_E004 as *mut _ + } +} + +impl ops::Deref for ICB { + type Target = self::icb::RegisterBlock; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + unsafe { &*Self::ptr() } + } +} + +impl ops::DerefMut for ICB { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *Self::ptr() } + } +} + /// Instrumentation Trace Macrocell pub struct ITM { _marker: PhantomData<*const ()>, diff --git a/src/peripheral/mpu.rs b/src/peripheral/mpu.rs index 09d06f0..4d53eb5 100644 --- a/src/peripheral/mpu.rs +++ b/src/peripheral/mpu.rs @@ -2,7 +2,8 @@ use volatile_register::{RO, RW}; -/// Register block +/// Register block for ARMv7-M +#[cfg(any(armv6m, armv7m, target_arch = "x86_64"))] // x86-64 is for rustdoc #[repr(C)] pub struct RegisterBlock { /// Type @@ -28,3 +29,37 @@ pub struct RegisterBlock { /// Alias 3 of RSAR pub rsar_a3: RW<u32>, } + +/// Register block for ARMv8-M +#[cfg(armv8m)] +#[repr(C)] +pub struct RegisterBlock { + /// Type + pub _type: RO<u32>, + /// Control + pub ctrl: RW<u32>, + /// Region Number + pub rnr: RW<u32>, + /// Region Base Address + pub rbar: RW<u32>, + /// Region Limit Address + pub rlar: RW<u32>, + /// Alias 1 of RBAR + pub rbar_a1: RW<u32>, + /// Alias 1 of RLAR + pub rlar_a1: RW<u32>, + /// Alias 2 of RBAR + pub rbar_a2: RW<u32>, + /// Alias 2 of RLAR + pub rlar_a2: RW<u32>, + /// Alias 3 of RBAR + pub rbar_a3: RW<u32>, + /// Alias 3 of RLAR + pub rlar_a3: RW<u32>, + + // Reserved word at offset 0xBC + _reserved: u32, + + /// Memory Attribute Indirection register 0 and 1 + pub mair: [RW<u32>; 2], +} |