Skip to content

Commit 5d405da

Browse files
Autogen PLL values in STM32F2/4 for any freq
1 parent b43d00a commit 5d405da

File tree

8 files changed

+351
-63
lines changed

8 files changed

+351
-63
lines changed

stm32f2/Makefile.stm32f2

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,8 @@ LDFLAGS += --specs=nosys.specs -T $(HALPATH)/stm32f2/LinkerScript.ld -Wl,--gc-s
3434
ifneq ($(UART_INITBAUD),)
3535
CDEFS += -DUART_INITBAUD=$(UART_INITBAUD)
3636
CPPDEFS += -DUART_INITBAUD=$(UART_INITBAUD)
37-
endif
37+
endif
38+
39+
PLL_SCRIPT := "infreq=($(F_CPU))/1e6; print('{} {} {} {}'.format(int(infreq*1e6), *min(((m, n, q) for m in range(2, 64) if 0.95 <= (f1 := infreq / m) <= 2.10 for n in range(192, 433) if 192 <= (f2 := f1 * n) <= 432 for q in range(2, 16) if 0 <= (f := f2 / q) <= 48), key=lambda x: abs(infreq / x[0] * x[1] / x[2] - 48))))"
40+
PLL_VALUES := $(shell python3 -c $(PLL_SCRIPT))
41+
CDEFS += -DHSE_VALUE=$(word 1, $(PLL_VALUES))U -DHSE_PLLM_VALUE=$(word 2, $(PLL_VALUES))U -DHSE_PLLN_VALUE=$(word 3, $(PLL_VALUES))U -DHSE_PLLQ_VALUE=$(word 4, $(PLL_VALUES))U

stm32f2/stm32f2_hal.c

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,7 @@
77
#include "stm32f2xx_hal_uart.h"
88
#include "stm32f2xx_hal_rng.h"
99

10-
#ifndef UART_INITBAUD
11-
#if SS_VER==SS_VER_2_1
12-
#define UART_INITBAUD 230400
13-
#else
14-
#define UART_INITBAUD 38400
15-
#endif
16-
#endif
10+
1711

1812
RNG_HandleTypeDef RngHandle;
1913
UART_HandleTypeDef UartHandle;
@@ -22,7 +16,7 @@ void platform_init(void)
2216
{
2317
//HAL_Init();
2418

25-
#ifdef USE_INTERNAL_CLK
19+
#if defined(USE_INTERNAL_CLK)
2620
RCC_OscInitTypeDef RCC_OscInitStruct;
2721
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
2822
RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
@@ -41,30 +35,29 @@ void platform_init(void)
4135
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
4236
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
4337
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
44-
uint32_t flash_latency = 0;
45-
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, flash_latency);
46-
#elif USE_PLL
38+
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_ACR_LATENCY_0WS); // wait states not needed for < 30MHz
39+
#elif defined(USE_PLL)
4740
RCC_OscInitTypeDef RCC_OscInitStruct;
4841
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI;
4942
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
5043
RCC_OscInitStruct.HSIState = RCC_HSI_ON; // HSI is needed for the RNG
5144
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // we need PLL to use RNG
5245
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
53-
RCC_OscInitStruct.PLL.PLLM = 7; // External clock is 7.3728MHz
54-
RCC_OscInitStruct.PLL.PLLN = 319;
55-
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8;
56-
RCC_OscInitStruct.PLL.PLLQ = 7; // divisor for RNG, USB and SDIO
46+
RCC_OscInitStruct.PLL.PLLM = HSE_PLLM_VALUE;
47+
RCC_OscInitStruct.PLL.PLLN = HSE_PLLN_VALUE;
48+
RCC_OscInitStruct.PLL.PLLP = HSE_PLLP_VALUE;
49+
RCC_OscInitStruct.PLL.PLLQ = HSE_PLLQ_VALUE; // divisor for RNG, USB and SDIO
5750
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
5851
for(;;);
5952
}
6053

6154
RCC_ClkInitTypeDef RCC_ClkInitStruct;
6255
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
6356
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
64-
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
65-
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
66-
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
67-
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_ACR_LATENCY_1WS); // 1 wait state needed for < 60MHz
57+
RCC_ClkInitStruct.AHBCLKDivider = HSE_AHBCLKDIV_HVALUE;
58+
RCC_ClkInitStruct.APB1CLKDivider = HSE_APB1CLKDIV_HVALUE;
59+
RCC_ClkInitStruct.APB2CLKDivider = HSE_APB2CLKDIV_HVALUE;
60+
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_HVALUE);
6861
FLASH->ACR |= 0b111 << 8; //enable ART acceleration
6962

