STM32F429 Getting Started: RCC Clock Tree

RCC:reset clock control reset and clock controller. We use clock controller more often.

I. The main function of RCC is the clock part.

Set the system clock SYSCLK, set the AHB frequency dividing factor (determine how much HCLK equals), set the APB2 frequency dividing factor (determine how much PCLK2 equals), set the APB1 frequency dividing factor (determine how much PCLK1 equals), set the frequency dividing factor for each peripheral, control the opening of three bus clocks: AHB, APB2 and AB1, and control the opening of the clock for each peripheral.

Open the assembly file and find this statement=SystemInit->void SystemInit(void)->SetSysClock();This function is where you configure various crossover factors. The function of this function is to use HSE to set the clock to HCLK = SYSCLK=PLLCLK = 180M, PCLK1=HCLK/2 = 90M, PCLK1=HCLK/4 = 45M. We open STM32F4XX Chinese Reference Manual to find the clock tree.

We can divide the clock into: system clock, other clocks.

2. HSE High Speed External Clock Signal

 

 

  • HSE: High Speed External Clock signal, a high-speed external clock.

  • Source: Active crystal oscillation (1-50M): When active crystal oscillation is used, the clock enters from the OSC_IN pin and the OSC_OUT pin hangs empty. Passive crystal oscillation (4-26M): When passive crystal oscillation is selected, the clock enters from OSC_IN and OSC_OUT with a resonant capacitance. HSE uses 25M passive crystal oscillation.

  • Control: RCC_CR clock control register bit 16:HSEON control.

When the HSE fails, we turn off the HSE, and the high-speed internal clock signal HSI will be used as the standby system clock until the HSE returns to normal, HSI = 16M.

 

 

  • HSI:High Speed Internal Clock signal, which is a high-speed internal clock.

  • Source: Inside the chip, the size is 16M. When the HSE fails, the system clock will switch to the HSI automatically until the HSE starts successfully.

  • Control: RCC_CR clock control register bit 0:HSION control.

3. Phase-Locked Loop Clock PLL

The main function of PLL is to multiply the frequency of the clock, and then output the clock to each function unit. There are two PLLs, one is the main PLL and the other is the dedicated PLLI2S, which provide clock input signal by HSE or HSI.

 

  • Phase-locked loop clocks - PLLCLK

  • Source: HSI, HSE. Configured by PLLSRC bit.

  • HSE or HSI passes through a frequency dividing factor M first, then a frequency doubling factor N, then a frequency dividing factor P, and finally becomes a phase-locked loop clock: PLLCLK = (HSE/M)*N/P=25/25 / *360/2 = 180M.

    HSE or HSI passes through PLL clock input frequency dividing factor M (2~63)After frequency division, the VCO clock must be between 1 and 2M. We select HSE=25M as the clock input of PLL, and M is set to 25, then the VCO input clock is equal to 1M. After the VCO input clock passes through the N-fold frequency factor of VCO, it becomes the VCO clock output, and the VCO clock must be between 192 and 432M. When we configure N to 360, the VCO input clock must be between 192 and 432M.The output clock of the VCO is equal to 360M. If you want the system clock to overrun, you have to do something here at the VCO doubling factor N.

    LLCLK_OUTMAX = VCOCLK_OUTMAX/P_MIN = 432/2=216M,

    That is, F429 can exceed the maximum frequency to 216M. The parameter limits of VCO can be found in the manual:

 

  • Control: RCC_PLLCFGR:RCC PLL Configuration Register

  • The crossover factor Q:PLL48CK:USB_FS, RANG, SDIO provides the clock. The value can be 4-15, but USB OTG FS must use 48M, Q=VCO output clock 360/48=7.5, which is obviously a decimal error. The trade-off is to reconfigure the multiplier N=336, VCOCLK=1M*336=336M, PLLCLK=VCOCLK/2=168M, USBCLK=336/7=48M. When using USB, PLLK=336/7=48M.Reduced to 168M, 180M is not available.

  • The crossover factor R:F429 does not exist.

  • The clock configuration of PLL can be expressed by the following formula:

