Skip to content

Commit 1044336

Browse files
committed
hw/mcu/stm32f4: Add PLL helper functions
This adds several function for PLL frequency checking. Signed-off-by: Jerzy Kasenberg <jerzy@apache.org>
1 parent d19b64f commit 1044336

File tree

2 files changed

+169
-2
lines changed

2 files changed

+169
-2
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#ifndef __MCU_CLOCK_STM32F4XX_H_
21+
#define __MCU_CLOCK_STM32F4XX_H_
22+
23+
#include <stdint.h>
24+
#include <stm32_common/mcu.h>
25+
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif
29+
30+
/**
31+
* Return PLL VCO frequency
32+
*
33+
* @return PLL VCO frequency
34+
*/
35+
uint32_t stm32f4xx_pll_vco_freq(void);
36+
37+
/**
38+
* Return PLLI2S VCO frequency
39+
*
40+
* @return PLLI2S VCO frequency
41+
*/
42+
uint32_t stm32f4xx_plli2s_vco_freq(void);
43+
44+
/**
45+
* Return PLL P frequency (can be SYSCLK)
46+
*
47+
* @return PLL P frequency
48+
*/
49+
uint32_t stm32f4xx_pll_p_freq(void);
50+
51+
/**
52+
* Return PLL Q frequency (usually 48MHz)
53+
*
54+
* @return PLL Q frequency
55+
*/
56+
uint32_t stm32f4xx_pll_q_freq(void);
57+
58+
/**
59+
* Return PLL R frequency
60+
*
61+
* @return PLL R frequency
62+
*/
63+
uint32_t stm32f4xx_pll_r_freq(void);
64+
65+
/**
66+
* Return PLLI2S Q frequency
67+
*
68+
* @return PLLI2S Q frequency
69+
*/
70+
uint32_t stm32f4xx_plli2s_q_freq(void);
71+
72+
/**
73+
* Return PLLI2S R frequency
74+
*
75+
* @return PLLI2S R frequency
76+
*/
77+
uint32_t stm32f4xx_plli2s_r_freq(void);
78+
79+
#ifdef __cplusplus
80+
}
81+
#endif
82+
83+
#endif /* __MCU_CLOCK_STM32F4XX_H_ */

hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,93 @@
2424
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525
*/
2626

27-
#include "stm32f4xx_hal_pwr_ex.h"
28-
#include "stm32f4xx_hal.h"
2927
#include <assert.h>
28+
#include <stm32f4xx_hal_pwr_ex.h>
29+
#include <stm32f4xx_hal.h>
30+
#include <mcu/clock_stm32f4xx.h>
31+
32+
#define FIELD_VAL(per, reg, field) \
33+
((per->reg & per##_##reg##_##field##_Msk) >> per##_##reg##_##field##_Pos)
34+
35+
uint32_t
36+
stm32f4xx_pll_vco_freq(void)
37+
{
38+
uint32_t pll_vco;
39+
uint32_t pll_source_freq;
40+
uint32_t pll_m;
41+
42+
pll_source_freq = FIELD_VAL(RCC, PLLCFGR, PLLSRC) ? HSE_VALUE : HSI_VALUE;
43+
pll_m = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
44+
45+
pll_vco = (pll_source_freq / pll_m) * FIELD_VAL(RCC, PLLCFGR, PLLN);
46+
47+
return pll_vco;
48+
}
49+
50+
uint32_t
51+
stm32f4xx_plli2s_vco_freq(void)
52+
{
53+
uint32_t pll_vco;
54+
uint32_t pll_source_freq;
55+
uint32_t pll_m;
56+
57+
#ifdef RCC_PLLI2SCFGR_PLLI2SSRC
58+
pll_source_freq = FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SSRC) ? HSE_VALUE : HSI_VALUE;
59+
pll_m = FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SM);
60+
#else
61+
pll_source_freq = FIELD_VAL(RCC, PLLCFGR, PLLSRC) ? HSE_VALUE : HSI_VALUE;
62+
pll_m = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
63+
#endif
64+
65+
pll_vco = (pll_source_freq / pll_m);
66+
pll_vco *= FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SN);
67+
68+
return pll_vco;
69+
}
70+
71+
uint32_t
72+
stm32f4xx_pll_p_freq(void)
73+
{
74+
uint32_t pll_p = (FIELD_VAL(RCC, PLLCFGR, PLLP) + 1) * 2;
75+
76+
return stm32f4xx_pll_vco_freq() / pll_p;
77+
}
78+
79+
uint32_t
80+
stm32f4xx_pll_q_freq(void)
81+
{
82+
uint32_t pll_q = FIELD_VAL(RCC, PLLCFGR, PLLQ);
83+
84+
return stm32f4xx_pll_vco_freq() / pll_q;
85+
}
86+
87+
#ifdef RCC_PLLCFGR_PLLR
88+
uint32_t
89+
stm32f4xx_pll_r_freq(void)
90+
{
91+
uint32_t pll_r = FIELD_VAL(RCC, PLLCFGR, PLLR);
92+
93+
return stm32f4xx_pll_vco_freq() / pll_r;
94+
}
95+
#endif
96+
97+
#ifdef RCC_PLLI2SCFGR_PLLP
98+
uint32_t
99+
stm32f4xx_plli2s_p_freq(void)
100+
{
101+
uint32_t pll_p = (FIELD_VAL(RCC, PLLI2SCFGR, PLLP) + 1) * 2;
102+
103+
return stm32f4xx_plli2s_vco_freq() / pll_p;
104+
}
105+
#endif
106+
107+
uint32_t
108+
stm32f4xx_plli2s_r_freq(void)
109+
{
110+
uint32_t pll_r = FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SR);
111+
112+
return stm32f4xx_pll_vco_freq() / pll_r;
113+
}
30114

31115
/*
32116
* This allows an user to have a custom clock configuration by zeroing

0 commit comments

Comments
 (0)