Even though IRQs are disabled this seems to be required on H7 Rev Y,
otherwise Systick interrupt triggers and the MCU leaves the stop mode
immediately.
This commit saves OSCs/PLLs state before STOP mode and restores them on
exit. Some boards use HSI48 for USB for example, others have PLL2/3
enabled, etc.
This commit improves pllvalues.py to generate PLL values for H7 MCUs that
are valid (VCO in and out are in range) and extend for the entire range of
SYSCLK values up to 400MHz (up to 480MHz is currently unsupported).
PLLM is shared among all PLL blocks on F7 MCUs, and this calculation to
configure PLLSAI to have 48MHz on the P output previously assumed that PLLM
is equal to HSE (eg PLLM=25 for HSE=25MHz). This commit relaxes this
assumption to allow other values of PLLM.
This new series of MCUs is similar to the L4 series with an additional
Cortex-M0 coprocessor. The firmware for the wireless stack must be managed
separately and MicroPython does not currently interface to it. Supported
features so far include: RTC, UART, USB, internal flash filesystem.
Entering a bootloader (ST system bootloader, or custom mboot) from software
by directly branching to it is not reliable, and the reliability of it
working can depend on the peripherals that were enabled by the application
code. It's also not possible to branch to a bootloader if the WDT is
enabled (unless the bootloader has specific provisions to feed the WDT).
This patch changes the way a bootloader is entered from software by first
doing a complete system reset, then branching to the desired bootloader
early on in the start-up process. The top two words of RAM (of the stack)
are reserved to store flags indicating that the bootloader should be
entered after a reset.
This patch makes pllvalues.py generate two tables: one for when HSI is used
and one for when HSE is used. The correct table is then selected at
compile time via the existing MICROPY_HW_CLK_USE_HSI.
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.