VCOCLK_IN = PLLCLK_IN / M = HSE / 25 = 1M 
VCOCLK_OUT = VCOCLK_IN * N = 1M * 360 = 360M PLLCLK_OUT=VCOCLK_OUT/P=360/2=180M
USBCLK = VCOCLK_OUT/Q=360/7=51.7  //Reconfiguration when actually using usb

4. System Clock SYSCLK

  • The maximum is 180M.

  • Source: HSI, HSE, PLLCLK

  • Control: The RCC_CFGR clock configures the SW bit of the register, commonly using a phase-locked loop as the system clock. If the system clock is obtained by the PLLCLK after the HSE passes through the PLL frequency doubling, the system clock will switch to HSI=16M when the HSE fails until the HSE returns to normal.

 

 

V. HCLK Clock

  • HCLK:AHB High Speed Bus Clock, up to 180M. Provides a clock for the peripherals of the AHB bus, a clock for the Cortex system timer (SysTick), and a clock for the kernel (FCLK) =180M, which is the CPU clock.

  • AHB is advanced high-performance bus.

  • Source: System clock crossover is obtained.

  • Control: RCC_CFGR clock configuration register HPRE bit.

 

 

6. PCLK1 Clock

  • PCLK1:APB low speed bus clock, up to 45M. Clock is provided for APB1 bus peripherals. Clock is provided for APB1 bus timers after 2x, up to 90M.

  • Source: HCLK frequency division obtained

  • Control: PPRE1 bit of RCC_CFGR clock configuration register.

7. PCLK2 Clock

  • PCLK2: APB High Speed Bus Clock, up to 90M. Clock for APB2 bus peripherals. Clock for APB2 bus timer after 2x, up to 180M.

  • Source: HCLK frequency division obtained.

  • Control: PPRE2-bit RCC_CFGR clock configuration register.

8. Other Clocks

(1) RTC clock

 

 

  • RTC: Provides the clock for RTC inside the chip.

  • Sources: HSE_RTC (obtained by HSE crossover), LSE (provided by external 32.768 kHz crystals), LSI (32 khz).

  • Control: RCC backup domain control register RCC_BDCR:RTCSEL bit control.

  • Independent Watchdog Clock: IWDGCLK, provided by LSI.

  • LSE is produced by an external crystal resonator. The precision of the resonant capacitance required is high, otherwise it is easy to avoid vibration.

(2) I2S clock

 

The I2S clock can be either input by the external clock pin I2S_CKIN or provided by the dedicated PLLI2SCLK, specifically configured by the I2SSCR bit of the RCC clock configuration register (RCC_CFGR). When we use the I2S peripheral to drive W8978, the clock used is PLLI2SCLK, which eliminates an active crystal oscillation.

(3) PHY Ethernet clock

 

 

429 has no integrated PHY, only PHY chips, such as LAN8720, can be attached. The PHY clock is provided by the external PHY chips with a size of 50M. The advantage of using RMII interface is that the IO used is reduced by half, and the speed is the same as MII interface. When using RMII interface, PHY chips only need to output one clock to MCU. If using MII interface, PHY coreThe chip needs to provide two clocks to the MCU.

(4) USB PHY clock

 

429 USB does not have PHY integrated. For high-speed USB transmission, only PHY chips, such as USB33000, can be external. The USB PHY clock is provided by the external PHY chips.

(5) MCO clock output

MCO is the abbreviation of the microcontroller clock output, which is the pin of the microcontroller clock output. Its main function is to provide the clock to the outside world, which is equivalent to an active crystal oscillation. There are two MCOs in F429, which are multiplexed by PA8/PC9. The clock source required by MCO1 is MCO1PRE[2:0] and MCO1[1:0] in the RCC clock configuration register (RCC_CFGR).Bit selection. The clock source required for MCO2 is selected by MCO2PRE[2:0] and MCO2 bits in the RCC clock configuration register (RCC_CFGR).

 

 

