aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/peripheral/icb.rs30
-rw-r--r--src/peripheral/itm.rs13
-rw-r--r--src/peripheral/mod.rs49
-rw-r--r--src/peripheral/mpu.rs37
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],
+}