stm32: Apply race fixes to stm32h7_adc.c
Improve handling of race conditions with hardware updates. This is
the same changes applied to stm32f0_adc.c in commit 88325b6c
.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
201f715b55
commit
69f76b3b66
|
@ -28,7 +28,6 @@
|
||||||
// Number of samples is 2^OVERSAMPLES_EXPONENT (exponent can be 0-10)
|
// Number of samples is 2^OVERSAMPLES_EXPONENT (exponent can be 0-10)
|
||||||
#define OVERSAMPLES_EXPONENT 3
|
#define OVERSAMPLES_EXPONENT 3
|
||||||
#define OVERSAMPLES (1 << OVERSAMPLES_EXPONENT)
|
#define OVERSAMPLES (1 << OVERSAMPLES_EXPONENT)
|
||||||
#define ADC_MEAS_DELAY (1 + 2.3666*OVERSAMPLES)
|
|
||||||
|
|
||||||
// LDORDY registers are missing from CMSIS (only available on revision V!)
|
// LDORDY registers are missing from CMSIS (only available on revision V!)
|
||||||
#define ADC_ISR_LDORDY_Pos (12U)
|
#define ADC_ISR_LDORDY_Pos (12U)
|
||||||
|
@ -44,7 +43,6 @@
|
||||||
#define ADC_TS (ADC12_COMMON)
|
#define ADC_TS (ADC12_COMMON)
|
||||||
|
|
||||||
#define OVERSAMPLES (0)
|
#define OVERSAMPLES (0)
|
||||||
#define ADC_MEAS_DELAY (10)
|
|
||||||
|
|
||||||
#elif CONFIG_MACH_STM32G4
|
#elif CONFIG_MACH_STM32G4
|
||||||
#define ADCIN_BANK_SIZE (19)
|
#define ADCIN_BANK_SIZE (19)
|
||||||
|
@ -57,7 +55,6 @@
|
||||||
#define ADC_CCR_TSEN (ADC_CCR_VSENSESEL)
|
#define ADC_CCR_TSEN (ADC_CCR_VSENSESEL)
|
||||||
|
|
||||||
#define OVERSAMPLES (0)
|
#define OVERSAMPLES (0)
|
||||||
#define ADC_MEAS_DELAY (10)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ADC_TEMPERATURE_PIN 0xfe
|
#define ADC_TEMPERATURE_PIN 0xfe
|
||||||
|
@ -361,20 +358,19 @@ uint32_t
|
||||||
gpio_adc_sample(struct gpio_adc g)
|
gpio_adc_sample(struct gpio_adc g)
|
||||||
{
|
{
|
||||||
ADC_TypeDef *adc = g.adc;
|
ADC_TypeDef *adc = g.adc;
|
||||||
// Conversion ready
|
uint32_t cr = adc->CR;
|
||||||
// EOC flag is cleared by hardware when reading DR
|
if (cr & ADC_CR_ADSTART)
|
||||||
// the channel condition only works if this ist the only channel
|
goto need_delay;
|
||||||
// on the sequence and length set to 1 (ADC_SQR1_L = 0000)
|
if (adc->ISR & ADC_ISR_EOC) {
|
||||||
if (adc->ISR & ADC_ISR_EOC && adc->SQR1 == (g.chan << ADC_SQR1_SQ1_Pos))
|
if (adc->SQR1 == (g.chan << ADC_SQR1_SQ1_Pos))
|
||||||
return 0;
|
return 0;
|
||||||
// Conversion started but not ready or wrong channel
|
goto need_delay;
|
||||||
if (adc->CR & ADC_CR_ADSTART)
|
}
|
||||||
return timer_from_us(10);
|
|
||||||
// Start sample
|
// Start sample
|
||||||
adc->SQR1 = (g.chan << ADC_SQR1_SQ1_Pos);
|
adc->SQR1 = (g.chan << ADC_SQR1_SQ1_Pos);
|
||||||
adc->CR |= ADC_CR_ADSTART;
|
adc->CR = cr | ADC_CR_ADSTART;
|
||||||
// Should take 2.3666us, add 1us for clock synchronisation etc.
|
need_delay:
|
||||||
return timer_from_us(ADC_MEAS_DELAY);
|
return timer_from_us(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a value; use only after gpio_adc_sample() returns zero
|
// Read a value; use only after gpio_adc_sample() returns zero
|
||||||
|
@ -391,9 +387,12 @@ gpio_adc_cancel_sample(struct gpio_adc g)
|
||||||
{
|
{
|
||||||
ADC_TypeDef *adc = g.adc;
|
ADC_TypeDef *adc = g.adc;
|
||||||
irqstatus_t flag = irq_save();
|
irqstatus_t flag = irq_save();
|
||||||
// ADSTART is not as long true as SR_STRT on stm32f4
|
if (adc->SQR1 == (g.chan << ADC_SQR1_SQ1_Pos)) {
|
||||||
if ((adc->CR & ADC_CR_ADSTART || adc->ISR & ADC_ISR_EOC)
|
uint32_t cr = adc->CR;
|
||||||
&& adc->SQR1 == (g.chan << ADC_SQR1_SQ1_Pos))
|
if (cr & ADC_CR_ADSTART)
|
||||||
gpio_adc_read(g);
|
adc->CR = (cr & ~ADC_CR_ADSTART) | ADC_CR_ADSTP;
|
||||||
|
if (adc->ISR & ADC_ISR_EOC)
|
||||||
|
gpio_adc_read(g);
|
||||||
|
}
|
||||||
irq_restore(flag);
|
irq_restore(flag);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue