cancel
Showing results for 
Search instead for 
Did you mean: 

Best way to configure clock [from scratch project]

Jems On
Associate II
Posted on March 24, 2018 at 17:51

Hello everyone,

I'm starting a blank project and would like to know the best way to configure the clocks (without using CubeMX).

The initial project therefore contains the startup file stm32f413xx.s as well as the file system_stm32f4xx.c and a main.c

In the startup file, after the reset comes the call of the SystemInit function present in the system_stm32f4xx.c

When using CubeMX, the system_stm32f4xx.c file is not modified and therefore remains the one proposed by the CMSIS driver by default.

The clocks are then modified in initialization via the SystemClock_Config () function;

using the function calls of the HAL library.

As I understand the clock configuration is done in two stages (not very effective)

I would like to configure the registers by myself without going through the HAL layer but I would like to know if the cleanest way is to keep the file system_stm32f4xx.c as it is provided in the CMSIS pack and to do a function of initialization

registers called in the main.

Or is it better to modify directly the system_stm32f4xx.c file.

Before using CubeMX we generated a file system_stm32f4xx.c from an excel clock syst

em configuration tool. C'�tait plutot propre. Existait il des soucis en proc�dant ainsi ? 

Thanks in advance !

#clock-configuration
7 REPLIES 7
AVI-crak
Senior
Posted on March 24, 2018 at 18:27

https://bitbucket.org/AVI-crak/rtos-cortex-m3-gcc/src/bc5ff54d96b3eae68b232a6367232439c1af389c/system_stm32f7xx.h?at=default&fileviewer=file-view-default

 

Registers stm32f4 - stm32f7 have a lot in common. In any case, you should be interested in lines numbered 235.

Posted on March 24, 2018 at 19:16

Type of question where you're going to get a dozen different answers.

I tend to prefer to use the CMSIS method via SystemInit() and SetSysClock() in system_stm32f4xx.c, with the F4 it has got to the point where my code determines the model of part I'm working and then sets the PLL and AHB/APB clocks to maximal settings for the part in question.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
T J
Lead
Posted on March 24, 2018 at 21:20

I use the Cube, it does a nice job,

I set all the peripherals to use the slowest clock available to reduce the processor power/temperature

for example the Usarts can be clocked at 216MHz or 12MHz. same with most peripherals.

The graphical view inside the Cube is excellent.

 I start by putting the 216MHz in first.

then fiddle the PLL settings so the USB gets to 48MHz

then you would want to consider the SAI set, it is problematic if you need it.

AVI-crak
Senior
Posted on March 25, 2018 at 11:44

I updated the sample for bullying system_stm32f7xx.h in the repository.

The essence of the update is to show the complexity of working with registers in direct circulation. HAL and LL use their own layer of abstraction, and the names only partially coincide with the documentation and CMSIS itself. The bottom line is that with a complete heritage of names there will be a terrible mess in the namespace, from which you will get sick.

The complexity of the work lies in the total study of the documentation, where a bit needs to be written. At the same time, the number of additional #define lines grows very quickly, and it is very difficult to control. LL wraps calls to registers through its own functions, and now the number of function names is growing - they are just a huge amount. All this in the space of global names, where your own functions and announcements are drowning.

There is an option - use dolls (examples) to fill the registers. For symbolic names of register bits, use static filled structures. At compilation a preprocessor will be used, which will remove all single-use static structures from the firmware - multiply them by zero.

It is necessary to study the documentation in any case, but it is important to do this with benefit. If you use magic numbers to fill the register (for example 0x32ff54ee) - then you will have to go back to reading the documentation more than once. Using a doll frees you from re-learning the documentation.

RCC->PLLCFGR = swPLLCFGR_DIVM(12)               // Primary frequency divider 2-63

                               |swPLLCFGR_PLLN(324)             // Clock multiplier for PLLCLK 50-432

                               |swPLLCFGR_DIVP(2)                  // The last divisor for PLLCLK 2,4,6,8

                               |swPLLCFGR_DIVQ(9)                  // Divisor for USB, SDMMC, and RNG 2-15

                               |RCC_PLLCFGR_PLLSRC_HSE; // 0x00000000U Clock from HSE
Posted on March 25, 2018 at 10:02

Thanks Clive for your answer.

You're right, my question has several answers but your way of doing seems to me the most relevant for my project

For the configuration of the registers   RCC->CR,  RCC->CFGR  RCC->PLLCFGR  RCC->CIR , you modify them directly in the function SystemInit() ?

Would you have an initialization example that you use?

Thanks Clive

Posted on March 25, 2018 at 15:51

You're totally right.

using registers can make the code more difficult to manage and

ut the use of libraries requires too many functions.

On the same basis I  configure clocks as well using the defines of the file stm32f413xx.h:

 [CODE]

 RCC->CFGR = (0 << RCC_CFGR_SW_Pos)                     /*!< SW[1:0] bits (System clock Switch) */

            |(0 << RCC_CFGR_SWS_Pos)                    /*!< SWS[1:0] bits (System Clock Switch Status) */

            |(0 << RCC_CFGR_HPRE_Pos)                   /*!< HPRE[3:0] bits (AHB prescaler)  [HCLK] */

            |(4 << RCC_CFGR_PPRE1_Pos)                  /*!< PRE1[2:0] bits (APB1 prescaler) [PCLK1] */

            |(0 << RCC_CFGR_PPRE2_Pos)                  /*!< PRE2[2:0] bits (APB2 prescaler) [PCLK2] */

            |( << RCC_CFGR_RTCPRE_Pos)                  /*!< RTCPRE[4:0] bits (HSE division factor for RTC clock) */

            |( << RCC_CFGR_MCO1_Pos)                    /*!< MCO1[1:0] bits (Microcontroller clock output 1) */

            |( << RCC_CFGR_MCO1PRE_Pos)                 /*!< MCO1PRE[1:0] MCO1 prescaler */

            |( << RCC_CFGR_MCO2PRE_Pos)                 /*!< MCO2PRE[1:0] MCO2 prescaler */

            |( << RCC_CFGR_MCO2_Pos)                    /*!< MCO2[1:0] bits (Microcontroller clock output 2) */

 //etc ...

[/CODE]

Thank you for your answer !

Posted on March 25, 2018 at 18:28

And still, look at my option

https://bitbucket.org/AVI-crak/system_f746/src/7422207476d059b8fce5c72c82eae3adb0232e54/stm32f7_emus.h?at=default&fileviewer=file-view-default

  .

You need protection from input errors, + character names instead of magic numbers, and a small context help. In addition, you need to collect all functions and variables related to the same register in one place. In the final version, the same doll will turn out.

You will need to copy the doll and remove the redundant information. This is much more reliable than a separate self-padding.