Skip to content

Commit 160d699

Browse files
committed
Expose the orphaned ICTR/ACTLR registers.
In ARMv7-M these were floating alone in system control space, without a unifying name. As a result, they weren't exposed in earlier versions of this crate. In ARMv8-M they have been given a name, the Implementation Control Block, and more registers have been added. I've used that name for all architecture revisions.
1 parent c9c7539 commit 160d699

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

src/peripheral/icb.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//! Implementation Control Block
2+
3+
use volatile_register::{RO, RW};
4+
5+
/// Register block
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// Interrupt Controller Type Register
9+
///
10+
/// The bottom four bits of this register give the number of implemented
11+
/// interrupt lines, divided by 32. So a value of `0b0010` indicates 64
12+
/// interrupts.
13+
#[cfg(any(armv7m, armv8m))]
14+
pub ictr: RO<u32>,
15+
16+
/// The ICTR is not defined in the ARMv6-M Architecture Reference manual, so
17+
/// we replace it with this.
18+
#[cfg(armv6m)]
19+
_reserved: u32,
20+
21+
/// Auxiliary Control Register
22+
///
23+
/// This register is entirely implementation defined -- the standard gives
24+
/// it an address, but does not define its role or contents.
25+
pub actlr: RW<u32>,
26+
27+
/// Coprocessor Power Control Register
28+
#[cfg(armv8m)]
29+
pub cppwr: RW<u32>,
30+
}

src/peripheral/mod.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
//!
5656
//! - ARMv7-M Architecture Reference Manual (Issue E.b) - Chapter B3
5757
58-
// TODO stand-alone registers: ICTR, ACTLR and STIR
58+
// TODO stand-alone register: STIR
5959

6060
use core::marker::PhantomData;
6161
use core::ops;
@@ -72,6 +72,7 @@ pub mod fpb;
7272
// NOTE(target_arch) is for documentation purposes
7373
#[cfg(any(has_fpu, target_arch = "x86_64"))]
7474
pub mod fpu;
75+
pub mod icb;
7576
#[cfg(all(not(armv6m), not(armv8m_base)))]
7677
pub mod itm;
7778
pub mod mpu;
@@ -112,6 +113,12 @@ pub struct Peripherals {
112113
/// Floating Point Unit.
113114
pub FPU: FPU,
114115

116+
/// Implementation Control Block.
117+
///
118+
/// The name is from the v8-M spec, but the block existed in earlier
119+
/// revisions, without a name.
120+
pub ICB: ICB,
121+
115122
/// Instrumentation Trace Macrocell.
116123
/// Not available on Armv6-M and Armv8-M Baseline.
117124
pub ITM: ITM,
@@ -182,6 +189,9 @@ impl Peripherals {
182189
FPU: FPU {
183190
_marker: PhantomData,
184191
},
192+
ICB: ICB {
193+
_marker: PhantomData,
194+
},
185195
ITM: ITM {
186196
_marker: PhantomData,
187197
},
@@ -365,6 +375,42 @@ impl ops::Deref for FPU {
365375
}
366376
}
367377

378+
/// Implementation Control Block.
379+
///
380+
/// This block contains implementation-defined registers like `ictr` and
381+
/// `actlr`. It's called the "implementation control block" in the ARMv8-M
382+
/// standard, but earlier standards contained the registers, just without a
383+
/// name.
384+
pub struct ICB {
385+
_marker: PhantomData<*const ()>,
386+
}
387+
388+
unsafe impl Send for ICB {}
389+
390+
impl ICB {
391+
/// Returns a pointer to the register block
392+
#[inline(always)]
393+
pub fn ptr() -> *mut icb::RegisterBlock {
394+
0xE000_E004 as *mut _
395+
}
396+
}
397+
398+
impl ops::Deref for ICB {
399+
type Target = self::icb::RegisterBlock;
400+
401+
#[inline(always)]
402+
fn deref(&self) -> &Self::Target {
403+
unsafe { &*Self::ptr() }
404+
}
405+
}
406+
407+
impl ops::DerefMut for ICB {
408+
#[inline(always)]
409+
fn deref_mut(&mut self) -> &mut Self::Target {
410+
unsafe { &mut *Self::ptr() }
411+
}
412+
}
413+
368414
/// Instrumentation Trace Macrocell
369415
pub struct ITM {
370416
_marker: PhantomData<*const ()>,

0 commit comments

Comments
 (0)