stm32f0/l0: Fix HSI48 USB clock recovery configuration. - #19904
Merged
xiaoxiang781216 merged 5 commits intoAug 20, 2026
Conversation
The clock recovery system peripheral clock was enabled only when CONFIG_STM32_CRS was selected. The CRS is required by any board that uses HSI48 as the 48MHz clock source, because HSI48 must be trimmed from an external synchronisation event to stay within the tolerance demanded by USB full speed operation. STM32_USE_HSI48 is the condition under which the remaining HSI48 and CRS setup is compiled in, see stm32_enable_hsi48(), so accept that condition here as well. Without the peripheral clock the CRS registers are inaccessible and automatic trimming silently does nothing. CONFIG_STM32_CRS is retained so that boards selecting the CRS directly are unaffected. Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
The SYSCFG peripheral clock was gated on CONFIG_STM32_SYSCFG, but that symbol is not defined by the STM32L0 Kconfig (only stm32h7 declares it), so RCC_APB2ENR_SYSCFGEN was never set on this chip. With SYSCFG unclocked every write performed by vrefint_enable() is discarded and SYSCFG_CFGR3 reads back as 0x00000000. VREFINT and, in particular, the ENBUFVREFINTHSI48 reference for the HSI48 oscillator are therefore never enabled. HSI48 still reports HSI48RDY, but it runs without its voltage reference and the 48MHz clock supplied to the USB device controller is unusable: the controller cannot sample the bus, never latches a reset condition in USB_ISTR, and never raises its interrupt. The result is a USB device that is configured correctly in every visible register yet never enumerates. VREFINT is configured exclusively through SYSCFG_CFGR3, so enable the SYSCFG clock whenever CONFIG_STM32_VREFINT is selected. Observed on NUCLEO-L073RZ (STM32L073RZ): before: SYSCFG_CFGR3 = 0x00000000, no enumeration after: SYSCFG_CFGR3 non-zero, device enumerates as CDC/ACM Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
stm32_enable_hsi48() set CRS_CR_AUTOTRIMEN but left CRS_CR_CEN clear. AUTOTRIMEN only instructs the hardware to apply corrections derived from the frequency error counter; the counter itself is enabled by CEN. With CEN clear no error measurement is ever produced and the HSI48 TRIM value stays at its reset default, so the oscillator is never disciplined to the synchronisation source. Set both bits, matching the value the STM32 ROM bootloader programs when it runs its own crystal-less USB stack (CRS_CR = 0x1a60, i.e. CEN | AUTOTRIMEN with a trimmed TRIM field). This file is shared by the M0 STM32 parts (F0, G0, C0, L0); all of them require CEN for automatic trimming to function. Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
STM32_HSI48_SYNCSRC was SYNCSRC_NONE, which makes stm32_enable_hsi48() return before configuring the CRS at all. HSI48 then free runs at its untrimmed factory frequency, which is not accurate enough for USB full speed operation. The board has no CRS_SYNC pin wired and does not fit an LSE crystal for this purpose, so the USB start of frame packet is the available synchronisation source. This is the intended configuration for crystal-less USB on this part. Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
vrefint_enable() sets SYSCFG_CFGR3_ENBUFVREFINTHSI48 in its local copy of the register value but never writes that value back to the hardware. The VREFINT reference for the HSI48 scaler is therefore never enabled. Only the earlier ENVREFINT update reaches the register, so VREFINT itself is enabled while the HSI48 reference is not. HSI48 then runs without its voltage reference and the 48MHz clock is not accurate enough to be used by the USB device controller. Write the register after applying the HSI48 reference bit. Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
jsanchez-2g
requested review from
antmerlino,
jerpelea,
linguini1,
raiden00pl and
xiaoxiang781216
as code owners
August 20, 2026 01:10
xiaoxiang781216
approved these changes
Aug 20, 2026
jerpelea
approved these changes
Aug 20, 2026
jerpelea
approved these changes
Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix HSI48 and clock recovery system configuration required for crystal-less USB
device operation on STM32F0 and STM32L0.
The fixes:
support for boards that explicitly select CONFIG_STM32_CRS.
voltage-reference bit was updated only in a local variable.
Before these changes, USB device registers could appear correctly configured,
and the host could detect the D+ pull-up, but the 48 MHz clock was not usable:
the controller did not latch USB reset in USB_ISTR and never raised its USB
interrupt.
Impact
which also supports STM32U0.
included with the corresponding board-support PRs.
the CRS is now correctly enabled and able to trim the oscillator.
Testing
Build host:
Hardware:
Before:
unclocked. USB_ISTR never latched host reset, and USB IRQ 47 never fired.
pristine apache/master plus board support.
After:
CRS_CR enables CEN and AUTOTRIMEN; NSH and USB CDC/ACM enumeration pass.
NuttX Apps checkout after the signed histories were rebuilt.
Validation:
PR verification Self-Check