cancel
Showing results for 
Search instead for 
Did you mean: 

Manual Clock Configuration Issue

Len_Heske
Associate III

Hello,

first let me start this post by mentioning that I'm still very much a beginner.

I'm writing my own abstraction layer functions for the N657X0.

While running my clock_config() function, I ran into an issue that I don't know how to fix. The function works as follows:

- reset RCC->CR, CRGR1, CFGR2

- enable MSI and wait for MSI ready bit

- set CPU & SYS clock source to MSI and wait for clock source confirmation bits

- disable all other oscillators and all PLL

- reset RCC->HSICFGR

- configure HSI

- enable HSI and wait for HSI ready bit

- set CPU & SYS clock source to HSI and wait for clock source confirmation bits

- disable MSI

- reset RCC->MSICFGR

- configure MSI

- enable/disable oscillators (if HSIEN=0 then MSIEN=1 and vice-versa)

- reset RCC->ICxCFGR

- configure ICx

- reset RCC->PLLxCFGRx

- configure PLLx

- enable PLLx and wait for PLLx lock ready bit

- check CPU and SYS clock source selection

- check if source is actually active by checking the corresponding ready bit again

- select CPU and SYS clock sources (IC1 for CPU and IC2 for SYS)

- wait for clock source confirmation bits <- endless wait loop fault here!

 

The fault occurs at the very last link in the chain. I checked the clock source ready bit before when setting the sources to MSI/HSI and it worked then but not at the end. Is my clock_config() logic sound at all?

 

15 REPLIES 15
TDK
Super User

You should be more deliberate when changing RCC register values to avoid invalid intermediate states. For example:

reset(&rcc.CR);

This cannot clear the CR register as that would stop all clocks. The CPU needs a clock to run. The hardware is smart enough to avoid letting you do this, but you shouldn't rely on that. The state of CR after this operation is (a) definitely not 0 and (b) dependent upon the current clock configuration.

> RCC_SR_PLL1RDY_Msk

Are these the bits not being set? If so, there's probably a misconfiguration issue. Looking at the RCC register values as @waclawek.jan suggests at the time the issue occurs is probably the best approach to debugging.

I don't see wait states being set anywhere in here. Could have missed it.

The checks done in HAL_RCC_OscConfig are done deliberately to ensure the system transitions smoothly to the target state. Your code will need to do the same, or need to ensure the starting state is always the same.

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

Hello @TDK ,

sorry for the very late reply. I couldn't look into it very much the last few day as I didn't have much time.

First of all thank you very much for your reply! :)

Just so you know, the reset() function doesn't clear the register. It only writes the default reset condition word - as specified in the manuals - into that register. Every register has a reset word and the structs "[REFERENCE].[REGISTER_NAME]" (like "rcc.CR" or "a.MODER" for GPIOA) contain a register pointer and the specific reset word like 0x00000008. These writes should not violate any rules as they essentially don't change anything and just make sure the register is in its default state.

RCC_SR_PLL1RDY_Msk

^This is a ST specific mask that I didn't create but is instead a standard constant in the ST libraries. Same goes for any constant names similar to this. There are three types: (1) no ending for single bits or bit position "_0", "_1", "_[n]" to indicate a high bit in that position, (2) "_Msk" ending to indicate a mask for that bit segment (relevant if mask is more than one bit) and (3) "_Pos" ending to indicate the starting position of the segment. As these are ST constants, I'm very confident that they are not a problem or could cause any issues.

HAL_RCC_OscConfig

Thank you for suggesting this HAL function. I'll look into it and see if I can check its source code for more information.

I generally cleaned up my code a bit and improved and expanded the error information on return for better troubleshooting. I'll keep you updated and post a fix if I can find it so that I may close this case. I'm always open and glad for more feedback and suggestions. I'm still a beginner after all and need to learn a lot.

Kind regards,

Len

Hello @waclawek.jan ,

I took some time to read up on what you said.

In development mode, I load my FSBL program from my debug PC straight into the internal SRAM of the microcontroller. The N657 does not have internal flash memory like other µc. Instead, the programs are loaded into the internal SRAM either from external Octo-SPI flash memory in flash mode or from a debug PC in development mode through an ST-Link connection. The latter making the program not persistent, as I already noticed myself.

So in conclusion, it is never the goal to run a program from flash memory but to always load it into the SRAM before execution. Which is either done through ST-Link or the BootROM, but - as far as I know - not by the user.

Since the program is always loaded into SRAM before execution, memory bus configuration and flash wait states are not relevant, I think...

Kind regards

Len

waclawek.jan
Super User

> The N657 does not have internal flash memory like other µc.

Oh. OK, learned that, thanks.

JW

LCE
Principal II

I recently checked the N6, and oh my - what a beast, especially the clock configuration.

I'm also a big fan of NOT using STM's HAL, but as said before: at least use it for "inspiration" how this is set up.

Len_Heske
Associate III

Solved!

Had to enable PLLxPDIV, set PLLxMODSSDIS and PLLxMODSSRST high and PLLxMODDSEN low, as well as enabling ICx - which I had no idea was something you had to enable - through a register somewhere far far into the register list.

For anyone who ever finds themselves in a similar situation, consider the following checklist:

(Whenever I talk about "resetting" a register, do NOT just set it to 0x00000000, but rather the specific default value as stated for each register in RM0486!)

  • reset RCC_CR, leave MSI on (you need two clock sources - HSI & MSI - for clock configuration)
  • wait for ready bits on/off in RCC_SR
  • reset RCC_CFGR1
  • wait for source confirmation bits in RCC_CFGR1
  • configure overdrive pin for higher clock speeds (optional - won't go into detail)
  • switch to MSI inside RCC_CFGR1
  • wait for source confirmation bits in RCC_CFGR1
  • disable HSI
  • wait for ready bits on/off in RCC_SR
  • configure HSI
  • enable HSI
  • wait for ready bits on/off in RCC_SR
  • switch to HSI inside RCC_CFGR1
  • wait for source confirmation bits in RCC_CFGR1
  • disable MSI
  • wait for ready bits on/off in RCC_SR
  • configure MSI
  • enable MSI (optional. we are done using it to configure HSI)
  • (wait for ready bits on/off in RCC_SR)
  • disable all ICx through RCC_DIVENCR
  • configure PLLx (stick to integer mode if you don't know much about the other modes!)
    • reset RCC_PLLxCFGRx (1,2,3)
    • select oscillator (f_osc >= 5MHz so you can't use MSI in 4MHz mode!)
    • set DIVM (f_DIVMout <= 50MHz)
    • set DIVN (f_DIVNout <= 3200MHz)
    • clear RCC_PLLxCFGR2 (has to be empty for integer mode)
    • enable PLLxPDIV
    • set PLLxPDIV1 & PLLxPDIV2 to 1
    • set PLLxMODSSDIS high
    • set PLLxMODSSRST high
    • set PLLxMODDSEN low (as well as other unused bits)
    • either enable or bypass PLLx with PLLxON in RCC_CR or PLLxBYP in RCC_PLLxCFGR1
    • wait for ready bits on/off in RCC_SR
  • configure ICx through RCC_ICxCFGR
    • reset RCC_ICxCFGR
    • select PLLx
    • select division factor
    • enable ICx through RCC_DIVENSR
  • reset RCC_CFGR2
  • configure TIMPRE, HPRE and PPREx (1,2,4,5)
  • select final clock source in RCC_CFGR1
  • wait for source confirmation bits in RCC_CFGR1

Hope this helps!

Kind regards

Len