hw/adc/stm32f2xx_adc: fix left-aligned conversion results

Left-aligned regular conversion results must occupy bits [15:4],
[15:6], or [15:8] for 12-, 10-, or 8-bit resolution respectively.
At 6-bit resolution the result is aligned within a byte, in bits [7:2].

The current single-bit shift and 0xFFF0 mask both misalign the result
and discard significant sample bits. Select the shift according to RES
and keep the existing right-aligned sample generation unchanged.

Signed-off-by: Manuele Conti <conti.manuele@gmail.com>
Message-id: 20261020211529.99689-1-conti.manuele@gmail.com
[PMM: expanded comment slightly, added brackets for clarity]

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Manuele Conti authored and Peter Maydell committed 2026-10-23 10:01:16 +01:00
1 parent 9dadc6e121
commit 02e9aebb8e
1 file changed
+10 -2
+10 -2
View File
@@ -69,10 +69,12 @@ static void stm32f2xx_adc_reset(DeviceState *dev)
static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
{
unsigned resolution = (s->adc_cr1 & ADC_CR1_RES) >> 24;
/* Attempts to fake some ADC values */
s->adc_dr = s->adc_dr + 7;
switch ((s->adc_cr1 & ADC_CR1_RES) >> 24) {
switch (resolution) {
case 0:
/* 12-bit */
s->adc_dr &= 0xFFF;
@@ -91,7 +93,13 @@ static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
}
if (s->adc_cr2 & ADC_CR2_ALIGN) {
return (s->adc_dr << 1) & 0xFFF0;
/*
* Results are left-aligned within a half-word, except for
* 6-bit results, which are left aligned within a byte.
*/
unsigned shift = resolution == 3 ? 2 : (4 + 2 * resolution);
return s->adc_dr << shift;
} else {
return s->adc_dr;
}