Overclock STM32F4 device up to 250MHz

http://stm32f4-discovery.com/2014/11/overclock-stm32f4-device-up-to-250mhz/

Let’s test what STM32F4xx devices can do.

I have all “4 speed families” at home so why not to try it how fast we can go.

By default, for those who don’t know max frequencies for STM32F4xx devices, they are in list below:

  • 84MHz: STM32F401 MCUs, including Nucleo-F401 board
  • 100MHz: STM32F411 MCUs, including Nucleo F411 board
  • 168MHz: STM32F405/7 and STM32F415/17 MCUs, including STM32F4-Discovery board
  • 180MHz: STM32F427/29 and STM32F437/39 MCUs, including STM32F429-Discovery board

Ok, we have everything provided, let’s test how far we can go with PLL settings.

First we have to go through, how to set PLL parameters to even get any clock.

Step by step on how PLL works.

About PLL settings

  1. You gave him some input frequency, let’s say HSE_VALUE = 8MHz.
    Then, he divide this by PLL_M factor, that we get 1MHz in the first stage output. This means 
  2. Then, PLL multiplies output (1MHz) with a large number, factor is called PLL_N.
    This number depends on STM32F4xx family.
    By default, for normal clocks (specified in datasheet) values are:
    1. 84MHz: PLL_N = 336
    2. 100MHz: PLL_N = 400
    3. 168MHz: PLL_N = 336
    4. 180MHz: PLL_N = 360

    Probably your question is why so strange values.
    Simple answer, STM32F4xx have different peripherals (SDIO, USB, etc)
    and some specific peripherals needs exact clock.
    If you want to have 168MHz core clock and then for USB 48MHz, this is not possible,
    because you cannot set a prescaler of 168/48 = 3.5.
    This is “no go”. For that purpose, least common value for (in this case) 168MHz and 48MHz is used, 336.

    PLL_VCO = PLL_N * (HSE_VALUE / PLL_M)

     

  3. Ok, we have 336MHz somewhere inside PLL now.
    Now become 2 new PLL parameters.

    1. PLL_P: This parameter is used to set system core clock for MCU.
      If you want 168MHz clock, and you have 336MHz on the input of this divider,
      you set parameter PLL_P = 2. Equation is 
      1. 84MHz: PLL_P = 4
      2. 100MHz: PLL_P = 4
      3. 168MHz: PLL_P = 2
      4. 180MHz: PLL_P = 2

    2. PLL_Q: This parameter is used to set clock for special peripheral (SDIO, USB, RNG)
      to be at least about 48MHz. But this is not always possible.
      It divides the input frequency for special peripherals like PLL_P does for system core clock.
      CLOCK_48MHz = PLL_VCO / PLL_Q = 336MHz / 7 = 48MHz

      By default this parameter is set to 7.
      If we take a look at what happens if we have 180MHz clock and PLL_N set to 360,
      the our PLL_VCO is 360MHz and our “48MHz” clock becomes:

      CLOCK_48MHz = 360MHz / 7 = 51.7MHz

       

  4. If we now make a full equatons for system core clock, we will get something like this:
    PLL_VCO = ((HSE_VALUE / PLL_M) * PLL_N) 
    SYSTEM_CORE_CLOCK = PLL_VCO / PLL_P
    CLOCK_48MHZ = PLL_VCO / PLL_Q
  5. All these settings are set in system_stm32f4xx.c file if you use Standard Peripheral Drivers like I do.

Overclocking STM32F4xx device

To test how far I can go, I used my PWM library hich automatically sets timer period and prescaler

according to the timer’s frequency and pwm frequency you choose.

This values are stored in my working struct for PWM library.

I used this PWM output to measure actual frequency with oscilloscope.

First, I tried overclock STM32F429-Discovery board.

For first test, it was just good if I set PLL_N to higher value.

I set it to PLL_N = 400, and if we calculate this, we will get SYSCLK = 200MHz.

This is more than 180MHz so we can expect any problems. I’ve also set variable

SystemCoreClock = 200000000

to be sure my settings are OK in file.

Then I’ve started my program in debug mode and set timer settings and PWM output.

I’ve measured real 10kHz PWM output like I set.

I was still not sure if this is ok. In debug window, you can look at variables.

Like I previously said, my PWM struct stores information about timer prescaler and period.

I read from debug windows values below:

  • Period: 10000
    • Absolute value how much ticks timer has to make. Value stored in TIM’s register is Period – 1
  • Prescaler: 1
    • Absolute value to use with calculations. Value stored in TIM’s register is Prescaler – 1

It was strange for me first time, because this was not so nice result.

Then I realized, that TIM2 for PWM is connected to APB1 bus,

which clock frequency is on F429 APB1 = SYSCLK / 4

but TIM has internal PLL which increases frequency by 2,

so you get TIM2_TICK_DEFAULT = SYSCLK / 4 * 2 = SYSCLK / 2 = 100MHz.

This result is better now. because you get: 

So I was doing this a lot of times, trying different frequencies.

