Skip to content

Commit 04d3da7

Browse files
committed
adc: iio: hardware: only finish ADC setup once first values are available
Under some circumstances it can happen that all steps of the ADC setup succeed but reading the first set of values fails. Currently this special case results in the thread waiting for the values busy-looping forever. Delay signaling "setup ready" until we avtually have a first reading. Signed-off-by: Leonard Göhrs <l.goehrs@pengutronix.de>
1 parent b5d62c3 commit 04d3da7

File tree

1 file changed

+52
-34
lines changed

1 file changed

+52
-34
lines changed

src/adc/iio/hardware.rs

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ use std::thread;
2323
use std::thread::JoinHandle;
2424
use std::time::{Duration, Instant};
2525

26-
use anyhow::{anyhow, Context, Result};
26+
use anyhow::{anyhow, Context, Error, Result};
2727
use async_std::channel::bounded;
2828
use async_std::stream::StreamExt;
2929
use async_std::sync::Arc;
3030

3131
use industrial_io::{Buffer, Channel};
3232

33-
use log::{debug, warn};
33+
use log::{debug, error, warn};
3434
use thread_priority::*;
3535

3636
use crate::measurement::{Measurement, Timestamp};
@@ -310,44 +310,56 @@ impl IioThread {
310310
let join = thread::Builder::new()
311311
.name("tacd iio".into())
312312
.spawn(move || {
313-
let (thread_weak, stm32_channels, mut stm32_buf, pwr_channels) =
314-
match Self::adc_setup() {
315-
Ok((stm32_channels, stm32_buf, pwr_channels)) => {
316-
let thread = Arc::new(Self {
317-
ref_instant: Instant::now(),
318-
timestamp: AtomicU64::new(0),
319-
values: [
320-
AtomicU16::new(0),
321-
AtomicU16::new(0),
322-
AtomicU16::new(0),
323-
AtomicU16::new(0),
324-
AtomicU16::new(0),
325-
AtomicU16::new(0),
326-
AtomicU16::new(0),
327-
AtomicU16::new(0),
328-
AtomicU16::new(0),
329-
AtomicU16::new(0),
330-
],
331-
join: Mutex::new(None),
332-
});
333-
let thread_weak = Arc::downgrade(&thread);
334-
335-
thread_res_tx.try_send(Ok(thread)).unwrap();
336-
337-
(thread_weak, stm32_channels, stm32_buf, pwr_channels)
338-
}
339-
Err(e) => {
340-
thread_res_tx.try_send(Err(e)).unwrap();
341-
panic!()
342-
}
343-
};
313+
let (thread, stm32_channels, mut stm32_buf, pwr_channels) = match Self::adc_setup()
314+
{
315+
Ok((stm32_channels, stm32_buf, pwr_channels)) => {
316+
let thread = Arc::new(Self {
317+
ref_instant: Instant::now(),
318+
timestamp: AtomicU64::new(0),
319+
values: [
320+
AtomicU16::new(0),
321+
AtomicU16::new(0),
322+
AtomicU16::new(0),
323+
AtomicU16::new(0),
324+
AtomicU16::new(0),
325+
AtomicU16::new(0),
326+
AtomicU16::new(0),
327+
AtomicU16::new(0),
328+
AtomicU16::new(0),
329+
AtomicU16::new(0),
330+
],
331+
join: Mutex::new(None),
332+
});
333+
334+
(thread, stm32_channels, stm32_buf, pwr_channels)
335+
}
336+
Err(e) => {
337+
thread_res_tx.try_send(Err(e)).unwrap();
338+
panic!()
339+
}
340+
};
341+
342+
let thread_weak = Arc::downgrade(&thread);
343+
let mut signal_ready = Some((thread, thread_res_tx));
344344

345345
// Stop running as soon as the last reference to this Arc<IioThread>
346346
// is dropped (e.g. the weak reference can no longer be upgraded).
347347
while let Some(thread) = thread_weak.upgrade() {
348348
// Use the buffer interface to get STM32 ADC values at a high
349349
// sampling rate to perform averaging in software.
350-
stm32_buf.refill().unwrap();
350+
if let Err(e) = stm32_buf.refill() {
351+
error!("Failed to refill STM32 ADC buffer: {}", e);
352+
353+
// If the ADC has not yet produced any values we still have the
354+
// queue at hand that signals readiness to the main thread.
355+
// This gives us a chance to return an Err from new().
356+
// If the queue was already used just print an error instead.
357+
if let Some((_, tx)) = signal_ready.take() {
358+
tx.try_send(Err(Error::new(e))).unwrap();
359+
}
360+
361+
break;
362+
}
351363

352364
let stm32_values = stm32_channels.iter().map(|ch| {
353365
let buf_sum: u32 =
@@ -377,6 +389,12 @@ impl IioThread {
377389
.unwrap();
378390

379391
thread.timestamp.store(ts, Ordering::Release);
392+
393+
// Now that we know that the ADC actually works and we have
394+
// initial values: return a handle to it.
395+
if let Some((content, tx)) = signal_ready.take() {
396+
tx.try_send(Ok(content)).unwrap();
397+
}
380398
}
381399
})?;
382400

0 commit comments

Comments
 (0)