Now that you know the clock tree above, let's use HSE to configure the system clock.

We'll set the function SetSysClock();Copy to our new file. Then delete the unnecessary things. Our chip uses passive crystal oscillation, so we remove the active crystal oscillation part.

That is the code below #if defined(USE_HSE_BYPASS).

Then delete the other chips'configurations, leaving behind F429-related ones. Finally, delete the corresponding macros, which will reduce the amount of code.

The final code parses as follows:

 

void SetSysClock(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
/*-------------------------1-Enable HSE and wait for HSE to stabilize -----------------------------------------*/
  /* Enabling HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait for the HSE to initialize successfully, when it initializes successfully, the pin will turn to 1 and jump out if it times out*/
  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;  //Start Successful
  }
  else
  {
    HSEStatus = (uint32_t)0x00;	//Start unsuccessful
  }

	//Start Successful
  if (HSEStatus == (uint32_t)0x01)
  {
/*---------------------------------------------------------------------*/
    /* Select voltage regulator, select output mode 1  */
		/* Enable power interface clock*/
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
		/*Controls the output voltage of the internal main voltage regulator to balance energy with power consumption when the device operates at the end of the maximum frequency*/
		/*Mode 1*/
    PWR->CR |= PWR_CR_VOS;
		
/*-----------------2-Configuring Pre-dividing Frequency Factor for AHB APB2 APB1 Bus-------------------------------*/

    /* HCLK = SYSCLK / 1*/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

    /* PCLK2 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    
    /* PCLK1 = HCLK / 4*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
		
/*-----------------3-Configure various pre-dividing factors of PLL and enable PLL-------------------*/

    /* Configure Master PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
    
    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Waiting for PLL to start stable */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
			
    }
		
/*---------------------------------------------------------------------*/
   
    /* Turn on OVER-Drive mode to achieve higher frequency, hardware set one*/
    PWR->CR |= PWR_CR_ODEN;
    while((PWR->CSR & PWR_CSR_ODRDY) == 0)
    {
    }
    PWR->CR |= PWR_CR_ODSWEN;
    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
    {
    }      
    /* Configure Flash prefetch finger, instruction cache, data cache, and wait cycles */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

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

    /* Waiting for PLLCLK to switch to system clock */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    {
    }
	}
  else
  {  
			//Users can add code they need if the HSE fails to start
  }

}

To understand the library function, we need to configure a system clock by using the firmware library, and try the overfrequency by the way, so we can freely achieve the size of the frequency. Then we can use the flashing light to see how the frequency affects the response.

//m: Frequency division factor PLLM 2<=PLLM<=63 for master PLL and audio PLL input clocks
//n: Primary PLL multiplier 192<=PLLN<=432 for VCO
//p: Main PLL frequency dividing factor PLLP for master system clock = 2\4\6\8
//q: Main PLL frequency dividing factor, suitable for USB OTG, SDIO and random number generator clock 2<=PLLQ<=15
//SYSCLK = (HSE/m)*n/p = 25/25*432/2=261M    MaxHSE_SetSysClk(25,432,2,7)
void HSE_SetSysClk(uint32_t m,uint32_t n,uint32_t p,uint32_t q)
{
		__IO uint32_t HSEStartUpStatus = 0;
	
		//Enable HSE and wait for startup to complete
		RCC_HSEConfig(RCC_HSE_ON);
	
		HSEStartUpStatus = RCC_WaitForHSEStartUp();
	
		if(HSEStartUpStatus==SUCCESS)
		{
		    /* Select voltage regulator, select output mode 1  */
				/* Enable power interface clock*/
				RCC->APB1ENR |= RCC_APB1ENR_PWREN;
				/*Controls the output voltage of the internal main voltage regulator to balance energy with power consumption when the device operates at the end of the maximum frequency*/
				/*Mode 1*/
				PWR->CR |= PWR_CR_VOS;
			
				RCC_HCLKConfig(RCC_SYSCLK_Div1);
				RCC_PCLK2Config(RCC_HCLK_Div2);
				RCC_PCLK1Config(RCC_HCLK_Div4);
			
				RCC_PLLConfig(RCC_PLLSource_HSE,m, n, p, q);
			
				//Open main phase-locked loop
				RCC_PLLCmd(ENABLE);
				
				//Waiting to open
				while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
				{
				}
				
				/* Configure Flash prefetch finger, instruction cache, data cache, and wait cycles */
				FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
				//Configure System Clock
				RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
				while((RCC_GetSYSCLKSource())!=0X08)
				{
				}
				
		}
		else
		{
				//HSE failed to start. User adds error correction code here
		}
		
}