To 250MHz on STM32F429-Discovery I got frequency on my oscilloscope 10kHz and parameters for timer were valid.

So clock was really 250MHz.

For other boards, I got maximum clocks of:

  • STM32F429-Discovery; 250MHz
    • APB1 = SYSCLK / 4; TIM2 default frequency = SYSCLK / 4 * 2 = 125MHz
  • STM32F4-Discovery: 250MHz
    • APB1 = SYSCLK / 4; TIM2 default frequency = SYSCLK / 4 * 2 = 125MHz
  • Nucleo F401: 125MHz
    • APB1 = SYSCLK / 2; TIM2 default frequency = SYSCLK / 2 * 2 = 125MHz
  • Nucleo F411: 125MHz
    • APB1 = SYSCLK / 2; TIM2 default frequency = SYSCLK / 2 * 2 = 125MHz

Important notes:

  • There is no guarantee that every MCU in the series will go to the value like my did, because they are not designed for so high speed,
    • I do not suggest you that you use this in production
  • When frequency is higher than expected, MCU can become unstable and can crash or some hardfault error can happen,
    • Also, temperature rises with frequency.
  • You can blow your MCU
    • I’m not responsible for that. You are doing this on your own risk.

PLL Settings

These settings are set in system_stm32f4xx.c file

/************************* PLL Parameters *************************************/
#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      8
#else /* STM32F411xE */ #if defined (USE_HSE_BYPASS) #define PLL_M 8 #else /* STM32F411xE */
#define PLL_M 16 #endif /* USE_HSE_BYPASS */
#endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */ /* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ #define PLL_Q 7 #if defined (STM32F40_41xxx) #define PLL_N 500 /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 2 #endif /* STM32F40_41xxx */ #if defined (STM32F427_437xx) || defined (STM32F429_439xx) #define PLL_N 500 /* 250MHz clock for STM32F429-Discovery board */ /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 2 #endif /* STM32F427_437x || STM32F429_439xx */ #if defined (STM32F401xx) #define PLL_N 500 /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 4 #endif /* STM32F401xx */ #if defined (STM32F411xE) #define PLL_N 500 /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 4 #endif /* STM32F411xx */ /******************************************************************************/ /** * @} */ /** @addtogroup STM32F4xx_System_Private_Macros * @{ */ /** * @} */ /** @addtogroup STM32F4xx_System_Private_Variables * @{ */ #if defined (STM32F40_41xxx) uint32_t SystemCoreClock = 250000000; #endif /* STM32F40_41xxx */ #if defined (STM32F427_437xx) || defined (STM32F429_439xx) uint32_t SystemCoreClock = 250000000; /* 250MHz clock */ #endif /* STM32F427_437x || STM32F429_439xx */ #if defined (STM32F401xx) uint32_t SystemCoreClock = 125000000; #endif /* STM32F401xx */ #if defined (STM32F411xE) uint32_t SystemCoreClock = 125000000; #endif /* STM32F401xx */

Main

Main program

/**
 *    Keil project for overclocking STM32F4xx devices
 *
 *    Before you start, select your target, on the right of the "Load" button
 *
 *    @author        Tilen Majerle
 *    @email        tilen@majerle.eu
 *    @website    http://stm32f4-discovery.com
 *    @ide        Keil uVision 5
 *    @packs        STM32F4xx Keil packs version 2.2.0 or greater required
 *    @stdperiph    STM32F4xx Standard peripheral drivers version 1.4.0 or greater required
 *
 *    When you use debug, you need to print "PWM_Data" variable to see results
 */
/* Include core modules */
#include "stm32f4xx.h"
/* Include my libraries here */
#include "defines.h"
#include "tm_stm32f4_delay.h"
#include "tm_stm32f4_disco.h"
#include "tm_stm32f4_pwm.h"

int main(void) {
    /* Timer settings struct */
    TM_PWM_TIM_t PWM_Data;
    
    /* Initialize system */
    SystemInit();
    
    /* Initialize delay */
    TM_DELAY_Init();
    
    /* Initialize leds on board */
    TM_DISCO_LedInit();
    
    /* Turn on all leds */
    TM_DISCO_LedOn(LED_GREEN);
    
    /* Init Timer for PWM, TIM frequency 10kHz */
    TM_PWM_InitTimer(TIM2, &PWM_Data, 10000);
    
    /* Initialize PWM Channel 1 on TIM2, PinsPack 2 = PA5 */
    TM_PWM_InitChannel(TIM2, TM_PWM_Channel_1, TM_PWM_PinsPack_2);
    
    /* Set 70% duty cycle */
    TM_PWM_SetChannelPercent(TIM2, &PWM_Data, TM_PWM_Channel_1, 70);
    
    while (1) {
        
    }
}

Project below has settings in system_stm32f4xx.c

set to maximum frequency like I said above, so 250 and 125MHz.

Before you debug in Keil uVision, you have to rebuild. All libs are included in project. 

posted @ 2015-07-29 16:43  IAmAProgrammer  阅读(663)  评论(0编辑  收藏  举报