cortex_m/peripheral/
cpuid.rs

1//! CPUID
2
3use volatile_register::RO;
4#[cfg(not(armv6m))]
5use volatile_register::RW;
6
7#[cfg(not(armv6m))]
8use crate::peripheral::CPUID;
9
10/// Register block
11#[repr(C)]
12pub struct RegisterBlock {
13    /// CPUID base
14    pub base: RO<u32>,
15
16    _reserved0: [u32; 15],
17
18    /// Processor Feature (not present on Cortex-M0 variants)
19    #[cfg(not(armv6m))]
20    pub pfr: [RO<u32>; 2],
21    #[cfg(armv6m)]
22    _reserved1: [u32; 2],
23
24    /// Debug Feature (not present on Cortex-M0 variants)
25    #[cfg(not(armv6m))]
26    pub dfr: RO<u32>,
27    #[cfg(armv6m)]
28    _reserved2: u32,
29
30    /// Auxiliary Feature (not present on Cortex-M0 variants)
31    #[cfg(not(armv6m))]
32    pub afr: RO<u32>,
33    #[cfg(armv6m)]
34    _reserved3: u32,
35
36    /// Memory Model Feature (not present on Cortex-M0 variants)
37    #[cfg(not(armv6m))]
38    pub mmfr: [RO<u32>; 4],
39    #[cfg(armv6m)]
40    _reserved4: [u32; 4],
41
42    /// Instruction Set Attribute (not present on Cortex-M0 variants)
43    #[cfg(not(armv6m))]
44    pub isar: [RO<u32>; 5],
45    #[cfg(armv6m)]
46    _reserved5: [u32; 5],
47
48    _reserved6: u32,
49
50    /// Cache Level ID (only present on Cortex-M7)
51    #[cfg(not(armv6m))]
52    pub clidr: RO<u32>,
53
54    /// Cache Type (only present on Cortex-M7)
55    #[cfg(not(armv6m))]
56    pub ctr: RO<u32>,
57
58    /// Cache Size ID (only present on Cortex-M7)
59    #[cfg(not(armv6m))]
60    pub ccsidr: RO<u32>,
61
62    /// Cache Size Selection (only present on Cortex-M7)
63    #[cfg(not(armv6m))]
64    pub csselr: RW<u32>,
65}
66
67/// Type of cache to select on CSSELR writes.
68#[cfg(not(armv6m))]
69#[derive(Copy, Clone, Debug, PartialEq, Eq)]
70pub enum CsselrCacheType {
71    /// Select DCache or unified cache
72    DataOrUnified = 0,
73    /// Select ICache
74    Instruction = 1,
75}
76
77#[cfg(not(armv6m))]
78impl CPUID {
79    /// Selects the current CCSIDR
80    ///
81    /// * `level`: the required cache level minus 1, e.g. 0 for L1, 1 for L2
82    /// * `ind`: select instruction cache or data/unified cache
83    ///
84    /// `level` is masked to be between 0 and 7.
85    #[inline]
86    pub fn select_cache(&mut self, level: u8, ind: CsselrCacheType) {
87        const CSSELR_IND_POS: u32 = 0;
88        const CSSELR_IND_MASK: u32 = 1 << CSSELR_IND_POS;
89        const CSSELR_LEVEL_POS: u32 = 1;
90        const CSSELR_LEVEL_MASK: u32 = 0x7 << CSSELR_LEVEL_POS;
91
92        unsafe {
93            self.csselr.write(
94                ((u32::from(level) << CSSELR_LEVEL_POS) & CSSELR_LEVEL_MASK)
95                    | (((ind as u32) << CSSELR_IND_POS) & CSSELR_IND_MASK),
96            )
97        }
98    }
99
100    /// Returns the number of sets and ways in the selected cache
101    #[inline]
102    pub fn cache_num_sets_ways(&mut self, level: u8, ind: CsselrCacheType) -> (u16, u16) {
103        const CCSIDR_NUMSETS_POS: u32 = 13;
104        const CCSIDR_NUMSETS_MASK: u32 = 0x7FFF << CCSIDR_NUMSETS_POS;
105        const CCSIDR_ASSOCIATIVITY_POS: u32 = 3;
106        const CCSIDR_ASSOCIATIVITY_MASK: u32 = 0x3FF << CCSIDR_ASSOCIATIVITY_POS;
107
108        self.select_cache(level, ind);
109        crate::asm::dsb();
110        let ccsidr = self.ccsidr.read();
111        (
112            (1 + ((ccsidr & CCSIDR_NUMSETS_MASK) >> CCSIDR_NUMSETS_POS)) as u16,
113            (1 + ((ccsidr & CCSIDR_ASSOCIATIVITY_MASK) >> CCSIDR_ASSOCIATIVITY_POS)) as u16,
114        )
115    }
116
117    /// Returns log2 of the number of words in the smallest cache line of all the data cache and
118    /// unified caches that are controlled by the processor.
119    ///
120    /// This is the `DminLine` field of the CTR register.
121    #[inline(always)]
122    pub fn cache_dminline() -> u32 {
123        const CTR_DMINLINE_POS: u32 = 16;
124        const CTR_DMINLINE_MASK: u32 = 0xF << CTR_DMINLINE_POS;
125        let ctr = unsafe { (*Self::PTR).ctr.read() };
126        (ctr & CTR_DMINLINE_MASK) >> CTR_DMINLINE_POS
127    }
128
129    /// Returns log2 of the number of words in the smallest cache line of all the instruction
130    /// caches that are controlled by the processor.
131    ///
132    /// This is the `IminLine` field of the CTR register.
133    #[inline(always)]
134    pub fn cache_iminline() -> u32 {
135        const CTR_IMINLINE_POS: u32 = 0;
136        const CTR_IMINLINE_MASK: u32 = 0xF << CTR_IMINLINE_POS;
137        let ctr = unsafe { (*Self::PTR).ctr.read() };
138        (ctr & CTR_IMINLINE_MASK) >> CTR_IMINLINE_POS
139    }
140}