STM32 gotchas
221. ADC may freeze around calibration or enable/disable, sequencing has to be observed carefully

Users sometimes report ADC freezing, typically when waiting for some of the "ready" signals around calibration, or ADC enable/disable. Unfortunately, such reports are rarely confirmed/reproduced and the root cause established.

It appears, that these incidents may stem from the fact that ADC is a typical dual-clock peripheral, and that signals have to cross between the APB domain (with which the rest of the chip interacts) and the kernel-clock domain (which contains the actual hardware performing the conversions). This involves resynchronizations of the signals, and timing of these depends on the minute details of both clocks, resulting in varying timing with different clocks settings. This, together with the inherent difficulties to precisely control timing in the 32-bit microcontrollers (especially if a high-level language such as C is involved), may be the reason why are these issues so hard to reproduce.

It may well be, that by following more meticulously the guidelines in the Reference Manual would prevent some of these incidents to happen. However, this also indicates, that programming the ADC may be challenging and requires care.

Let's have a look at some of the reported cases:

In 'G0 (and related 'C0 and 'WL families), there should be a 2 ADC kernel clock delay observed after disabling the ADC, and performing any other ADC-kernel-related operation (such as re-enabling ADC, or performing calibration, or writing the calibration factor).

In 'L4, it appears, that there needs to be a delay between end of calibration and enabling the ADC. One way to tackle this is to keep setting the ADC enable bit in a loop, until the ADRDY bit indicates that ADC is enabled. This problem will probably get more pronounced with high difference between system clock and ADC kernel clock frequencies (e.g. due to high ADC clock divider). (The initial post in that same thread appears to describe a slightly different problem in 'F3, namely that the default setting of ADC clock in ADCx_CCR.CKMODE is the asynchronous ("product level") clock to be set in some of the RCC registers, but the default setting there for this particular family is disabled clock).

In 'L0, writing to any field of ADC_CFGR2 while ADC is enabled (ADC_CR.ADEN = 1) results in the ADC kernel losing its clock and "freezing". While description of ADC_CFGR2.CKMODE prohibits writing to it while ADC is enabled, other fields don't have this warning; but writing to any of them rewrites the whole register thus ADC_CFGR2.CKMODE too.

In 'U5, delay may be needed between writing the CALINDEX field in ADC_CR and ADC_CALFACT2 registers.