Clock Configuration for STM32F407

The selection of clock that I used for STM32F407 can be explained by below diagram and steps: -


Steps for clock setting: -

  1. Decide if frequency source, HSE (high speed external = crystal of 8MHz) or HSI (high speed internal = 16MHz) to be used. Crystal have high frequency stability and their variations can be measured in ppm (about 20 ppm) (if measured in %, it will be 0.002%), but internal frequency source vary quite a bit, when temperature changes. They are OK for UART, SPI, I2C, PWM and ADC. But the frequency variation is not good for CAN, UAB, ETHERNET etc.
  2. Select "M" (divisor) as 8 for HSE and 16 for HSI. So output is 1MHz. This 1MHz is input to PLL.
  3. The 1MHz is not multiplied by "N". "N" is selected as 336.
  4. There are 2 divisors = P and Q. "P" is selected as 2 and "Q" is selected as 7 to get output of 168MHz and 48MHz respectively.
  5. The 168MHz then goes to AHB divisor, which is selected as 1. Hence AHB frequency is 168MHz.
  6. There are 2 more divisors for peripheral clock = APB1 and APB2. APB1 divisor is selected as 4 and APB2 is selected as 2 to get output of 42MHz and 84MHz respectively.
  7. Once all selections are done, the PLL is enabled. Once enabled, we should check if the PLL is locked or not.
  8. Check working of controller by LED blink!!


clockConfig.h
#ifndef _CLOCK_CONFIG_HEADER
#define _CLOCK_CONFIG_HEADER

#include "stm32f4xx.h"
/**************************************************************************/
#define USE_HSE
//#define USE_HSI
/**************************************************************************/
/*
 * HSI = 16MHz, HSE = 8MHz
 * PLL_Input = HSI/16 or HSE/8 = 1MHz
 * Multiplier = N = 336
 * PLL_Output = (PLL_Input * 336) = 336MHz
 * PLLCLK = PLL_Output/P = 336/2 = 168MHz
 * PLL48CK = PLL_Output/Q = 336/7 = 48MHz
 *
 * In the code, PLLCLK is set as SYSCLK
 *
 * AHB = SYSCLK/1 = 168MHz
 * APB1 = SYSCLK/4 = 42MHz
 * APB2 = SYSCLK/2 = 84MHz
 *
 */
/**************************************************************************/
#ifdef USE_HSI
 #define PLL_M   16
#endif
/**************************************************************************/
#ifdef USE_HSE
 #define PLL_M   8
#endif
/**************************************************************************/
#define PLL_N    336  // Multiplier, directly is the number
#define PLL_P    0  // 0 means P = 2, 1 means P = 4....
#define PLL_Q    7  // Q, directly is the number
/**************************************************************************/
#define AHB_PRESCALAR  0  // 0 means, AHB = SYSCLK/1 (168MHz)
#define APB1_PRESCALAR  5  // 5 means, APB1 = SYSCLK/4 (42MHz), 6 means, APB1 = AHB/8...
#define APB2_PRESCALAR  4  // 4 means, APB2 = SYSCLK/2 (84MHz), 5 means, APB2 = AHB/4...
/**************************************************************************/
void SystemClock_Config(void);
/**************************************************************************/

#define APB2_FREQ   (uint32_t)84000000
#define APB1_FREQ   (uint32_t)42000000

#endif




clockConfig.c

#include "clockConfig.h"
/**************************************************************************/
void SystemClock_Config(void)
{
  uint32_t temp;
  /***************************************************************************/
  /* Enable Power Control clock */
  RCC->APB1ENR |= 0x10000000;   // Enable PWREN bit (page - 183 of RM)
  /**************************************************************************/
  
  /* The voltage scaling allows optimizing the power consumption when the device is 
     clocked below the maximum system frequency, to update the voltage scaling value 
     regarding system frequency refer to product datasheet.  */
  PWR->CR |= 0x00004000; //VOS bit = 01 (page - 145 or RM)
  /**************************************************************************/
#ifdef USE_HSE
  //RCC->CR &= ~0x00000001; // HSI OFF, not guranteed, but does not matter, may be slight increase in current
  RCC->CR |= 0x00010000; // HSE ON
  while((RCC->CR & 0x00020000) == 0); // Wait till HSE is ready

  // Set PLL
  temp = 0x00400000; // PLL source is HSE (PLLSRC bit is set to one)
#endif
  /**************************************************************************/
#ifdef USE_HSI
  RCC->CR |= 0x00000001; // HSI ON
  //RCC->CR &= ~0x00010000; // HSE OFF, not guranted, but does not matter, may be slight increase in current
  while((RCC->CR & 0x00000002) == 0); // Wait till HSI is ready

  // Set PLL
  temp = 0x00000000; // PLL source is HSI (PLLSRC bit is cleared to zero)
#endif
  /**************************************************************************/
  temp |= (uint32_t)PLL_M;
  temp |= ((uint32_t)PLL_N << 6);
  temp |= ((uint32_t)PLL_P << 16);
  temp |= ((uint32_t)PLL_Q << 24);
  RCC->PLLCFGR = temp;
  /**************************************************************************/
  // Select PLLCLK as SYSCLK, APB2, APB1 and AHB
  temp = RCC->CFGR;
  temp |= ((uint32_t)AHB_PRESCALAR << 4);
  temp |= ((uint32_t)APB1_PRESCALAR << 10);
  temp |= ((uint32_t)APB2_PRESCALAR << 13);
  temp |= 0x00000002;   // Select PLL as SYSCLK
  RCC->CFGR = temp;
  /**************************************************************************/
  FLASH->ACR |= 0x00000005; // FLASH_LATENCY_5
  /**************************************************************************/
  // Now, switch ON the PLL
  RCC->CR |= 0x01000000; // PLL ON
  while((RCC->CR & 0x02000000) == 0); // Wait till PLL is ready
  /**************************************************************************/
  // wait till PLL is really used as SYSCLK
  while((RCC->CFGR & 0x00000008) == 0); // Make sure SWS = 0b10 = PLL is really selected
  /**************************************************************************/
   /* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported  */
  volatile uint32_t idNumber = DBGMCU->IDCODE;
  idNumber = idNumber >> 16;
  /**************************************************************************/
  /* Enable the Flash prefetch */
  if(idNumber == 0x1001)
  {
   FLASH->ACR |= 0x00000100;
  }
}
/**************************************************************************/





Comments

Popular Posts