cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 XiP Clock change

ESawa.1
Senior

Hey together, 

I have a question regarding changing the clock while running in XiP mode. Upfront everything works so far very well. 

On our STM32H750 we have a very simple bootloader. This bootloader configures the QSPI and the STM32H7 to run the appliction code in XIP. Therefore we configure the QSPI clock to use the HCLK3 in the bootloader. We use an external crystal 8MHz and the PLL as SYSCLK to generate the 240MHz for the HCLK3. Then we jump to the application code. 

The applicaiton code resets the System Clock Mux in the startup code calling "SystemInit ()" inside the system_stm32h7xx.c to use the HSI (64MHz) for SYSCLK. This results at first in a drop of external crystal signal as well as a clock drop of the QSPI Clock from 240MHz to 64MHz. Then we reconfigure in the application code, while running in XiP, the System Clock Mux to use the external crystal and the PLL. Going back to the 240MHz for the QSPI. 

So far this seems to work perfectly fine, as there is always a clock present on the QSPI and we do not stuck or so. The question is: Can we keep this as it is? Otherwise we would have to prevent the clock reset inside the "SystemInit()" function somehow. Regenerating via CubeMX will then overwrite this part i guess. 

 

ESawa1_0-1761134946554.png

Best regards,

Eric 

1 ACCEPTED SOLUTION

Accepted Solutions

Hey @AScha.3 ,

I understand your solution to keep the clock tree in default for the application code. I guess this will work and will not regenerate the PLL reset inside the SystemInit(). But this is no real solution as all other interfaces which are used in the application would need the correct clock settings to show the right configuration inside of CubeMX. 

But I tried to comment the PLL reset inside the SystemInit() and regenerated the Code via CubeMX. It seems that CubeMX does not regenerate the "system_stm32h7xx.c". This is good as i can prevent it in this way. 

Hopefully ST keeps that there is no regeneration of "system_stm32h7xx.c". 

Best regards and thanks a lot for your support,

Eric 

 

View solution in original post

6 REPLIES 6
AScha.3
Super User

Hi,

is the basic code generated from Cube or IDE?

-

Because in my (generated) code is no new clock switching...

SystemInit () is just :

void SystemInit(void)
{
  /* Configure the Vector Table location -------------------------------------*/
  SCB->VTOR = INTVECT_START;

  /* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  SCB->CPACR |= ((3UL << 20U)|(3UL << 22U));  /* set CP10 and CP11 Full Access */
#endif
}
If you feel a post has answered your question, please click "Accept as Solution".
ESawa.1
Senior

Hey @AScha.3 

yes it is in the auto generated code from CubeMX. I guess it depends on the configuration you use in CubeMX. Here is my auto gernerated SystemInit

