aboutsummaryrefslogtreecommitdiff
path: root/src/peripheral/cbp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/peripheral/cbp.rs')
-rw-r--r--src/peripheral/cbp.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/peripheral/cbp.rs b/src/peripheral/cbp.rs
new file mode 100644
index 0000000..3397fff
--- /dev/null
+++ b/src/peripheral/cbp.rs
@@ -0,0 +1,142 @@
+//! Cache and branch predictor maintenance operations
+
+use volatile_register::WO;
+
+/// Register block
+#[repr(C)]
+pub struct RegisterBlock {
+ /// I-cache invalidate all to PoU
+ pub iciallu: WO<u32>,
+ reserved0: u32,
+ /// I-cache invalidate by MVA to PoU
+ pub icimvau: WO<u32>,
+ /// D-cache invalidate by MVA to PoC
+ pub dcimvac: WO<u32>,
+ /// D-cache invalidate by set-way
+ pub dcisw: WO<u32>,
+ /// D-cache clean by MVA to PoU
+ pub dccmvau: WO<u32>,
+ /// D-cache clean by MVA to PoC
+ pub dccmvac: WO<u32>,
+ /// D-cache clean by set-way
+ pub dccsw: WO<u32>,
+ /// D-cache clean and invalidate by MVA to PoC
+ pub dccimvac: WO<u32>,
+ /// D-cache clean and invalidate by set-way
+ pub dccisw: WO<u32>,
+ /// Branch predictor invalidate all
+ pub bpiall: WO<u32>,
+}
+
+const CBP_SW_WAY_POS: u32 = 30;
+const CBP_SW_WAY_MASK: u32 = 0x3 << CBP_SW_WAY_POS;
+const CBP_SW_SET_POS: u32 = 5;
+const CBP_SW_SET_MASK: u32 = 0x1FF << CBP_SW_SET_POS;
+
+impl RegisterBlock {
+ /// I-cache invalidate all to PoU
+ #[inline(always)]
+ pub fn iciallu(&self) {
+ unsafe {
+ self.iciallu.write(0);
+ }
+ }
+
+ /// I-cache invalidate by MVA to PoU
+ #[inline(always)]
+ pub fn icimvau(&self, mva: u32) {
+ unsafe {
+ self.icimvau.write(mva);
+ }
+ }
+
+ /// D-cache invalidate by MVA to PoC
+ #[inline(always)]
+ pub fn dcimvac(&self, mva: u32) {
+ unsafe {
+ self.dcimvac.write(mva);
+ }
+ }
+
+ /// D-cache invalidate by set-way
+ ///
+ /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
+ #[inline(always)]
+ pub fn dcisw(&self, set: u16, way: u16) {
+ // The ARMv7-M Architecture Reference Manual, as of Revision E.b, says these set/way
+ // operations have a register data format which depends on the implementation's
+ // associativity and number of sets. Specifically the 'way' and 'set' fields have
+ // offsets 32-log2(ASSOCIATIVITY) and log2(LINELEN) respectively.
+ //
+ // However, in Cortex-M7 devices, these offsets are fixed at 30 and 5, as per the Cortex-M7
+ // Generic User Guide section 4.8.3. Since no other ARMv7-M implementations except the
+ // Cortex-M7 have a DCACHE or ICACHE at all, it seems safe to do the same thing as the
+ // CMSIS-Core implementation and use fixed values.
+ unsafe {
+ self.dcisw.write(
+ (((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
+ | (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
+ );
+ }
+ }
+
+ /// D-cache clean by MVA to PoU
+ #[inline(always)]
+ pub fn dccmvau(&self, mva: u32) {
+ unsafe {
+ self.dccmvau.write(mva);
+ }
+ }
+
+ /// D-cache clean by MVA to PoC
+ #[inline(always)]
+ pub fn dccmvac(&self, mva: u32) {
+ unsafe {
+ self.dccmvac.write(mva);
+ }
+ }
+
+ /// D-cache clean by set-way
+ ///
+ /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
+ #[inline(always)]
+ pub fn dccsw(&self, set: u16, way: u16) {
+ // See comment for dcisw() about the format here
+ unsafe {
+ self.dccsw.write(
+ (((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
+ | (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
+ );
+ }
+ }
+
+ /// D-cache clean and invalidate by MVA to PoC
+ #[inline(always)]
+ pub fn dccimvac(&self, mva: u32) {
+ unsafe {
+ self.dccimvac.write(mva);
+ }
+ }
+
+ /// D-cache clean and invalidate by set-way
+ ///
+ /// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
+ #[inline(always)]
+ pub fn dccisw(&self, set: u16, way: u16) {
+ // See comment for dcisw() about the format here
+ unsafe {
+ self.dccisw.write(
+ (((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
+ | (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
+ );
+ }
+ }
+
+ /// Branch predictor invalidate all
+ #[inline(always)]
+ pub fn bpiall(&self) {
+ unsafe {
+ self.bpiall.write(0);
+ }
+ }
+}