Skip to content

Commit 23cf91a

Browse files
authored
Merge pull request #203 from TheZoq2/fix_adc_race_condition
Fix race condition causing ADCs to read stale values
2 parents 1cb9a17 + d871bf3 commit 23cf91a

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2727
### Fixed
2828

2929
- Fix PWM on `TIM1`
30+
- Fix ADC race condition causing incorrect reads at certain frequencies
3031

3132
## [v0.5.3] - 2020-01-20
3233

src/adc.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,34 @@ macro_rules! adc_hal {
349349
self.rb.sqr1.modify(|_, w| w.l().bits((len-1) as u8));
350350
}
351351

352+
/**
353+
Performs an ADC conversion
354+
355+
NOTE: Conversions can be started by writing a 1 to the ADON
356+
bit in the `CR2` while it is already 1, and no other bits
357+
are being written in the same operation. This means that
358+
the EOC bit *might* be set already when entering this function
359+
which can cause a read of stale values
360+
361+
The check for `cr2.swstart.bit_is_set` *should* fix it, but
362+
does not. Therefore, ensure you do not do any no-op modifications
363+
to `cr2` just before calling this function
364+
*/
352365
fn convert(&mut self, chan: u8) -> u16 {
353-
self.rb.cr2.modify(|_, w| w.align().bit(self.align.into()));
366+
// Dummy read in case something accidentally triggered
367+
// a conversion by writing to CR2 without changing any
368+
// of the bits
369+
self.rb.dr.read().data().bits();
370+
354371
self.set_channel_sample_time(chan, self.sample_time);
355372
self.rb.sqr3.modify(|_, w| unsafe { w.sq1().bits(chan) });
356373

357374
// ADC start conversion of regular sequence
358-
self.rb.cr2.modify(|_, w| w.swstart().set_bit());
375+
self.rb.cr2.modify(|_, w|
376+
w
377+
.swstart().set_bit()
378+
.align().bit(self.align.into())
379+
);
359380
while self.rb.cr2.read().swstart().bit_is_set() {}
360381
// ADC wait for conversion results
361382
while self.rb.sr.read().eoc().bit_is_clear() {}

0 commit comments

Comments
 (0)