cortex_m/peripheral/cbp.rs
1//! Cache and branch predictor maintenance operations
2//!
3//! *NOTE* Not available on Armv6-M.
4
5use volatile_register::WO;
6
7use crate::peripheral::CBP;
8
9/// Register block
10#[repr(C)]
11pub struct RegisterBlock {
12 /// I-cache invalidate all to PoU
13 pub iciallu: WO<u32>,
14 reserved0: u32,
15 /// I-cache invalidate by MVA to PoU
16 pub icimvau: WO<u32>,
17 /// D-cache invalidate by MVA to PoC
18 pub dcimvac: WO<u32>,
19 /// D-cache invalidate by set-way
20 pub dcisw: WO<u32>,
21 /// D-cache clean by MVA to PoU
22 pub dccmvau: WO<u32>,
23 /// D-cache clean by MVA to PoC
24 pub dccmvac: WO<u32>,
25 /// D-cache clean by set-way
26 pub dccsw: WO<u32>,
27 /// D-cache clean and invalidate by MVA to PoC
28 pub dccimvac: WO<u32>,
29 /// D-cache clean and invalidate by set-way
30 pub dccisw: WO<u32>,
31 /// Branch predictor invalidate all
32 pub bpiall: WO<u32>,
33}
34
35const CBP_SW_WAY_POS: u32 = 30;
36const CBP_SW_WAY_MASK: u32 = 0x3 << CBP_SW_WAY_POS;
37const CBP_SW_SET_POS: u32 = 5;
38const CBP_SW_SET_MASK: u32 = 0x1FF << CBP_SW_SET_POS;
39
40impl CBP {
41 /// I-cache invalidate all to PoU
42 #[inline(always)]
43 pub fn iciallu(&mut self) {
44 unsafe { self.iciallu.write(0) };
45 }
46
47 /// I-cache invalidate by MVA to PoU
48 #[inline(always)]
49 pub fn icimvau(&mut self, mva: u32) {
50 unsafe { self.icimvau.write(mva) };
51 }
52
53 /// D-cache invalidate by MVA to PoC
54 #[inline(always)]
55 pub unsafe fn dcimvac(&mut self, mva: u32) {
56 unsafe {
57 self.dcimvac.write(mva);
58 }
59 }
60
61 /// D-cache invalidate by set-way
62 ///
63 /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
64 #[inline(always)]
65 pub unsafe fn dcisw(&mut self, set: u16, way: u16) {
66 unsafe {
67 // The ARMv7-M Architecture Reference Manual, as of Revision E.b, says these set/way
68 // operations have a register data format which depends on the implementation's
69 // associativity and number of sets. Specifically the 'way' and 'set' fields have
70 // offsets 32-log2(ASSOCIATIVITY) and log2(LINELEN) respectively.
71 //
72 // However, in Cortex-M7 devices, these offsets are fixed at 30 and 5, as per the Cortex-M7
73 // Generic User Guide section 4.8.3. Since no other ARMv7-M implementations except the
74 // Cortex-M7 have a DCACHE or ICACHE at all, it seems safe to do the same thing as the
75 // CMSIS-Core implementation and use fixed values.
76 self.dcisw.write(
77 ((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
78 | ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
79 );
80 }
81 }
82
83 /// D-cache clean by MVA to PoU
84 #[inline(always)]
85 pub fn dccmvau(&mut self, mva: u32) {
86 unsafe {
87 self.dccmvau.write(mva);
88 }
89 }
90
91 /// D-cache clean by MVA to PoC
92 #[inline(always)]
93 pub fn dccmvac(&mut self, mva: u32) {
94 unsafe {
95 self.dccmvac.write(mva);
96 }
97 }
98
99 /// D-cache clean by set-way
100 ///
101 /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
102 #[inline(always)]
103 pub fn dccsw(&mut self, set: u16, way: u16) {
104 // See comment for dcisw() about the format here
105 unsafe {
106 self.dccsw.write(
107 ((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
108 | ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
109 );
110 }
111 }
112
113 /// D-cache clean and invalidate by MVA to PoC
114 #[inline(always)]
115 pub fn dccimvac(&mut self, mva: u32) {
116 unsafe {
117 self.dccimvac.write(mva);
118 }
119 }
120
121 /// D-cache clean and invalidate by set-way
122 ///
123 /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
124 #[inline(always)]
125 pub fn dccisw(&mut self, set: u16, way: u16) {
126 // See comment for dcisw() about the format here
127 unsafe {
128 self.dccisw.write(
129 ((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
130 | ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
131 );
132 }
133 }
134
135 /// Branch predictor invalidate all
136 #[inline(always)]
137 pub fn bpiall(&mut self) {
138 unsafe {
139 self.bpiall.write(0);
140 }
141 }
142}