Skip to content

[Tracking] Refactor STM32 clock configuration and initialization #14975

Open
@aabadie

Description

Description

This issue is a tracking for the refactoring of the clock configuration and initialization on STM32 cpus.

Current situation

In the current situation, the whole clock configuration is done at board level although a lot parameters are CPU level specific.

  • Here is the list of clock parameters that doesn't depend on the board configuration:

    • sysclk source clock: it can be either HSE, HSI, MSI (only on L0,L1,L4,WB families) or PLL but in RIOT only the PLL is used.
    • the PLL parameters (M,N,P,Q factors or PREDIV,MUL factors, depending on the families
    • the AHB/APBx dividers
  • There are other problems with the current clock configuration mechanism: it's not easy to change the parameters.
    For example, one would have to write his own config header and use pre-processor conditionals to skip the default values. This custom header would have to define all parameters, even if only a few needs to be tweaked.

  • For AHB/APBx dividers, there's no connection between the define of the divider value (it must contain the corresponding bitfields to put in the configuration register) and actual output clock of the bus. Example:

    #define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1
    #define CLOCK_AHB (CLOCK_CORECLOCK / 1)
    #define CLOCK_APB1_DIV RCC_CFGR_PPRE_DIV1 /* max 48MHz */
    #define CLOCK_APB1 (CLOCK_CORECLOCK / 1)
    #define CLOCK_APB2 (CLOCK_APB1)

    Here, CLOCK_APB1 is CLOCK_CORECLOCK divided by 1, but CLOCK_APB1_DIV is not 1, it's the corresponding bitfield. It would be simpler to directly compute CLOCK_APB1 from CLOCK_CORECLOCK and CLOCK_APB1_DIV:

#define CLOCK_APB1   CLOCK_CORECLOCK / CLOCK_APB1_DIV

And since APB1 corresponds to HCLK / CLOCK_APB1_DIV, it should even be CLOCK_AHB / CLOCK_APB1_DIV

  • Another issue with the current design is that CLOCK_CORECLOCK is hardcoded although it could easily be computed automatically, at build time, as a combination of the input clock frequency (either HSI or HSE) and the PLL factors.

  • The stm32fx.c file is mixing two different families of clocks initialization: those with M/N/P PLL (f2/f4/f7) and those with PREDIV/MUL PLL (F0/F1/F3)

  • About the selection of the 48MHz clock (used by USB): some 100MHz and 180MHz capable CPUs are forced to run at 96MHz and 168MHz to get a 48MHz clock PLLQ even if it's unused (no USB required for instance).

  • It is not possible to define the AHB divider to something different than 1, otherwise xtimer test applications are not working properly.

Expected situation

In general, the expected situation should provide a way to easily configure the clocks of a CPU: by easily, we mean no need to know the bitfields in advance and the parameters can be overridden via CFLAGS (command line or Makefile), a custom config header and Kconfig.

  • The only parameters that should depend on the board configuration are:
    • whether the board provides an HSE to clock the CPU
    • if there's one, the frequency of the HSE
    • whether the board provides an LSE (and eventually it's frequency)
  • All other parameters should be only exposed at the CPU level: SYSCLK source, PLL parameters, AHB/APBx dividers, MCO sources, enabling and config of 48MHz clocks

Doing this will allow a simpler and centralized clock configuration: less code duplication and more flexibility.
The CLOCK_CORECLOCK and all sub-clock values should be computed at build time with good defaults.

For the 48MHz source clocks, they should only be enabled if required by the application. For the moment, this is only the case when the USB peripheral feature is required.
On F4 and F7 families, several 48MHz clock source are possible (from PLLQ, PLLI2S or PLLSAI). The idea is to fall back to PLLI2S/PLLSAI when PLLQ cannot output 48MHz and to fail at build time if no 48MHz clock is available.
For 100MHz and 180MHz capable CPUs (typically on F4), we should by default configure them to reach their maximum clock frequency by default and adapt it when 48MHz is needed (and then their core clock would decrease to 96/168MHz).

After that rework, the cpu/dist/clk_conf tool will become obsolete and will not longer be needed.

Work to be done

Achieving what's described above is a lot of work and cannot be done in a single PR. To prepare the work needed for Kconfig, all configuration constants will be prefixed by CONFIG_.

Here are the steps needed (not necessary in order, for some there are already opened PRs and some PRs were already merged):

This is is not exhaustive and is subject to change over time.

Metadata

Assignees

Labels

Area: boardsArea: Board portsArea: cpuArea: CPU/MCU portsPlatform: ARMPlatform: This PR/issue effects ARM-based platformsType: enhancementThe issue suggests enhanceable parts / The PR enhances parts of the codebase / documentationType: trackingThe issue tracks and organizes the sub-tasks of a larger effort

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions