Changing core frequency of STM32F411 using registers only

In this guide, we shall use registers to change the core frequency from default 16MHz to 100MHz (maximum for F411RE).

We shall use both keil uVision and STM32CubeIDE to change the core frequency to 100MHz.

1. Open CubMX

After you select your MCU, head to RCC and select external oscillator

Then open clock configuration and set the external oscillator to one on your board (in my case is 8MHz).

Note the following Values:

  • PLL_M
  • PLL_N
  • PLL_P
  • Also, APB1 and APB2 prescalers

In my case they are the following:

#define PLL_M      4
#define PLL_N      200
#define PLL_P      4

2. Start new project

Open either CubeIDE or Keil uVision and start new project

3. Open system_stm32f4xx.c

Open system_stm32f4xx.c file and change the external frequency from 25MHz to one on your board (8MHz in my case).

4. Start the configuration

We start of by enabling external clock and waiting for the external clock to be ready

__IO uint32_t StartUpCounter = 0, HSEStatus = 0;


  RCC->CR |= ((uint32_t)RCC_CR_HSEON);


  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;
  } while((HSEStatus == 0) && (StartUpCounter != 3000));

then if the external clock is enable, proceed to change the core frequency as following

if ((RCC->CR & RCC_CR_HSERDY) != RESET) //HSE enabled
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }

  if (HSEStatus == (uint32_t)0x01)
  {

    RCC->APB1ENR |= RCC_APB1ENR_PWREN; //enable opwer regultor
    PWR->CR &= (uint32_t)~(PWR_CR_VOS); //reset VOS (mode 3 selected)


    RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //configure AHB1 bus prescaler to 1


    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; //APB2 prescaler to 1


    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; //APB2 prescaler to 2


    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | //set PLL_M,PLL_N,PLL_P 
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);


    RCC->CR |= RCC_CR_PLLON; //turn on the PLL


    while((RCC->CR & RCC_CR_PLLRDY) == 0) //wait untill PLL is active
    {
    }

    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS;

    /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;

    /* Wait till the main PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL)
    {;}
  }
  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 */
  }

5. Testing using SysTick delay

We can test the core frequency using SysTick to generate delay as following

void delay(int ms)
{
	SysTick->LOAD=100000-1;
	SysTick->VAL=0;
	SysTick->CTRL=0x5;
		for (int i=0;i<ms;i++)
		{
			while(!(SysTick->CTRL &0x10000)){}
		}
	SysTick->CTRL=0;
}

6. Download source Code

You may download the entire project from here

Keil uVison version

STM32CubeIDE version

7. Demo

Add Comment

Your email address will not be published. Required fields are marked *