stm32f4xx/clocks/
phclk.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 crate::clocks::Stm32f4Clocks;
6use crate::rcc::{APBPrescaler, Rcc, RtcClockSource};
7use kernel::platform::chip::ClockInterface;
8
9pub struct PeripheralClock<'a> {
10    pub clock: PeripheralClockType,
11    clocks: &'a dyn Stm32f4Clocks,
12}
13
14/// Bus + Clock name for the peripherals
15pub enum PeripheralClockType {
16    AHB1(HCLK1),
17    AHB2(HCLK2),
18    AHB3(HCLK3),
19    APB1(PCLK1),
20    APB2(PCLK2),
21    RTC,
22    PWR,
23}
24
25/// Peripherals clocked by HCLK1
26pub enum HCLK1 {
27    DMA1,
28    DMA2,
29    GPIOH,
30    GPIOG,
31    GPIOF,
32    GPIOE,
33    GPIOD,
34    GPIOC,
35    GPIOB,
36    GPIOA,
37}
38
39/// Peripherals clocked by HCLK3
40pub enum HCLK3 {
41    FMC,
42}
43
44/// Peripherals clocked by HCLK2
45pub enum HCLK2 {
46    RNG,
47    OTGFS,
48}
49
50/// Peripherals clocked by PCLK1
51pub enum PCLK1 {
52    TIM2,
53    USART2,
54    USART3,
55    SPI3,
56    I2C1,
57    CAN1,
58    DAC,
59}
60
61/// Peripherals clocked by PCLK2
62pub enum PCLK2 {
63    USART1,
64    ADC1,
65    SYSCFG,
66}
67
68impl<'a> PeripheralClock<'a> {
69    pub const fn new(clock: PeripheralClockType, clocks: &'a dyn Stm32f4Clocks) -> Self {
70        Self { clock, clocks }
71    }
72
73    pub fn configure_rng_clock(&self) {
74        self.clocks.get_rcc().configure_rng_clock();
75    }
76
77    pub fn get_frequency(&self) -> u32 {
78        #[inline(always)]
79        fn tim_freq(rcc: &Rcc, hclk_freq: usize, prescaler: APBPrescaler) -> usize {
80            // Reference Manual RM0090 section 6.2
81            // When TIMPRE bit of the RCC_DCKCFGR register is reset, if APBx prescaler is 1, then
82            // TIMxCLK = PCLKx, otherwise TIMxCLK = 2x PCLKx.
83            // When TIMPRE bit in the RCC_DCKCFGR register is set, if APBx prescaler is 1,2 or 4,
84            // then TIMxCLK = HCLK, otherwise TIMxCLK = 4x PCLKx.
85            if !rcc.is_enabled_tim_pre() {
86                match prescaler {
87                    APBPrescaler::DivideBy1 | APBPrescaler::DivideBy2 => hclk_freq,
88                    _ => hclk_freq / usize::from(prescaler) * 2,
89                }
90            } else {
91                match prescaler {
92                    APBPrescaler::DivideBy1 | APBPrescaler::DivideBy2 | APBPrescaler::DivideBy4 => {
93                        hclk_freq
94                    }
95                    _ => hclk_freq / usize::from(prescaler) * 4,
96                }
97            }
98        }
99        let rcc = self.clocks.get_rcc();
100        let hclk_freq = self.clocks.get_ahb_frequency();
101        match self.clock {
102            PeripheralClockType::AHB1(_)
103            | PeripheralClockType::AHB2(_)
104            | PeripheralClockType::AHB3(_) => hclk_freq as u32,
105            PeripheralClockType::APB1(ref v) => {
106                let prescaler = rcc.get_apb1_prescaler();
107                match v {
108                    PCLK1::TIM2 => tim_freq(rcc, hclk_freq, prescaler) as u32,
109                    _ => (hclk_freq / usize::from(prescaler)) as u32,
110                }
111            }
112            PeripheralClockType::APB2(_) => {
113                let prescaler = rcc.get_apb2_prescaler();
114                (hclk_freq / usize::from(prescaler)) as u32
115            }
116            //TODO: implement clock frequency retrieval for RTC and PWR peripherals
117            PeripheralClockType::RTC => todo!(),
118            PeripheralClockType::PWR => todo!(),
119        }
120    }
121}
122
123impl ClockInterface for PeripheralClock<'_> {
124    fn is_enabled(&self) -> bool {
125        let rcc = self.clocks.get_rcc();
126        match self.clock {
127            PeripheralClockType::AHB1(ref v) => match v {
128                HCLK1::DMA1 => rcc.is_enabled_dma1_clock(),
129                HCLK1::DMA2 => rcc.is_enabled_dma2_clock(),
130                HCLK1::GPIOH => rcc.is_enabled_gpioh_clock(),
131                HCLK1::GPIOG => rcc.is_enabled_gpiog_clock(),
132                HCLK1::GPIOF => rcc.is_enabled_gpiof_clock(),
133                HCLK1::GPIOE => rcc.is_enabled_gpioe_clock(),
134                HCLK1::GPIOD => rcc.is_enabled_gpiod_clock(),
135                HCLK1::GPIOC => rcc.is_enabled_gpioc_clock(),
136                HCLK1::GPIOB => rcc.is_enabled_gpiob_clock(),
137                HCLK1::GPIOA => rcc.is_enabled_gpioa_clock(),
138            },
139            PeripheralClockType::AHB2(ref v) => match v {
140                HCLK2::RNG => rcc.is_enabled_rng_clock(),
141                HCLK2::OTGFS => rcc.is_enabled_otgfs_clock(),
142            },
143            PeripheralClockType::AHB3(ref v) => match v {
144                HCLK3::FMC => rcc.is_enabled_fmc_clock(),
145            },
146            PeripheralClockType::APB1(ref v) => match v {
147                PCLK1::TIM2 => rcc.is_enabled_tim2_clock(),
148                PCLK1::USART2 => rcc.is_enabled_usart2_clock(),
149                PCLK1::USART3 => rcc.is_enabled_usart3_clock(),
150                PCLK1::I2C1 => rcc.is_enabled_i2c1_clock(),
151                PCLK1::SPI3 => rcc.is_enabled_spi3_clock(),
152                PCLK1::CAN1 => rcc.is_enabled_can1_clock(),
153                PCLK1::DAC => rcc.is_enabled_dac_clock(),
154            },
155            PeripheralClockType::APB2(ref v) => match v {
156                PCLK2::USART1 => rcc.is_enabled_usart1_clock(),
157                PCLK2::ADC1 => rcc.is_enabled_adc1_clock(),
158                PCLK2::SYSCFG => rcc.is_enabled_syscfg_clock(),
159            },
160            PeripheralClockType::RTC => rcc.is_enabled_rtc_clock(),
161            PeripheralClockType::PWR => rcc.is_enabled_pwr_clock(),
162        }
163    }
164
165    fn enable(&self) {
166        let rcc = self.clocks.get_rcc();
167        match self.clock {
168            PeripheralClockType::AHB1(ref v) => match v {
169                HCLK1::DMA1 => {
170                    rcc.enable_dma1_clock();
171                }
172                HCLK1::DMA2 => {
173                    rcc.enable_dma2_clock();
174                }
175                HCLK1::GPIOH => {
176                    rcc.enable_gpioh_clock();
177                }
178                HCLK1::GPIOG => {
179                    rcc.enable_gpiog_clock();
180                }
181                HCLK1::GPIOF => {
182                    rcc.enable_gpiof_clock();
183                }
184                HCLK1::GPIOE => {
185                    rcc.enable_gpioe_clock();
186                }
187                HCLK1::GPIOD => {
188                    rcc.enable_gpiod_clock();
189                }
190                HCLK1::GPIOC => {
191                    rcc.enable_gpioc_clock();
192                }
193                HCLK1::GPIOB => {
194                    rcc.enable_gpiob_clock();
195                }
196                HCLK1::GPIOA => {
197                    rcc.enable_gpioa_clock();
198                }
199            },
200            PeripheralClockType::AHB2(ref v) => match v {
201                HCLK2::RNG => {
202                    rcc.enable_rng_clock();
203                }
204                HCLK2::OTGFS => {
205                    rcc.enable_otgfs_clock();
206                }
207            },
208            PeripheralClockType::AHB3(ref v) => match v {
209                HCLK3::FMC => rcc.enable_fmc_clock(),
210            },
211            PeripheralClockType::APB1(ref v) => match v {
212                PCLK1::TIM2 => {
213                    rcc.enable_tim2_clock();
214                }
215                PCLK1::USART2 => {
216                    rcc.enable_usart2_clock();
217                }
218                PCLK1::USART3 => {
219                    rcc.enable_usart3_clock();
220                }
221                PCLK1::I2C1 => {
222                    rcc.enable_i2c1_clock();
223                }
224                PCLK1::SPI3 => {
225                    rcc.enable_spi3_clock();
226                }
227                PCLK1::CAN1 => {
228                    rcc.enable_can1_clock();
229                }
230                PCLK1::DAC => {
231                    rcc.enable_dac_clock();
232                }
233            },
234            PeripheralClockType::APB2(ref v) => match v {
235                PCLK2::USART1 => {
236                    rcc.enable_usart1_clock();
237                }
238                PCLK2::ADC1 => {
239                    rcc.enable_adc1_clock();
240                }
241                PCLK2::SYSCFG => {
242                    rcc.enable_syscfg_clock();
243                }
244            },
245            PeripheralClockType::RTC => rcc.enable_rtc_clock(RtcClockSource::LSI),
246            PeripheralClockType::PWR => rcc.enable_pwr_clock(),
247        }
248    }
249
250    fn disable(&self) {
251        let rcc = self.clocks.get_rcc();
252        match self.clock {
253            PeripheralClockType::AHB1(ref v) => match v {
254                HCLK1::DMA1 => {
255                    rcc.disable_dma1_clock();
256                }
257                HCLK1::DMA2 => {
258                    rcc.disable_dma2_clock();
259                }
260                HCLK1::GPIOH => {
261                    rcc.disable_gpioh_clock();
262                }
263                HCLK1::GPIOG => {
264                    rcc.disable_gpiog_clock();
265                }
266                HCLK1::GPIOF => {
267                    rcc.disable_gpiof_clock();
268                }
269                HCLK1::GPIOE => {
270                    rcc.disable_gpioe_clock();
271                }
272                HCLK1::GPIOD => {
273                    rcc.disable_gpiod_clock();
274                }
275                HCLK1::GPIOC => {
276                    rcc.disable_gpioc_clock();
277                }
278                HCLK1::GPIOB => {
279                    rcc.disable_gpiob_clock();
280                }
281                HCLK1::GPIOA => {
282                    rcc.disable_gpioa_clock();
283                }
284            },
285            PeripheralClockType::AHB2(ref v) => match v {
286                HCLK2::RNG => {
287                    rcc.disable_rng_clock();
288                }
289                HCLK2::OTGFS => {
290                    rcc.disable_otgfs_clock();
291                }
292            },
293            PeripheralClockType::AHB3(ref v) => match v {
294                HCLK3::FMC => rcc.disable_fmc_clock(),
295            },
296            PeripheralClockType::APB1(ref v) => match v {
297                PCLK1::TIM2 => {
298                    rcc.disable_tim2_clock();
299                }
300                PCLK1::USART2 => {
301                    rcc.disable_usart2_clock();
302                }
303                PCLK1::USART3 => {
304                    rcc.disable_usart3_clock();
305                }
306                PCLK1::I2C1 => {
307                    rcc.disable_i2c1_clock();
308                }
309                PCLK1::SPI3 => {
310                    rcc.disable_spi3_clock();
311                }
312                PCLK1::CAN1 => {
313                    rcc.disable_can1_clock();
314                }
315                PCLK1::DAC => {
316                    rcc.disable_dac_clock();
317                }
318            },
319            PeripheralClockType::APB2(ref v) => match v {
320                PCLK2::USART1 => {
321                    rcc.disable_usart1_clock();
322                }
323                PCLK2::ADC1 => {
324                    rcc.disable_adc1_clock();
325                }
326                PCLK2::SYSCFG => {
327                    rcc.disable_syscfg_clock();
328                }
329            },
330            PeripheralClockType::RTC => rcc.disable_rtc_clock(),
331            PeripheralClockType::PWR => rcc.disable_pwr_clock(),
332        }
333    }
334}