7063
#else
@@ -74,21 +67,21 @@ void platform_init(void)
7467
RCC_OscInitStruct.HSIState = RCC_HSI_ON; // HSI is needed for the RNG
7568
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // we need PLL to use RNG
7669
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
77-
RCC_OscInitStruct.PLL.PLLM = 7; // External clock is 7.3728MHz
78-
RCC_OscInitStruct.PLL.PLLN = 319;
79-
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8;
80-
RCC_OscInitStruct.PLL.PLLQ = 7; // divisor for RNG, USB and SDIO
70+
RCC_OscInitStruct.PLL.PLLM = HSE_PLLM_VALUE;
71+
RCC_OscInitStruct.PLL.PLLN = HSE_PLLN_VALUE;
72+
RCC_OscInitStruct.PLL.PLLP = HSE_PLLP_VALUE;
73+
RCC_OscInitStruct.PLL.PLLQ = HSE_PLLQ_VALUE; // divisor for RNG, USB and SDIO
8174
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
8275
for(;;);
8376
}
8477

8578
RCC_ClkInitTypeDef RCC_ClkInitStruct;
8679
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
8780
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
88-
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
89-
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
90-
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
91-
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_ACR_LATENCY_0WS); // wait states not needed for < 30MHz
81+
RCC_ClkInitStruct.AHBCLKDivider = HSE_AHBCLKDIV_HVALUE;
82+
RCC_ClkInitStruct.APB1CLKDivider = HSE_APB1CLKDIV_HVALUE;
83+
RCC_ClkInitStruct.APB2CLKDivider = HSE_APB2CLKDIV_HVALUE;
84+
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_HVALUE);
9285
#endif
9386

9487
// Configure and starts the RNG

stm32f2/stm32f2_hal_lowlevel.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@
4343
#include "stm32f2xx_hal_uart.h"
4444
#include "stm32f2xx_hal_flash.h"
4545

46-
#ifndef F_CPU
47-
#define F_CPU 7372800U
48-
#endif
4946

5047
#define assert_param(expr) ((void)0U)
5148

@@ -58,12 +55,12 @@ uint32_t HAL_GetTick(void)
5855
return tick++;;
5956
}
6057

61-
#define RCC_CFGR_HPRE_BITNUMBER POSITION_VAL(RCC_CFGR_HPRE)
58+
// #define RCC_CFGR_HPRE_BITNUMBER POSITION_VAL(RCC_CFGR_HPRE)
6259

63-
const uint8_t APBAHBPrescTable[16] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
60+
// const uint8_t APBAHBPrescTable[16] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
6461

65-
#define UART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
66-
USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */
62+
/* #define UART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
63+
USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) */ /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */
6764

6865

6966

