stm32f303xc/
syscfg.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use enum_primitive::cast::FromPrimitive;
6use enum_primitive::enum_from_primitive;
7use kernel::platform::chip::ClockInterface;
8use kernel::utilities::registers::interfaces::ReadWriteable;
9use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
10use kernel::utilities::StaticRef;
11
12use crate::gpio;
13use crate::rcc;
14
15/// System configuration controller
16#[repr(C)]
17struct SyscfgRegisters {
18    /// memory remap register
19    memrm: ReadWrite<u32, MEMRM::Register>,
20    /// peripheral mode configuration register
21    pmc: ReadWrite<u32, PMC::Register>,
22    /// external interrupt configuration register 1
23    exticr1: ReadWrite<u32, EXTICR1::Register>,
24    /// external interrupt configuration register 2
25    exticr2: ReadWrite<u32, EXTICR2::Register>,
26    /// external interrupt configuration register 3
27    exticr3: ReadWrite<u32, EXTICR3::Register>,
28    /// external interrupt configuration register 4
29    exticr4: ReadWrite<u32, EXTICR4::Register>,
30    _reserved0: [u8; 8],
31    /// Compensation cell control register
32    cmpcr: ReadOnly<u32, CMPCR::Register>,
33}
34
35register_bitfields![u32,
36    MEMRM [
37        /// Memory mapping selection
38        MEM_MODE OFFSET(0) NUMBITS(3) [],
39        /// Flash bank mode selection
40        FB_MODE OFFSET(8) NUMBITS(1) [],
41        /// FMC memory mapping swap
42        SWP_FMC OFFSET(10) NUMBITS(2) []
43    ],
44    PMC [
45        /// Ethernet PHY interface selection
46        MII_RMII_SEL OFFSET(23) NUMBITS(1) [],
47        /// ADC1DC2
48        ADC1DC2 OFFSET(16) NUMBITS(1) [],
49        /// ADC2DC2
50        ADC2DC2 OFFSET(17) NUMBITS(1) [],
51        /// ADC3DC2
52        ADC3DC2 OFFSET(18) NUMBITS(1) []
53    ],
54    EXTICR1 [
55        /// EXTI x configuration (x = 0 to 3)
56        EXTI3 OFFSET(12) NUMBITS(4) [],
57        /// EXTI x configuration (x = 0 to 3)
58        EXTI2 OFFSET(8) NUMBITS(4) [],
59        /// EXTI x configuration (x = 0 to 3)
60        EXTI1 OFFSET(4) NUMBITS(4) [],
61        /// EXTI x configuration (x = 0 to 3)
62        EXTI0 OFFSET(0) NUMBITS(4) []
63    ],
64    EXTICR2 [
65        /// EXTI x configuration (x = 4 to 7)
66        EXTI7 OFFSET(12) NUMBITS(4) [],
67        /// EXTI x configuration (x = 4 to 7)
68        EXTI6 OFFSET(8) NUMBITS(4) [],
69        /// EXTI x configuration (x = 4 to 7)
70        EXTI5 OFFSET(4) NUMBITS(4) [],
71        /// EXTI x configuration (x = 4 to 7)
72        EXTI4 OFFSET(0) NUMBITS(4) []
73    ],
74    EXTICR3 [
75        /// EXTI x configuration (x = 8 to 11)
76        EXTI11 OFFSET(12) NUMBITS(4) [],
77        /// EXTI10
78        EXTI10 OFFSET(8) NUMBITS(4) [],
79        /// EXTI x configuration (x = 8 to 11)
80        EXTI9 OFFSET(4) NUMBITS(4) [],
81        /// EXTI x configuration (x = 8 to 11)
82        EXTI8 OFFSET(0) NUMBITS(4) []
83    ],
84    EXTICR4 [
85        /// EXTI x configuration (x = 12 to 15)
86        EXTI15 OFFSET(12) NUMBITS(4) [],
87        /// EXTI x configuration (x = 12 to 15)
88        EXTI14 OFFSET(8) NUMBITS(4) [],
89        /// EXTI x configuration (x = 12 to 15)
90        EXTI13 OFFSET(4) NUMBITS(4) [],
91        /// EXTI x configuration (x = 12 to 15)
92        EXTI12 OFFSET(0) NUMBITS(4) []
93    ],
94    CMPCR [
95        /// READY
96        READY OFFSET(8) NUMBITS(1) [],
97        /// Compensation cell power-down
98        CMP_PD OFFSET(0) NUMBITS(1) []
99    ]
100];
101
102const SYSCFG_BASE: StaticRef<SyscfgRegisters> =
103    unsafe { StaticRef::new(0x40010000 as *const SyscfgRegisters) };
104
105enum_from_primitive! {
106    #[repr(u32)]
107    /// SYSCFG EXTI configuration [^1]
108    ///
109    /// [^1]: Section 8.2.2, page 197 of reference manual
110    enum ExtiCrId {
111        PA = 0b0000,
112        PB = 0b0001,
113        PC = 0b0010,
114        PD = 0b0011,
115        PE = 0b0100,
116        PF = 0b0101,
117        PG = 0b0110,
118        PH = 0b0111,
119    }
120}
121
122pub struct Syscfg<'a> {
123    registers: StaticRef<SyscfgRegisters>,
124    clock: SyscfgClock<'a>,
125}
126
127impl<'a> Syscfg<'a> {
128    pub const fn new(rcc: &'a rcc::Rcc) -> Self {
129        Self {
130            registers: SYSCFG_BASE,
131            clock: SyscfgClock(rcc::PeripheralClock::new(
132                rcc::PeripheralClockType::APB2(rcc::PCLK2::SYSCFG),
133                rcc,
134            )),
135        }
136    }
137
138    pub fn is_enabled_clock(&self) -> bool {
139        self.clock.is_enabled()
140    }
141
142    pub fn enable_clock(&self) {
143        self.clock.enable();
144    }
145
146    pub fn disable_clock(&self) {
147        self.clock.disable();
148    }
149
150    /// Configures the SYSCFG_EXTICR{1, 2, 3, 4} registers
151    pub fn configure_interrupt(&self, pinid: gpio::PinId) {
152        let exticrid = self.get_exticrid_from_port_num(pinid.get_port_number());
153
154        let pin_num = pinid.get_pin_number();
155        match pin_num {
156            // SYSCFG_EXTICR1
157            0b0000 => self
158                .registers
159                .exticr1
160                .modify(EXTICR1::EXTI0.val(exticrid as u32)),
161            0b0001 => self
162                .registers
163                .exticr1
164                .modify(EXTICR1::EXTI1.val(exticrid as u32)),
165            0b0010 => self
166                .registers
167                .exticr1
168                .modify(EXTICR1::EXTI2.val(exticrid as u32)),
169            0b0011 => self
170                .registers
171                .exticr1
172                .modify(EXTICR1::EXTI3.val(exticrid as u32)),
173            // SYSCFG_EXTICR2
174            0b0100 => self
175                .registers
176                .exticr2
177                .modify(EXTICR2::EXTI4.val(exticrid as u32)),
178            0b0101 => self
179                .registers
180                .exticr2
181                .modify(EXTICR2::EXTI5.val(exticrid as u32)),
182            0b0110 => self
183                .registers
184                .exticr2
185                .modify(EXTICR2::EXTI6.val(exticrid as u32)),
186            0b0111 => self
187                .registers
188                .exticr2
189                .modify(EXTICR2::EXTI7.val(exticrid as u32)),
190            // SYSCFG_EXTICR3
191            0b1000 => self
192                .registers
193                .exticr3
194                .modify(EXTICR3::EXTI8.val(exticrid as u32)),
195            0b1001 => self
196                .registers
197                .exticr3
198                .modify(EXTICR3::EXTI9.val(exticrid as u32)),
199            0b1010 => self
200                .registers
201                .exticr3
202                .modify(EXTICR3::EXTI10.val(exticrid as u32)),
203            0b1011 => self
204                .registers
205                .exticr3
206                .modify(EXTICR3::EXTI11.val(exticrid as u32)),
207            // SYSCFG_EXTICR4
208            0b1100 => self
209                .registers
210                .exticr4
211                .modify(EXTICR4::EXTI12.val(exticrid as u32)),
212            0b1101 => self
213                .registers
214                .exticr4
215                .modify(EXTICR4::EXTI13.val(exticrid as u32)),
216            0b1110 => self
217                .registers
218                .exticr4
219                .modify(EXTICR4::EXTI14.val(exticrid as u32)),
220            0b1111 => self
221                .registers
222                .exticr4
223                .modify(EXTICR4::EXTI15.val(exticrid as u32)),
224            _ => {}
225        }
226    }
227
228    fn get_exticrid_from_port_num(&self, port_num: u8) -> ExtiCrId {
229        ExtiCrId::from_u32(u32::from(port_num)).unwrap()
230    }
231}
232
233struct SyscfgClock<'a>(rcc::PeripheralClock<'a>);
234
235impl ClockInterface for SyscfgClock<'_> {
236    fn is_enabled(&self) -> bool {
237        self.0.is_enabled()
238    }
239
240    fn enable(&self) {
241        self.0.enable();
242    }
243
244    fn disable(&self) {
245        self.0.disable();
246    }
247}