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?

 

1 ACCEPTED SOLUTION

Accepted Solutions
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

View solution in original post

15 REPLIES 15
mƎALLEm
ST Employee

Hello,

As you are a beginner, I suggest you to use the HAL + CubeMx at the first time at least to inspire from the implementation.

PS: I'm not forcing you to use the HAL. I'm just suggesting you to accelerate the process, to understand the register configuration sequence and do some debug from your side.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Hello @mƎALLEm,

thank you for your answer :)

Are you suggesting I should look at the HAL function code for inspiration? I should do that. Otherwise, I don't want to use HAL for my projects. I'm writing my own abstraction layer as a way to learn and as a hobby.

I'm using CubeMX only by looking at its clock config UI. The UI helps me understand how the oscillators and clock sources work. But I don't use CubeMX to setup my projects. I started with a bare bone main.c with nothing but the main function.

I'm wondering though, if you are seeing any glaring issue with my config logic? I'm not asking for help in regards to code fixing, just whether the overall logic is sound or not.

Thank you and kind regards,

Len

I was anticipating that reply from you and that's why I said:

"PS: I'm not forcing you to use the HAL. I'm just suggesting you to accelerate the process, to understand the register configuration sequence and do some debug from your side. "

I know you need to do it yourself but N6 is a complex product especially for beginners.  So what I suggest is to start with HAL and inspire from it. May be you find the answers there..

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Hello @mƎALLEm,

don't get me wrong, I totally understand this suggestion! What I'm doing is unnecessary and not the advisable thing to do as a beginner. I 100% agree with that notion.

I just do it as a hobby and it's not part of any serious workflow.

I'm sorry if my reply came across as cocky :)

Kind regards,

Len


@Len_Heske wrote:

I'm sorry if my reply came across as cocky :)


Don't worry.. I didn't feel targeted at all ;) . Just needed to clarify how to proceed..

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Danish1
Lead III

What values do you actually get in the clock source confirmation bits? And in other RCC registers?

Could you share your code? You describe yourself as a beginner. It is possible you've made a mistake e.g. in your bitwise operations looking for the confirmation bits

TDK
Super User

> The function works as follows: 

Why not show the function itself?

Only translation errors can be introduced by paraphrasing what it's doing.

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

I am not familiar with the 'Nx.

Are you running from FLASH? Do you set FLASH waitstates according to the system frequency?

Also, while others call for showing code, I'd recommend to read out and check/post content of relevant registers.

JW

Hello @Danish1 and @TDK ,

thank you very much for your answers!

Should I send the entire code, i.e. my main.c and my library? Or just the function in question? I work with a lot of structs, so I'm concerned about the readability of it.

I attached a file with the function in question and some comments. I have no idea what a good code should look like so I'm sorry if it's ugly :D

 

Btw, this is the definition of the clear() function if you think it could be the culprit:

void clear(volatile uint32_t*reg, unsigned bit, unsigned pos)
{

    *reg &= ~(((high<<bit)-high)<<pos);
}

 

Kind regards,

Len