1 | //! CPUID |
2 | |
3 | use volatile_register::RO; |
4 | #[cfg (not(armv6m))] |
5 | use volatile_register::RW; |
6 | |
7 | #[cfg (not(armv6m))] |
8 | use crate::peripheral::CPUID; |
9 | |
10 | /// Register block |
11 | #[repr (C)] |
12 | pub 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)] |
70 | pub enum CsselrCacheType { |
71 | /// Select DCache or unified cache |
72 | DataOrUnified = 0, |
73 | /// Select ICache |
74 | Instruction = 1, |
75 | } |
76 | |
77 | #[cfg (not(armv6m))] |
78 | impl 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 | } |
141 | |