On the STM32F722 (at least, but STM32F767 is not affected) the CK48MSEL bit
must be deselected before PLLSAION is turned off, or else the 48MHz
peripherals (RNG, SDMMC, USB) may get stuck without a clock source.
In such "lock up" cases it seems that these peripherals are still being
clocked from the PLLSAI even though the CK48MSEL bit is turned off. A hard
reset does not get them out of this stuck state. Enabling the PLLSAI and
then disabling it does get them out. A test case to see this is:
import machine, pyb
for i in range(100):
machine.freq(122_000000)
machine.freq(120_000000)
print(i, [pyb.rng() for _ in range(4)])
On occasion the RNG will just return 0's, but will get fixed again on the
next loop (when PLLSAI is enabled by the change to a SYSCLK of 122MHz).
Fixes issue #4696.
To use HSI instead of HSE define MICROPY_HW_CLK_USE_HSI as 1 in the board
configuration file. The default is to use HSE.
HSI has been made the default for the NUCLEO_F401RE board to serve as an
example, and because early revisions of this board need a hardware
modification to get HSE working.
Configuring clocks is a critical operation and is best to avoid when
possible. If the clocks really need to be reset to the same values then
one can pass in a slightly higher value, eg 168000001 Hz to get 168MHz.
This ensures that on first boot the most optimal settings are used for the
voltage scaling and flash latency (for F7 MCUs).
This commit also provides more fine-grained control for the flash latency
settings.
Power and clock control is low-level functionality and it makes sense to
have it in a dedicated file, at least so it can be reused by other parts of
the code.