      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146

    //! Cache and branch predictor maintenance operations
    //!
    //! *NOTE* Available only on ARMv7-M (`thumbv7*m-none-eabi*`)

    use volatile_register::WO;

    use peripheral::CBP;

    /// 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 CBP {
        /// I-cache invalidate all to PoU
        #[inline]
        pub fn iciallu(&mut self) {
            unsafe {
                self.iciallu.write(0);
            }
        }

        /// I-cache invalidate by MVA to PoU
        #[inline]
        pub fn icimvau(&mut self, mva: u32) {
            unsafe {
                self.icimvau.write(mva);
            }
        }

        /// D-cache invalidate by MVA to PoC
        #[inline]
        pub fn dcimvac(&mut 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]
        pub fn dcisw(&mut 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]
        pub fn dccmvau(&mut self, mva: u32) {
            unsafe {
                self.dccmvau.write(mva);
            }
        }

        /// D-cache clean by MVA to PoC
        #[inline]
        pub fn dccmvac(&mut 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]
        pub fn dccsw(&mut 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]
        pub fn dccimvac(&mut 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]
        pub fn dccisw(&mut 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]
        pub fn bpiall(&mut self) {
            unsafe {
                self.bpiall.write(0);
            }
        }
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)