We can also call the MCO to monitor our frequencies, using an oscilloscope connected to the DuPont line outside:

// MCO1 PA8 GPIO Initialization
void MCO1_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
  // MCO1 GPIO Configuration
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
  GPIO_Init(GPIOA, &GPIO_InitStructure); 
}

// MCO2 PC9 GPIO Initialization
void MCO2_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  
  // MCO2 GPIO Configuration
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

The last observed function is as follows, and we can see that the flashing frequency of the lamp is faster than that of 180M:

void LED_GPIO_Config(void);

int main(void)
{
		HSE_SetSysClk(25,432,2,7);
	
		LED_GPIO_Config();
	  
    	MCO1_GPIO_Config(void);
	
    while(1)
		{
			LED1(ON);
			Delay(0x0FFFFF);
			LED1(OFF);
			Delay(0x0FFFFF);
		}
}

After learning HSE, we learn how to use it. HSI is very similar to HSE, and we can modify it based on the code of HSE.

The HSI is 16M, and the parameter m is also generally set to 16, so when we need to modify the system clock, we only need to modify the parameters N and p, SYSCLK=PLLCLK=HSI/m*n/p.

Function call example, setting clock using HSI:

SYSCLK=HCLK=180M,PCLK2=HCLK/2=90M,PCLK1=HCLK/4=45M

HSI_SetSysClock**(16, 360, 2, 7)**;

It is common practice for HSE to be the clock source and PLL to be the system clock.

System clock overfrequency to 216M HSI_SetSysClock(16, 432, 2, 9);

The specific implementation functions are as follows:

void HSI_SetSysClk(uint32_t m,uint32_t n,uint32_t p,uint32_t q)
{
		__IO uint32_t HSItartUpStatus = 0;
	
		//Initialize RCC peripheral to reset state
		RCC_DeInit();
	
		//Enable HSI and wait for stability
		RCC_HSICmd(ENABLE);
	
		HSItartUpStatus = RCC->CR & RCC_CR_HSIRDY;
	
		if(HSItartUpStatus==RCC_CR_HSIRDY)
		{
		    /* Select voltage regulator, select output mode 1  */
				/* Enable power interface clock*/
				RCC->APB1ENR |= RCC_APB1ENR_PWREN;
				/*Controls the output voltage of the internal main voltage regulator to balance energy with power consumption when the device operates at the end of the maximum frequency*/
				/*Mode 1*/
				PWR->CR |= PWR_CR_VOS;
			
				RCC_HCLKConfig(RCC_SYSCLK_Div1);
				RCC_PCLK2Config(RCC_HCLK_Div2);
				RCC_PCLK1Config(RCC_HCLK_Div4);
			
				RCC_PLLConfig(RCC_PLLSource_HSI,m, n, p, q);
			
				//Open main phase-locked loop
				RCC_PLLCmd(ENABLE);
				
				//Waiting to open
				while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
				{
				}
				
				/* Configure Flash prefetch finger, instruction cache, data cache, and wait cycles */
				FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
				//Configure System Clock
				RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
				while((RCC_GetSYSCLKSource())!=0X08)
				{
				}
				
		}
		else
		{
				//HSE failed to start. User adds error correction code here
		}
		
}

So RCC will learn here! Start learning something new tomorrow!

Tags: Embedded system stm32

Posted on Wed, 15 Sep 2021 13:29:30 -0400 by vb_123