STM32 gotchas
159. PLLI2S/PLLSAI outputs unexpected frequency (due to prescaler shared amongst PLLs)

Some STM32 families - e.g. 'F4/'F7/'L4 but also others - have several PLL units in their RCC module. One of the PLLs - "main" - is dedicated for system clock generation, and the others allow to generate relatively independent clocks, mostly to the audio-related modules such as I2S and SAI.

Details of interconnections of inputs and outputs of these PLLs to other signals within RCC differ significantly from family to family - and even between models within a family - but in many models there is only one path for the input reference signal, shared amongst all PLLs. It means, that there is only one multiplexer which selects usually between HSI and HSE as primary clock source, and one single prescaler, controlled by the PLLM field of the "main" PLL's control register (usually RCC_PLLCFGR).

As soon as any of the PLLs is enabled, the PLLM field is locked and cannot be written anymore. This means, that software shall set up all PLLs at once, or otherwise set them up with this limitation in mind.

However, functions for PLL setup in some libraries - e.g. the Cube/LL - expect, that they are able to write all fields determining the PLL's output frequency: the prescaler M, VCO divider ("multiplier") N, and post-scalers (STM32 PLLs have up to 3 outputs from a single VCO, so there are up to 3 post-scaler fields, P, Q and R). The usual setup is, that the "main" PLL is enabled the first, so calling its setup function sets the PLLM value and locks it. If, subsequently a function attempts to set one of the "auxilliary" PLLs with a different M setting, the new M value is quietly ignored, and as a result that PLL then outputs a surprising and unexpected frequency.