Skip to main content

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}