void SystemInit (void)
{
#if defined (DATA_IN_D2_SRAM)
 __IO uint32_t tmpreg;
#endif /* DATA_IN_D2_SRAM */

  /* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2)));  /* set CP10 and CP11 Full Access */
  #endif
  /* Reset the RCC clock configuration to the default reset state ------------*/

   /* Increasing the CPU frequency */
  if(FLASH_LATENCY_DEFAULT  > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
  {
    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
  }

  /* Set HSION bit */
  RCC->CR |= RCC_CR_HSION;

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000;

  /* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
  RCC->CR &= 0xEAF6ED7FU;

   /* Decreasing the number of wait states because of lower CPU frequency */
  if(FLASH_LATENCY_DEFAULT  < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
  {
    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
  }

#if defined(D3_SRAM_BASE)
  /* Reset D1CFGR register */
  RCC->D1CFGR = 0x00000000;

  /* Reset D2CFGR register */
  RCC->D2CFGR = 0x00000000;

  /* Reset D3CFGR register */
  RCC->D3CFGR = 0x00000000;
#else
  /* Reset CDCFGR1 register */
  RCC->CDCFGR1 = 0x00000000;

  /* Reset CDCFGR2 register */
  RCC->CDCFGR2 = 0x00000000;

  /* Reset SRDCFGR register */
  RCC->SRDCFGR = 0x00000000;
#endif
  /* Reset PLLCKSELR register */
  RCC->PLLCKSELR = 0x02020200;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x01FF0000;
  /* Reset PLL1DIVR register */
  RCC->PLL1DIVR = 0x01010280;
  /* Reset PLL1FRACR register */
  RCC->PLL1FRACR = 0x00000000;

  /* Reset PLL2DIVR register */
  RCC->PLL2DIVR = 0x01010280;

  /* Reset PLL2FRACR register */

  RCC->PLL2FRACR = 0x00000000;
  /* Reset PLL3DIVR register */
  RCC->PLL3DIVR = 0x01010280;

  /* Reset PLL3FRACR register */
  RCC->PLL3FRACR = 0x00000000;

  /* Reset HSEBYP bit */
  RCC->CR &= 0xFFFBFFFFU;

  /* Disable all interrupts */
  RCC->CIER = 0x00000000;

#if (STM32H7_DEV_ID == 0x450UL)
  /* dual core CM7 or single core line */
  if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
  {
    /* if stm32h7 revY*/
    /* Change  the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
    *((__IO uint32_t*)0x51008108) = 0x000000001U;
  }
#endif /* STM32H7_DEV_ID */

#if defined(DATA_IN_D2_SRAM)
  /* in case of initialized data in D2 SRAM (AHB SRAM), enable the D2 SRAM clock (AHB SRAM clock) */
#if defined(RCC_AHB2ENR_D2SRAM3EN)
  RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
#elif defined(RCC_AHB2ENR_D2SRAM2EN)
  RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
#else
  RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
#endif /* RCC_AHB2ENR_D2SRAM3EN */

  tmpreg = RCC->AHB2ENR;
  (void) tmpreg;
#endif /* DATA_IN_D2_SRAM */

#if defined(DUAL_CORE) && defined(CORE_CM4)
  /* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */

#else
  /*
   * Disable the FMC bank1 (enabled after reset).
   * This, prevents CPU speculation access on this bank which blocks the use of FMC during
   * 24us. During this time the others FMC master (such as LTDC) cannot use it!
   */
  FMC_Bank1_R->BTCR[0] = 0x000030D2;

  /* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */

#endif /*DUAL_CORE && CORE_CM4*/
}

 So you can see that the full PLL is reset in this function. 

Best regards,

Eric

>I guess it depends on the configuration you use in CubeMX

I guess you guess right. :)

 

+

Maybe you use some peripherals only in app, not in boot; so it needs to change the clock tree settings,

for init everything used in app.

Try check all peripherals, that need a certain clock, also in boot. Even if not used here at all.

So no new clock setup needed in app start.

If you feel a post has answered your question, please click "Accept as Solution".

Hey @AScha.3 ,

I think you are totally right this would be the best way to go. But there are still 2 questions open: 

Q1: Is it critical as we use it at the moment? If not, there is no need to create a dependency between bootloader and application. 

Q2: Is there a way to prevent CubeMX from regenerating the PLL reset inside SystemInit()? Otherwise it is super dangerous to modify the CubeMX file and we forget to disable the PLL reset by hand. 

But when I am thinking about it more in detail. I guess at least for Q2, we could just exclude the system_stm32h7xx.c file and provide our own one without the PLL reset. 

Best regards,

Eric

Q1:  I dont know for sure, but as clock switching has to be (!) always "clean" (= no spikes, etc), otherwise all this cpu/soc would hang up even on startup and first PLL/tree setting, it should be never "critical".

 

> Q2: If no clock/tree changes needed...it should not generate them.

or try: in project settings, to not generate it at all:

AScha3_0-1761211048027.png

But be sure, all needed clocks are already set active.

If you feel a post has answered your question, please click "Accept as Solution".

Hey @AScha.3 ,

I understand your solution to keep the clock tree in default for the application code. I guess this will work and will not regenerate the PLL reset inside the SystemInit(). But this is no real solution as all other interfaces which are used in the application would need the correct clock settings to show the right configuration inside of CubeMX. 

But I tried to comment the PLL reset inside the SystemInit() and regenerated the Code via CubeMX. It seems that CubeMX does not regenerate the "system_stm32h7xx.c". This is good as i can prevent it in this way. 

Hopefully ST keeps that there is no regeneration of "system_stm32h7xx.c". 

Best regards and thanks a lot for your support,

Eric