2021-01-12 10:06 AM
Hey guys and gals! I am facing a persistent problems when configuring system clock on the STM32L152 to 32MHz using SPL. It smoothly runs at 24MHz but always freezes when making it to run at its maximum freq.
The MCU's max clock frequnecy is 32MHz and it runs just fine when configuring the clock using STM32CUBE IDE and HAL. The intention is to run it from HSI (16MHz) via the PLL in this way:
It refuses to work in my SPL-based code, although the procedure seems to be the exact analogy to the HAL code:
void init32MHzClock() {
RCC_DeInit();
FLASH_SetLatency(FLASH_Latency_1);
PWR_VoltageScalingConfig(PWR_VoltageScaling_Range1);
RCC_HCLKConfig(RCC_SYSCLK_Div1); // HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div1); // PCLK1 = HCLK
RCC_AdjustHSICalibrationValue(0x10U); // default HSI calibration trimming value
RCC_HSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) != SET);
// PLL clock from 16 MHz HSI:
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_4, RCC_PLLDiv_2); // 16*4/2 = 32MHz
// RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_6, RCC_PLLDiv_4); // 16*6/4 = 24MHz
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // select the PLL as clock source.
while(RCC_GetSYSCLKSource() != 0x0C); // wait till PLL is used as system clock
SystemCoreClock = 32000000;
}
It never goes beyond the last while on line 23. All the code I had googled is mostly related to other MCUs (mostly F103), and there seems not to be anything that different in the architecture. Could any of you, please spot a difference or a missing piece and advise? Cheers!
Solved! Go to Solution.
2021-01-12 10:20 AM
Pretty sure you have to enable the 64-bit fetch
Here for HSE/PLL in SPL examples
/**
* @brief Sets System clock frequency to 32MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo32(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable 64-bit access */
FLASH->ACR |= FLASH_ACR_ACC64;
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTEN;
/* Flash 1 wait state */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* Enable the PWR APB1 Clock */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Select the Voltage Range 1 (1.8V) */
PWR->CR = PWR_CR_VOS_0;
/* Wait Until the Voltage Regulator is ready */
while((PWR->CSR & PWR_CSR_VOSF) != RESET)
{
}
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
/* PLL configuration: PLLCLK = (HSE * 12) / 3 = 32MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |
RCC_CFGR_PLLDIV));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL12 | RCC_CFGR_PLLDIV3);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x0C)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
I'd try
...
FLASH_PrefetchBufferCmd(ENABLE);
FLASH_ReadAccess64Cmd(ENABLE);
FLASH_SetLatency(FLASH_Latency_1);
PWR_VoltageScalingConfig(PWR_VoltageScaling_Range1);
...
2021-01-12 10:20 AM
Pretty sure you have to enable the 64-bit fetch
Here for HSE/PLL in SPL examples
/**
* @brief Sets System clock frequency to 32MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo32(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable 64-bit access */
FLASH->ACR |= FLASH_ACR_ACC64;
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTEN;
/* Flash 1 wait state */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* Enable the PWR APB1 Clock */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Select the Voltage Range 1 (1.8V) */
PWR->CR = PWR_CR_VOS_0;
/* Wait Until the Voltage Regulator is ready */
while((PWR->CSR & PWR_CSR_VOSF) != RESET)
{
}
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
/* PLL configuration: PLLCLK = (HSE * 12) / 3 = 32MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |
RCC_CFGR_PLLDIV));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL12 | RCC_CFGR_PLLDIV3);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x0C)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
I'd try
...
FLASH_PrefetchBufferCmd(ENABLE);
FLASH_ReadAccess64Cmd(ENABLE);
FLASH_SetLatency(FLASH_Latency_1);
PWR_VoltageScalingConfig(PWR_VoltageScaling_Range1);
...
2021-01-13 12:29 AM
Yes! That worked! The missing parts were the prefetchBuffer + readAccess64. Thank you so much! :)
For future reference the complete working code is right here:
void init32MHzClock() {
FLASH_PrefetchBufferCmd(ENABLE);
FLASH_ReadAccess64Cmd(ENABLE);
FLASH_SetLatency(FLASH_Latency_1);
PWR_VoltageScalingConfig(PWR_VoltageScaling_Range1);
RCC_HCLKConfig(RCC_SYSCLK_Div1); // HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div1); // PCLK1 = HCLK
RCC_AdjustHSICalibrationValue(0x10U); // default HSI calibration trimming value
RCC_HSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) != SET);
// PLL clock from 16 MHz HSI:
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_4, RCC_PLLDiv_2); // 16*4/2 = 32MHz
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // select the PLL as clock source.
while(RCC_GetSYSCLKSource() != 0x0C); // wait till PLL is used as system clock
SystemCoreClock = 32000000;
}
2021-01-13 12:31 AM
Yes! That worked! The missing parts were the prefetchBuffer + readAccess64. Thank you so much! =)
For future reference the complete working code is right here:
void init32MHzClock() {
FLASH_PrefetchBufferCmd(ENABLE);
FLASH_ReadAccess64Cmd(ENABLE);
FLASH_SetLatency(FLASH_Latency_1);
PWR_VoltageScalingConfig(PWR_VoltageScaling_Range1);
RCC_HCLKConfig(RCC_SYSCLK_Div1); // HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div1); // PCLK1 = HCLK
RCC_AdjustHSICalibrationValue(0x10U); // default HSI calibration trimming value
RCC_HSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) != SET);
// PLL clock from 16 MHz HSI:
RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_4, RCC_PLLDiv_2); // 16*4/2 = 32MHz
// RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_6, RCC_PLLDiv_4); // 16*6/4 = 24MHz
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // select the PLL as clock source.
while(RCC_GetSYSCLKSource() != 0x0C); // wait till PLL is used as system clock
SystemCoreClock = 32000000;
}