Skip to content

Commit 319773e

Browse files
bors[bot]adamgreig
andauthored
Merge #192
192: Update and improve cache operations. r=jonas-schievink a=adamgreig Closes #47, #188. I've implemented the proposed methods from #47 and marked all d-cache invalidation functions as unsafe. It's not unsafe to invalidate i-cache or branch predictor as they are read-only caches. The clean and clean+invalidate operations do not alter memory from the executing core's point of view so are also safe. It wasn't possible to remove the requirement to pass in `&mut CPUID` as you require synchronized access to `CPUID` to read the number of sets and ways in the cache, which is required to fully clean or invalidate them, which is required to enable or disable them. So it goes. Breaking change due to changing safety of d-cache invalidation functions. Co-authored-by: Adam Greig <[email protected]>
2 parents 22d47dd + 9ad4e10 commit 319773e

File tree

3 files changed

+298
-94
lines changed

3 files changed

+298
-94
lines changed

src/peripheral/cbp.rs

+19-27
Original file line numberDiff line numberDiff line change
@@ -39,34 +39,28 @@ const CBP_SW_SET_MASK: u32 = 0x1FF << CBP_SW_SET_POS;
3939

4040
impl CBP {
4141
/// I-cache invalidate all to PoU
42-
#[inline]
42+
#[inline(always)]
4343
pub fn iciallu(&mut self) {
44-
unsafe {
45-
self.iciallu.write(0);
46-
}
44+
unsafe { self.iciallu.write(0) };
4745
}
4846

4947
/// I-cache invalidate by MVA to PoU
50-
#[inline]
48+
#[inline(always)]
5149
pub fn icimvau(&mut self, mva: u32) {
52-
unsafe {
53-
self.icimvau.write(mva);
54-
}
50+
unsafe { self.icimvau.write(mva) };
5551
}
5652

5753
/// D-cache invalidate by MVA to PoC
58-
#[inline]
59-
pub fn dcimvac(&mut self, mva: u32) {
60-
unsafe {
61-
self.dcimvac.write(mva);
62-
}
54+
#[inline(always)]
55+
pub unsafe fn dcimvac(&mut self, mva: u32) {
56+
self.dcimvac.write(mva);
6357
}
6458

6559
/// D-cache invalidate by set-way
6660
///
6761
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
68-
#[inline]
69-
pub fn dcisw(&mut self, set: u16, way: u16) {
62+
#[inline(always)]
63+
pub unsafe fn dcisw(&mut self, set: u16, way: u16) {
7064
// The ARMv7-M Architecture Reference Manual, as of Revision E.b, says these set/way
7165
// operations have a register data format which depends on the implementation's
7266
// associativity and number of sets. Specifically the 'way' and 'set' fields have
@@ -76,24 +70,22 @@ impl CBP {
7670
// Generic User Guide section 4.8.3. Since no other ARMv7-M implementations except the
7771
// Cortex-M7 have a DCACHE or ICACHE at all, it seems safe to do the same thing as the
7872
// CMSIS-Core implementation and use fixed values.
79-
unsafe {
80-
self.dcisw.write(
81-
((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
82-
| ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
83-
);
84-
}
73+
self.dcisw.write(
74+
((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
75+
| ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
76+
);
8577
}
8678

8779
/// D-cache clean by MVA to PoU
88-
#[inline]
80+
#[inline(always)]
8981
pub fn dccmvau(&mut self, mva: u32) {
9082
unsafe {
9183
self.dccmvau.write(mva);
9284
}
9385
}
9486

9587
/// D-cache clean by MVA to PoC
96-
#[inline]
88+
#[inline(always)]
9789
pub fn dccmvac(&mut self, mva: u32) {
9890
unsafe {
9991
self.dccmvac.write(mva);
@@ -103,7 +95,7 @@ impl CBP {
10395
/// D-cache clean by set-way
10496
///
10597
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
106-
#[inline]
98+
#[inline(always)]
10799
pub fn dccsw(&mut self, set: u16, way: u16) {
108100
// See comment for dcisw() about the format here
109101
unsafe {
@@ -115,7 +107,7 @@ impl CBP {
115107
}
116108

117109
/// D-cache clean and invalidate by MVA to PoC
118-
#[inline]
110+
#[inline(always)]
119111
pub fn dccimvac(&mut self, mva: u32) {
120112
unsafe {
121113
self.dccimvac.write(mva);
@@ -125,7 +117,7 @@ impl CBP {
125117
/// D-cache clean and invalidate by set-way
126118
///
127119
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
128-
#[inline]
120+
#[inline(always)]
129121
pub fn dccisw(&mut self, set: u16, way: u16) {
130122
// See comment for dcisw() about the format here
131123
unsafe {
@@ -137,7 +129,7 @@ impl CBP {
137129
}
138130

139131
/// Branch predictor invalidate all
140-
#[inline]
132+
#[inline(always)]
141133
pub fn bpiall(&mut self) {
142134
unsafe {
143135
self.bpiall.write(0);

src/peripheral/cpuid.rs

+24
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,28 @@ impl CPUID {
114114
(1 + ((ccsidr & CCSIDR_ASSOCIATIVITY_MASK) >> CCSIDR_ASSOCIATIVITY_POS)) as u16,
115115
)
116116
}
117+
118+
/// Returns log2 of the number of words in the smallest cache line of all the data cache and
119+
/// unified caches that are controlled by the processor.
120+
///
121+
/// This is the `DminLine` field of the CTR register.
122+
#[inline(always)]
123+
pub fn cache_dminline() -> u32 {
124+
const CTR_DMINLINE_POS: u32 = 16;
125+
const CTR_DMINLINE_MASK: u32 = 0xF << CTR_DMINLINE_POS;
126+
let ctr = unsafe { (*Self::ptr()).ctr.read() };
127+
(ctr & CTR_DMINLINE_MASK) >> CTR_DMINLINE_POS
128+
}
129+
130+
/// Returns log2 of the number of words in the smallest cache line of all the instruction
131+
/// caches that are controlled by the processor.
132+
///
133+
/// This is the `IminLine` field of the CTR register.
134+
#[inline(always)]
135+
pub fn cache_iminline() -> u32 {
136+
const CTR_IMINLINE_POS: u32 = 0;
137+
const CTR_IMINLINE_MASK: u32 = 0xF << CTR_IMINLINE_POS;
138+
let ctr = unsafe { (*Self::ptr()).ctr.read() };
139+
(ctr & CTR_IMINLINE_MASK) >> CTR_IMINLINE_POS
140+
}
117141
}

0 commit comments

Comments
 (0)