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        self.dcimvac.write(mva);
57    }
58
59    /// D-cache invalidate by set-way
60    ///
61    /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
62    #[inline(always)]
63    pub unsafe fn dcisw(&mut self, set: u16, way: u16) {
64        // The ARMv7-M Architecture Reference Manual, as of Revision E.b, says these set/way
65        // operations have a register data format which depends on the implementation's
66        // associativity and number of sets. Specifically the 'way' and 'set' fields have
67        // offsets 32-log2(ASSOCIATIVITY) and log2(LINELEN) respectively.
68        //
69        // However, in Cortex-M7 devices, these offsets are fixed at 30 and 5, as per the Cortex-M7
70        // Generic User Guide section 4.8.3. Since no other ARMv7-M implementations except the
71        // Cortex-M7 have a DCACHE or ICACHE at all, it seems safe to do the same thing as the
72        // CMSIS-Core implementation and use fixed values.
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        );
77    }
78
79    /// D-cache clean by MVA to PoU
80    #[inline(always)]
81    pub fn dccmvau(&mut self, mva: u32) {
82        unsafe {
83            self.dccmvau.write(mva);
84        }
85    }
86
87    /// D-cache clean by MVA to PoC
88    #[inline(always)]
89    pub fn dccmvac(&mut self, mva: u32) {
90        unsafe {
91            self.dccmvac.write(mva);
92        }
93    }
94
95    /// D-cache clean by set-way
96    ///
97    /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
98    #[inline(always)]
99    pub fn dccsw(&mut self, set: u16, way: u16) {
100        // See comment for dcisw() about the format here
101        unsafe {
102            self.dccsw.write(
103                ((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
104                    | ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
105            );
106        }
107    }
108
109    /// D-cache clean and invalidate by MVA to PoC
110    #[inline(always)]
111    pub fn dccimvac(&mut self, mva: u32) {
112        unsafe {
113            self.dccimvac.write(mva);
114        }
115    }
116
117    /// D-cache clean and invalidate by set-way
118    ///
119    /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
120    #[inline(always)]
121    pub fn dccisw(&mut self, set: u16, way: u16) {
122        // See comment for dcisw() about the format here
123        unsafe {
124            self.dccisw.write(
125                ((u32::from(way) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
126                    | ((u32::from(set) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
127            );
128        }
129    }
130
131    /// Branch predictor invalidate all
132    #[inline(always)]
133    pub fn bpiall(&mut self) {
134        unsafe {
135            self.bpiall.write(0);
136        }
137    }
138}