cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 Hard Fault when RCC at 165 MHz

FSkro.1
Associate II

I have the STM32H7B3I-DK (MCU: STM32H7B3LIH6Q), and I am trying to get the sys_ck close to its maximum frequency of 280 MHz, by running HSI or HSE through PLL. The trouble is that I can only get up to 164 MHz. Any higher and I get a hard fault. Is there something I am forgetting or messing up? Code:

File    : main.c
Purpose : Generic application start
 
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <stm32h7xx.h>
 
void setup_user_leds(void);
void user_led_red_high(void);
void user_led_red_low(void);
void user_led_blue_low(void);
void user_led_blue_high(void);
 
 
//User LEDs are on PG2 and PG11
void setup_user_leds(void)
{
  uint32_t reg_copy;
 
  //enable the clock to GPIOG peripheral
  RCC->AHB4ENR |=  RCC_AHB4ENR_GPIOGEN;
 
  //(MODER states are 2 bits, hence Read/Modify/Write)
  //make a copy of the current state of the register
  reg_copy = GPIOG->MODER;
  //use the masks to clear the bits  
  reg_copy &= ~(GPIO_MODER_MODE2_Msk|GPIO_MODER_MODE11_Msk);
  //set any of the cleared bits
  reg_copy |= (GPIO_MODER_MODE2_0|GPIO_MODER_MODE11_0);
  //save it back to memory
  GPIOG->MODER = reg_copy;
 
}
 
void user_led_red_high(void)
{
  GPIOG->BSRR = GPIO_BSRR_BS2;
}
 
void user_led_red_low(void)
{
  GPIOG->BSRR = GPIO_BSRR_BR2;
}
 
void user_led_blue_low(void)
{
  GPIOG->BSRR = GPIO_BSRR_BR11;
}
 
void user_led_blue_high(void)
{
  GPIOG->BSRR = GPIO_BSRR_BS11;
}
 
void delay()
{
  uint64_t t,i;
  t = 1000000;
  for(i=0;i<t;i++)
  {
    __NOP();
  }
}
 
void set_system_clk_hse(int pre_speed, int divisor) {
  if (280 < pre_speed || pre_speed < 64) return; // VCO output range F_ref*[64, 280] (F_ref = 2) must be respected
  if (64 < divisor || divisor < 1) return;
  RCC -> CFGR |= RCC_CFGR_SW_PLL1; // System clock and trace clock switch: Select PLL1 as system clock
  //while ((RCC -> CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL1); // System clock switch status: Wait until PLL1 is system clock
  RCC -> CR |= RCC_CR_HSEON; // HSE clock enable
  while (!(RCC -> CR & RCC_CR_HSERDY)); // Wait until HSE clock is ready
  RCC -> PLLCKSELR = 0x020200C2; // Divide HSE by 12 = 24 / 12 = 2 MHz = F_ref
  int divp = 2*divisor - 1;
  int divn = pre_speed - 1;
  RCC -> PLL1DIVR = 0x01010000 + (divp << RCC_PLL1DIVR_P1_Pos) + divn; // Set register (reset = 0x01010280)
  RCC -> CR |= RCC_CR_PLL1ON; // PLL1 enable
  //while((RCC -> CR & RCC_CR_PLL1RDY) == 0); // Wait until PLL1 clock is ready
}
 
void set_system_clk_hsi(int pre_speed, int divisor) {
  if (280 < pre_speed || pre_speed < 64) return; // VCO output range F_ref*[64, 280] (F_ref = 2) must be respected
  if (64 < divisor || divisor < 1) return;
  RCC -> CFGR |= RCC_CFGR_SW_PLL1; // System clock and trace clock switch: Select PLL1 as system clock
  //while ((RCC -> CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL1); // System clock switch status: Wait until PLL1 is system clock
  int divp = 2*divisor - 1;
  int divn = pre_speed - 1;
  RCC -> PLL1DIVR = 0x01010000 + (divp << RCC_PLL1DIVR_P1_Pos) + divn; // Set register (reset = 0x01010280)
  RCC -> CR |= RCC_CR_PLL1ON; // PLL1 enable
  //while((RCC -> CR & RCC_CR_PLL1RDY) == 0); // Wait until PLL1 clock is ready
}
 
/*********************************************************************
*
*       main()
*
*  Function description
*   Application entry point.
*/
int main(void) {
  int pre_speed = 165; // Theoretically, pre_speeds from 64 to 280 should work
  int divisor = 1; // [1, 64]
  set_system_clk_hsi(pre_speed, divisor); // Speed = pre_speed / divisor; trial max ~ 164 MHz, theoretical max = 280 MHz (high range) or 210 MHz (low range)
  /* frequency:
  before divn1 = 2
  after divn1 = 2 * speed
  after div[p/q/r]1 = speed
  */
  setup_user_leds();
  while(1)
  {
    user_led_red_high();
    delay();
    user_led_blue_high();
    delay();
    user_led_red_low();
    delay();
    user_led_blue_low();
    delay();
  }
}

1 ACCEPTED SOLUTION

Accepted Solutions

You are not supposed to set PLL as system clock source *before* you actually set up PLL.

Also, make sure the proper VOS and FLASH latency are set for given system clock frequency.

JW

View solution in original post

1 REPLY 1

You are not supposed to set PLL as system clock source *before* you actually set up PLL.

Also, make sure the proper VOS and FLASH latency are set for given system clock frequency.

JW