cancel
Showing results for 
Search instead for 
Did you mean: 

Configuring SysClk on STM32L152 to 32MHz using SPL

MCerv.1
Associate II

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:

0693W000007Azu3QAC.png 

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!

1 ACCEPTED SOLUTION

Accepted Solutions

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);

...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

3 REPLIES 3

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);

...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MCerv.1
Associate II

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;
}

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;
}