stm32: Rework register access on stm32f0_adc.c
Avoid read-modify-write operations where possible. The register values are in a known state so prefer absolute writes. Improve handling of race conditions with hardware updates. Remove the adc reference from "struct gpio_adc" as it is a constant. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
20ac48f680
commit
88325b6c93
|
@ -38,38 +38,23 @@ gpio_adc_setup(uint32_t pin)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine which ADC block to use
|
|
||||||
ADC_TypeDef *adc = ADC1;
|
|
||||||
uint32_t adc_base = ADC1_BASE;
|
|
||||||
|
|
||||||
// Enable the ADC
|
// Enable the ADC
|
||||||
if (!is_enabled_pclock(adc_base)) {
|
if (!is_enabled_pclock(ADC1_BASE)) {
|
||||||
enable_pclock(adc_base);
|
enable_pclock(ADC1_BASE);
|
||||||
|
|
||||||
|
ADC_TypeDef *adc = ADC1;
|
||||||
// 100: 41.5 ADC clock cycles
|
// 100: 41.5 ADC clock cycles
|
||||||
adc->SMPR |= ~ADC_SMPR_SMP_Msk | ADC_SMPR_SMP_2;
|
adc->SMPR = 4 << ADC_SMPR_SMP_Pos;
|
||||||
adc->CFGR2 |= ADC_CFGR2_CKMODE;
|
|
||||||
adc->CFGR1 &= ~ADC_CFGR1_AUTOFF;
|
|
||||||
adc->CFGR1 |= ADC_CFGR1_EXTSEL;
|
|
||||||
|
|
||||||
// do not enable ADC before calibration
|
|
||||||
adc->CR &= ~ADC_CR_ADEN;
|
|
||||||
while (adc->CR & ADC_CR_ADEN)
|
|
||||||
;
|
|
||||||
while (adc->CFGR1 & ADC_CFGR1_DMAEN)
|
|
||||||
;
|
|
||||||
// start calibration and wait for completion
|
// start calibration and wait for completion
|
||||||
adc->CR |= ADC_CR_ADCAL;
|
adc->CR = ADC_CR_ADCAL;
|
||||||
while (adc->CR & ADC_CR_ADCAL)
|
while (adc->CR & ADC_CR_ADCAL)
|
||||||
;
|
;
|
||||||
|
|
||||||
// if not enabled
|
adc->ISR = ADC_ISR_ADRDY;
|
||||||
if (!(adc->CR & ADC_CR_ADEN)) {
|
adc->CR = ADC_CR_ADEN;
|
||||||
adc->ISR |= ADC_ISR_ADRDY;
|
while (!(adc->ISR & ADC_ISR_ADRDY))
|
||||||
adc->CR |= ADC_CR_ADEN;
|
;
|
||||||
while (!(ADC1->ISR & ADC_ISR_ADRDY))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pin == ADC_TEMPERATURE_PIN)
|
if (pin == ADC_TEMPERATURE_PIN)
|
||||||
|
@ -77,7 +62,7 @@ gpio_adc_setup(uint32_t pin)
|
||||||
else
|
else
|
||||||
gpio_peripheral(pin, GPIO_ANALOG, 0);
|
gpio_peripheral(pin, GPIO_ANALOG, 0);
|
||||||
|
|
||||||
return (struct gpio_adc){ .adc = adc, .chan = 1 << chan };
|
return (struct gpio_adc){ .chan = 1 << chan };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to sample a value. Returns zero if sample ready, otherwise
|
// Try to sample a value. Returns zero if sample ready, otherwise
|
||||||
|
@ -86,13 +71,16 @@ gpio_adc_setup(uint32_t pin)
|
||||||
uint32_t
|
uint32_t
|
||||||
gpio_adc_sample(struct gpio_adc g)
|
gpio_adc_sample(struct gpio_adc g)
|
||||||
{
|
{
|
||||||
ADC_TypeDef *adc = g.adc;
|
ADC_TypeDef *adc = ADC1;
|
||||||
if (adc->ISR & ADC_ISR_EOC && adc->CHSELR == g.chan)
|
|
||||||
return 0;
|
|
||||||
if (adc->CR & ADC_CR_ADSTART)
|
if (adc->CR & ADC_CR_ADSTART)
|
||||||
goto need_delay;
|
goto need_delay;
|
||||||
|
if (adc->ISR & ADC_ISR_EOC) {
|
||||||
|
if (adc->CHSELR == g.chan)
|
||||||
|
return 0;
|
||||||
|
goto need_delay;
|
||||||
|
}
|
||||||
adc->CHSELR = g.chan;
|
adc->CHSELR = g.chan;
|
||||||
adc->CR |= ADC_CR_ADSTART;
|
adc->CR = ADC_CR_ADSTART;
|
||||||
|
|
||||||
need_delay:
|
need_delay:
|
||||||
return timer_from_us(10);
|
return timer_from_us(10);
|
||||||
|
@ -102,8 +90,7 @@ need_delay:
|
||||||
uint16_t
|
uint16_t
|
||||||
gpio_adc_read(struct gpio_adc g)
|
gpio_adc_read(struct gpio_adc g)
|
||||||
{
|
{
|
||||||
ADC_TypeDef *adc = g.adc;
|
ADC_TypeDef *adc = ADC1;
|
||||||
adc->ISR &= ~ADC_ISR_EOSEQ;
|
|
||||||
return adc->DR;
|
return adc->DR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,9 +98,13 @@ gpio_adc_read(struct gpio_adc g)
|
||||||
void
|
void
|
||||||
gpio_adc_cancel_sample(struct gpio_adc g)
|
gpio_adc_cancel_sample(struct gpio_adc g)
|
||||||
{
|
{
|
||||||
ADC_TypeDef *adc = g.adc;
|
ADC_TypeDef *adc = ADC1;
|
||||||
irqstatus_t flag = irq_save();
|
irqstatus_t flag = irq_save();
|
||||||
if (!(adc->ISR & ADC_ISR_EOC) && adc->CHSELR == g.chan)
|
if (adc->CHSELR == g.chan) {
|
||||||
adc->CR |= ADC_CR_ADSTP;
|
if (adc->CR & ADC_CR_ADSTART)
|
||||||
|
adc->CR = ADC_CR_ADSTP;
|
||||||
|
if (adc->ISR & ADC_ISR_EOC)
|
||||||
|
gpio_adc_read(g);
|
||||||
|
}
|
||||||
irq_restore(flag);
|
irq_restore(flag);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue