timestamp: pass overflows to the top and ignore them there

This commit is contained in:
Robert Jördens 2021-02-02 12:34:07 +01:00
parent 4475a2d040
commit 854ed29b1a
3 changed files with 20 additions and 19 deletions

View File

@ -117,8 +117,14 @@ const APP: () = {
let iir_state = c.resources.iir_state; let iir_state = c.resources.iir_state;
let lockin = c.resources.lockin; let lockin = c.resources.lockin;
let t = c
.resources
.timestamper
.latest_timestamp()
.unwrap_or_else(|t| t) // Ignore timer capture overflows.
.map(|t| t as i32);
let (pll_phase, pll_frequency) = c.resources.pll.update( let (pll_phase, pll_frequency) = c.resources.pll.update(
c.resources.timestamper.latest_timestamp().map(|t| t as i32), t,
22, // frequency settling time (log2 counter cycles), TODO: expose 22, // frequency settling time (log2 counter cycles), TODO: expose
22, // phase settling time, TODO: expose 22, // phase settling time, TODO: expose
); );

View File

@ -62,15 +62,12 @@ impl InputStamper {
/// Get the latest timestamp that has occurred. /// Get the latest timestamp that has occurred.
/// ///
/// # Note /// # Note
/// This function must be called sufficiently often. If an over-capture event occurs, this /// This function must be called at least as often as timestamps arrive.
/// function will panic, as this indicates a timestamp was inadvertently dropped. /// If an over-capture event occurs, this function will clear the overflow,
/// /// and return a new timestamp of unknown recency an `Err()`.
/// To prevent timestamp loss, the batch size and sampling rate must be adjusted such that at /// Note that this indicates at least one timestamp was inadvertently dropped.
/// most one timestamp will occur in each data processing cycle.
#[allow(dead_code)] #[allow(dead_code)]
pub fn latest_timestamp(&mut self) -> Option<u32> { pub fn latest_timestamp(&mut self) -> Result<Option<u32>, Option<u32>> {
self.capture_channel self.capture_channel.latest_capture()
.latest_capture()
.expect("DI0 timestamp overrun")
} }
} }

View File

@ -281,28 +281,26 @@ macro_rules! timer_channels {
impl [< Channel $index InputCapture >] { impl [< Channel $index InputCapture >] {
/// Get the latest capture from the channel. /// Get the latest capture from the channel.
#[allow(dead_code)] #[allow(dead_code)]
pub fn latest_capture(&mut self) -> Result<Option<$size>, ()> { pub fn latest_capture(&mut self) -> Result<Option<$size>, Option<$size>> {
// Note(unsafe): This channel owns all access to the specific timer channel. // Note(unsafe): This channel owns all access to the specific timer channel.
// Only atomic operations on completed on the timer registers. // Only atomic operations on completed on the timer registers.
let regs = unsafe { &*<$TY>::ptr() }; let regs = unsafe { &*<$TY>::ptr() };
let sr = regs.sr.read();
let result = if sr.[< cc $index if >]().bit_is_set() { let result = if regs.sr.read().[< cc $index if >]().bit_is_set() {
// Read the capture value. Reading the captured value clears the flag in the // Read the capture value. Reading the captured value clears the flag in the
// status register automatically. // status register automatically.
let ccx = regs.[< ccr $index >].read(); Some(regs.[< ccr $index >].read().ccr().bits())
Some(ccx.ccr().bits())
} else { } else {
None None
}; };
// Read SR again to check for a potential over-capture. If there is an // Read SR again to check for a potential over-capture. If there is an
// overcapture, return an error. // overcapture, return an error.
if regs.sr.read().[< cc $index of >]().bit_is_clear() { if regs.sr.read().[< cc $index of >]().bit_is_set() {
Ok(result)
} else {
regs.sr.modify(|_, w| w.[< cc $index of >]().clear_bit()); regs.sr.modify(|_, w| w.[< cc $index of >]().clear_bit());
Err(()) Err(result)
} else {
Ok(result)
} }
} }