stm32h7: Fix race condition in ADC interrupt handling

This commit is contained in:
Anthony Merlino 2024-03-23 18:33:53 +00:00 committed by Xiang Xiao
parent a5b5c963c7
commit d808ed450c

View File

@ -1253,6 +1253,8 @@ static void adc_enable(struct stm32_dev_s *priv)
/* Wait for hardware to be ready for conversions */
while (!(adc_getreg(priv, STM32_ADC_ISR_OFFSET) & ADC_INT_ADRDY));
adc_modifyreg(priv, STM32_ADC_ISR_OFFSET, 0, ADC_INT_ADRDY);
}
/****************************************************************************
@ -2008,6 +2010,13 @@ static int adc_interrupt(struct adc_dev_s *dev, uint32_t adcisr)
/* Stop ADC conversions to avoid continuous interrupts */
adc_startconv(priv, false);
/* Clear the interrupt. This register only accepts write 1's so its
* safe to only set the 1 bit without regard for the rest of the
* register
*/
adc_putreg(priv, STM32_ADC_ISR_OFFSET, ADC_INT_AWD1);
}
/* OVR: Overrun */
@ -2037,6 +2046,11 @@ static int adc_interrupt(struct adc_dev_s *dev, uint32_t adcisr)
priv->cb->au_reset(dev);
}
/* Clear the interrupt. This register only accepts write 1's so its
* safe to only set the 1 bit without regard for the rest of the
* register
*/
adc_putreg(priv, STM32_ADC_ISR_OFFSET, ADC_INT_OVR);
}
@ -2091,6 +2105,10 @@ static int adc_interrupt(struct adc_dev_s *dev, uint32_t adcisr)
}
}
while ((adc_getreg(priv, STM32_ADC_ISR_OFFSET) & ADC_INT_EOC) != 0);
/* We dont't add EOC to the bits to clear. It will cause a race
* condition. EOC should only be cleared by reading the ADC_DR
*/
}
return OK;
@ -2120,10 +2138,6 @@ static int adc12_interrupt(int irq, void *context, void *arg)
if (pending != 0)
{
adc_interrupt(&g_adcdev1, regval);
/* Clear interrupts */
putreg32(regval, STM32_ADC1_ISR);
}
#endif
@ -2133,10 +2147,6 @@ static int adc12_interrupt(int irq, void *context, void *arg)
if (pending != 0)
{
adc_interrupt(&g_adcdev2, regval);
/* Clear interrupts */
putreg32(regval, STM32_ADC2_ISR);
}
#endif
@ -2167,10 +2177,6 @@ static int adc3_interrupt(int irq, void *context, void *arg)
if (pending != 0)
{
adc_interrupt(&g_adcdev3, regval);
/* Clear interrupts */
putreg32(regval, STM32_ADC3_ISR);
}
return OK;