stm32h7: Fix race condition in ADC interrupt handling
This commit is contained in:
parent
a5b5c963c7
commit
d808ed450c
@ -1253,6 +1253,8 @@ static void adc_enable(struct stm32_dev_s *priv)
|
|||||||
/* Wait for hardware to be ready for conversions */
|
/* Wait for hardware to be ready for conversions */
|
||||||
|
|
||||||
while (!(adc_getreg(priv, STM32_ADC_ISR_OFFSET) & ADC_INT_ADRDY));
|
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 */
|
/* Stop ADC conversions to avoid continuous interrupts */
|
||||||
|
|
||||||
adc_startconv(priv, false);
|
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 */
|
/* OVR: Overrun */
|
||||||
@ -2037,6 +2046,11 @@ static int adc_interrupt(struct adc_dev_s *dev, uint32_t adcisr)
|
|||||||
priv->cb->au_reset(dev);
|
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);
|
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);
|
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;
|
return OK;
|
||||||
@ -2120,10 +2138,6 @@ static int adc12_interrupt(int irq, void *context, void *arg)
|
|||||||
if (pending != 0)
|
if (pending != 0)
|
||||||
{
|
{
|
||||||
adc_interrupt(&g_adcdev1, regval);
|
adc_interrupt(&g_adcdev1, regval);
|
||||||
|
|
||||||
/* Clear interrupts */
|
|
||||||
|
|
||||||
putreg32(regval, STM32_ADC1_ISR);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2133,10 +2147,6 @@ static int adc12_interrupt(int irq, void *context, void *arg)
|
|||||||
if (pending != 0)
|
if (pending != 0)
|
||||||
{
|
{
|
||||||
adc_interrupt(&g_adcdev2, regval);
|
adc_interrupt(&g_adcdev2, regval);
|
||||||
|
|
||||||
/* Clear interrupts */
|
|
||||||
|
|
||||||
putreg32(regval, STM32_ADC2_ISR);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2167,10 +2177,6 @@ static int adc3_interrupt(int irq, void *context, void *arg)
|
|||||||
if (pending != 0)
|
if (pending != 0)
|
||||||
{
|
{
|
||||||
adc_interrupt(&g_adcdev3, regval);
|
adc_interrupt(&g_adcdev3, regval);
|
||||||
|
|
||||||
/* Clear interrupts */
|
|
||||||
|
|
||||||
putreg32(regval, STM32_ADC3_ISR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user