Skip to content

Commit

Permalink
stm32h7: Fix race condition in ADC interrupt handling
Browse files Browse the repository at this point in the history
  • Loading branch information
antmerlino authored and xiaoxiang781216 committed Mar 25, 2024
1 parent a5b5c96 commit d808ed4
Showing 1 changed file with 18 additions and 12 deletions.
30 changes: 18 additions & 12 deletions arch/arm/src/stm32h7/stm32_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/****************************************************************************
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit d808ed4

Please sign in to comment.