Strangely accurate ADC noise
I've been struggling with a strange ADC problem for a while, and have now made some interesting observations.
The scenario
I'm using an STM32G474, where HRTIM directly controls a peltier driver for temperature regulation. Temperatures are measured by ADC4 (12 bit resolution), running in DMA circular mode, triggered by TIM7, at 1 kHz. This works. Temperatures are coming in, and are being used for PID regulation.
The problem
Quite often – perhaps always – some of the temperature readings are being disturbed, but only at certain temperatures. At first, I thought that it was random noise, but in a graph the noise looks strange. Not random at all.
After monitoring the raw ADC values that the DMA has thrown into memory, I discovered something that might be a clue – or it might just be a source of confusion. Every time a noisy sequence occurs, the ADC readout jumps to a lower nearby value where the five least significant bits are all 1, i.e. xxxx xxx1 1111. This is not random noise. It is if as the values are rounded down to nearest 0x001F.
A single spurious readout once in a while can be handled. But when this occurs, it happens so much that the PID regulation is disturbed.
The disturbances are visible in this chart. The orange trace are raw ADC samples, copied directly from the array that the DMA dumps the ADC values in. ADC values are on the right hand axis (decimal). The blue trace is the converted temperature readout, which is where I first noticed the problem.

The disturbing ADC values in this example are 0x073F, 0x07BF, 0x083F and 0x08BF. All ending with the 11111 bit pattern, and exactly 128 ADC counts apart. I have also run tests where the spacing was 64 counts. This also tells me that this isn't random noise.
Some zoomed-in examples:


Apparently, it doesn't matter if the temperature is slowly moving up or down:


During other tests, I have observed this behaviour at other values – but always with the xxxx xxx1 1111 pattern in the ADC value. I have watched the sampled values in RAM, by using STM32Programmer through the SWD interface. This is where I first spotted the recurring bit pattern.
I've checked my code (obviously), to see that the ADC value array isn't overwritten before is is handled in the interrupt function. The only thing that overwrites this array is the DMA channel.
What does the errata sheet say about this? The only section I've found that might be relevant, is this one:

I'm using all five ADCs for different purposes, all using the same clock source, with prescalers set to 1. Perhaps ADC4 is being disturbed by one of the other ADCs. If this is the case, I may be able to make a work-around.
But again, these aren't random disturbances. They only happen in certain windows, hitting very specific values.
I am unsure about what to show you, regarding setup and code. There is a lot of code in this project. But here is how ADC4 is setup in CubeMX:

Sampling time and offset is the same for all channels.
The function that initialises DMA, and starts ADC4:
void adcInitADC4(void)
{
ADC4Handle->Instance->CR = ADC_CR_ADVREGEN; // ADC disable
ADC4Handle->Instance->CR |= ADC_CR_ADCAL; // Start calibration
ADC4DMAHandle->Instance->CCR &=~ DMA_CCR_EN; // DMA channel off
ADC4DMAHandle->Instance->CCR |= DMA_CCR_TCIE; // Turn on DMA interrupt
ADC4DMAHandle->Instance->CNDTR = 10; // Ten transfers to memory
ADC4DMAHandle->Instance->CPAR = (uint32_t)&ADC4->DR; // Set peripheral address (ADC data register)
ADC4DMAHandle->Instance->CMAR = (uint32_t)&ADC4Buffer[0]; // Set memory address
ADC4DMAHandle->Instance->CCR |= DMA_CCR_EN; // Enable DMA
while (ADC4Handle->Instance->CR & ADC_CR_ADCAL) __asm("NOP");
ADC4Handle->Instance->CFGR |= ADC_CFGR_DMAEN; // DMA transfer enable
ADC4Handle->Instance->ISR = ADC_ISR_ADRDY; // Clear ADC ready Flag
ADC4Handle->Instance->CR |= ADC_CR_ADEN; // Enable ADC
while (!(ADC4Handle->Instance->ISR & ADC_ISR_ADRDY)); // Wait for ADC ready
ADC4Handle->Instance->CR |= ADC_CR_ADSTART; // Start ADC
TIM7->CR1 |= TIM_CR1_CEN;
}Can anyone help shed some light on this weirdness?