@@ -552,7 +549,7 @@ uint32_t HAL_RCC_GetPCLK1Freq(void)
552549
{
553550
/* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
554551
//return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1)>> POSITION_VAL(RCC_CFGR_PPRE1)]);
555-
return F_CPU;
552+
return (uint32_t)PCLK1_FREQ;
556553
}
557554

558555
/**
@@ -565,7 +562,7 @@ uint32_t HAL_RCC_GetPCLK2Freq(void)
565562
{
566563
/* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
567564
//return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2)>> POSITION_VAL(RCC_CFGR_PPRE2)]);
568-
return F_CPU;
565+
return (uint32_t)PCLK2_FREQ;
569566
}
570567

571568

stm32f2/stm32f2_hal_lowlevel.h

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,38 @@
5252
#define HSE_STARTUP_TIMEOUT (100U) /*!< Time out for HSE start up, in ms */
5353
#endif /* HSE_STARTUP_TIMEOUT */
5454

55+
#if !defined (HSE_PLLM_VALUE)
56+
#define HSE_PLLM_VALUE (7U)
57+
#endif /* HSE_PLLM_VALUE */
58+
59+
#if !defined (HSE_PLLN_VALUE)
60+
#define HSE_PLLN_VALUE (319U)
61+
#endif /* HSE_PLLN_VALUE */
62+
63+
#if !defined (HSE_PLLP_VALUE)
64+
#define HSE_PLLP_VALUE (8U)
65+
#endif /* HSE_PLLP_VALUE */
66+
67+
#if !defined (HSE_PLLQ_VALUE)
68+
#define HSE_PLLQ_VALUE (7U)
69+
#endif /* HSE_PLLQ_VALUE */
70+
71+
#if !defined (HSE_AHBCLKDIV_VALUE)
72+
#define HSE_AHBCLKDIV_VALUE (1U)
73+
#endif /* HSE_AHBCLKDIV_VALUE */
74+
75+
#if !defined (HSE_APB1CLKDIV_VALUE)
76+
#if defined(USE_PLL)
77+
#define HSE_APB1CLKDIV_VALUE (2U) /* PCLK1 max freq is 30 MHz */
78+
#else
79+
#define HSE_APB1CLKDIV_VALUE (1U)
80+
#endif
81+
#endif /* HSE_APB1CLKDIV_VALUE */
82+
83+
#if !defined (HSE_APB2CLKDIV_VALUE)
84+
#define HSE_APB2CLKDIV_VALUE (1U) /* PCLK2 max freq is 60 MHz */
85+
#endif /* HSE_APB2CLKDIV_VALUE */
86+
5587
/**
5688
* @brief Internal High Speed oscillator (HSI) value.
5789
* This value is used by the RCC HAL module to compute the system frequency
@@ -92,6 +124,18 @@
92124
/* Tip: To avoid modifying this file each time you need to use different HSE,
93125
=== you can define the HSE value in your toolchain compiler preprocessor. */
94126

127+
/* ########################### UART Configuration ######################### */
128+
/**
129+
* @brief UART initial baudrate
130+
*/
131+
#if !defined(UART_INITBAUD)
132+
#if SS_VER==SS_VER_2_1
133+
#define UART_INITBAUD 230400
134+
#else
135+
#define UART_INITBAUD 38400
136+
#endif
137+
#endif
138+
95139
/* ########################### System Configuration ######################### */
96140
/**
97141
* @brief This is the HAL system configuration section
@@ -108,4 +152,105 @@
108152
// #define STM32F215xx
109153
#include "stm32f2xx.h"
110154

155+
/* ########################### Generated Values ######################### */
156+
#if defined(USE_INTERNAL_CLK)
157+
#define SYSCLK_FREQ (HSI_VALUE)
158+
#elif defined(USE_PLL)
159+
#define SYSCLK_FREQ (HSE_VALUE / HSE_PLLM_VALUE * HSE_PLLN_VALUE / HSE_PLLP_VALUE)
160+
#else
161+
#define SYSCLK_FREQ (HSE_VALUE)
162+
#endif
163+
164+
#define HCLK_FREQ (SYSCLK_FREQ / HSE_AHBCLKDIV_VALUE)
165+
#define PCLK1_FREQ (HCLK_FREQ / HSE_APB1CLKDIV_VALUE)
166+
#define PCLK2_FREQ (HCLK_FREQ / HSE_APB2CLKDIV_VALUE)
167+
168+
#if HSE_VALUE > 26000000U
169+
#error "Maximum allowed HSE_VALUE is 26MHz"
170+
#endif
171+
#if HCLK_FREQ > 120000000U
172+
#error "Maximum allowed HCLK_FREQ is 120MHz"
173+
#endif
174+
#if PCLK1_FREQ > 30000000U
175+
#error "Maximum allowed PCLK1_FREQ is 30MHz"
176+
#endif
177+
#if PCLK2_FREQ > 60000000U
178+
#error "Maximum allowed PCLK2_FREQ is 60MHz"
179+
#endif
180+
181+
#if HSE_PLLM_VALUE < 2U || HSE_PLLM_VALUE > 63U
182+
#error "HSE_PLLM_VALUE not supported"
183+
#endif
184+
#if HSE_PLLN_VALUE < 192U || HSE_PLLN_VALUE > 432U
185+
#error "HSE_PLLN_VALUE not supported"
186+
#endif
187+
#if HSE_PLLP_VALUE != 2U && HSE_PLLP_VALUE != 4U && HSE_PLLP_VALUE != 6U && HSE_PLLP_VALUE != 8U
188+
#error "HSE_PLLP_VALUE not supported"
189+
#endif
190+
#if HSE_PLLQ_VALUE < 2U || HSE_PLLQ_VALUE > 15U
191+
#error "HSE_PLLQ_VALUE not supported"
192+
#endif
193+
194+
#if HSE_AHBCLKDIV_VALUE == 1
195+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV1
196+
#elif HSE_AHBCLKDIV_VALUE == 2
197+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV2
198+
#elif HSE_AHBCLKDIV_VALUE == 4
199+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV4
200+
#elif HSE_AHBCLKDIV_VALUE == 8
201+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV8
202+
#elif HSE_AHBCLKDIV_VALUE == 16
203+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV16
204+
#elif HSE_AHBCLKDIV_VALUE == 64
205+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV64
206+
#elif HSE_AHBCLKDIV_VALUE == 128
207+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV128
208+
#elif HSE_AHBCLKDIV_VALUE == 256
209+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV256
210+
#elif HSE_AHBCLKDIV_VALUE == 512
211+
#define HSE_AHBCLKDIV_HVALUE RCC_CFGR_HPRE_DIV512
212+
#else
213+
#error "HSE_AHBCLKDIV_VALUE not supported"
214+
#endif
215+
216+
#if HSE_APB1CLKDIV_VALUE == 1
217+
#define HSE_APB1CLKDIV_HVALUE RCC_CFGR_PPRE1_DIV1
218+
#elif HSE_APB1CLKDIV_VALUE == 2
219+
#define HSE_APB1CLKDIV_HVALUE RCC_CFGR_PPRE1_DIV2
220+
#elif HSE_APB1CLKDIV_VALUE == 4
221+
#define HSE_APB1CLKDIV_HVALUE RCC_CFGR_PPRE1_DIV4
222+
#elif HSE_APB1CLKDIV_VALUE == 8
223+
#define HSE_APB1CLKDIV_HVALUE RCC_CFGR_PPRE1_DIV8
224+
#elif HSE_APB1CLKDIV_VALUE == 16
225+
#define HSE_APB1CLKDIV_HVALUE RCC_CFGR_PPRE1_DIV16
226+
#else
227+
#error "HSE_APB1CLKDIV_VALUE not supported"
228+
#endif
229+
230+
#if HSE_APB2CLKDIV_VALUE == 1
231+
#define HSE_APB2CLKDIV_HVALUE RCC_CFGR_PPRE2_DIV1
232+
#elif HSE_APB2CLKDIV_VALUE == 2
233+
#define HSE_APB2CLKDIV_HVALUE RCC_CFGR_PPRE2_DIV2
234+
#elif HSE_APB2CLKDIV_VALUE == 4
235+
#define HSE_APB2CLKDIV_HVALUE RCC_CFGR_PPRE2_DIV4
236+
#elif HSE_APB2CLKDIV_VALUE == 8
237+
#define HSE_APB2CLKDIV_HVALUE RCC_CFGR_PPRE2_DIV8
238+
#elif HSE_APB2CLKDIV_VALUE == 16
239+
#define HSE_APB2CLKDIV_HVALUE RCC_CFGR_PPRE2_DIV16
240+
#else
241+
#error "HSE_APB2CLKDIV_VALUE not supported"
242+
#endif
243+
244+
#if HCLK_FREQ <= 30000000U
245+
#define FLASH_LATENCY_HVALUE FLASH_ACR_LATENCY_0WS
246+
#elif HCLK_FREQ <= 60000000U
247+
#define FLASH_LATENCY_HVALUE FLASH_ACR_LATENCY_1WS
248+
#elif HCLK_FREQ <= 90000000U
249+
#define FLASH_LATENCY_HVALUE FLASH_ACR_LATENCY_2WS
250+
#elif HCLK_FREQ <= 120000000U
251+
#define FLASH_LATENCY_HVALUE FLASH_ACR_LATENCY_3WS
252+
#else
253+
#error "HCLK_FREQ not supported"
254+
#endif
255+
111256
#endif

stm32f4/Makefile.stm32f4

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@ LDFLAGS += --specs=nosys.specs -T $(HALPATH)/stm32f4/LinkerScript.ld -Wl,--gc-s
4545
ifneq ($(UART_INITBAUD),)
4646
CDEFS += -DUART_INITBAUD=$(UART_INITBAUD)
4747
CPPDEFS += -DUART_INITBAUD=$(UART_INITBAUD)
48-
endif
48+
endif
49+
50+
PLL_SCRIPT := "infreq=($(F_CPU))/1e6; print('{} {} {} {}'.format(int(infreq*1e6), *min(((m, n, q) for m in range(2, 64) if 0.95 <= (f1 := infreq / m) <= 2.10 for n in range(50, 433) if 100 <= (f2 := f1 * n) <= 432 for q in range(2, 16) if 0 <= (f := f2 / q) <= 48), key=lambda x: abs(infreq / x[0] * x[1] / x[2] - 48))))"
51+
PLL_VALUES := $(shell python3 -c $(PLL_SCRIPT))
52+
CDEFS += -DHSE_VALUE=$(word 1, $(PLL_VALUES))U -DHSE_PLLM_VALUE=$(word 2, $(PLL_VALUES))U -DHSE_PLLN_VALUE=$(word 3, $(PLL_VALUES))U -DHSE_PLLQ_VALUE=$(word 4, $(PLL_VALUES))U

0 commit comments

Comments
 (0)