Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix improper reporting of DMA overruns when remaining bytes is outside the expected range #126

Closed
wants to merge 2 commits into from

Conversation

electroCutie
Copy link
Contributor

I've witnessed zeros as well as values larger than the initial setting,
albeit spuriously. Added a saturating subtraction and a modulo to the
position calculation and overrun now seems to be working correctly

There still seems to be more overruns than should strictly be happening,
but I've been unable to pin them down and they disappear when clocking
low enough. They might even be real but it is difficult to know. But
this fix is solid

Fix for #125

…e the expected range

I've witnessed zeros as well as values larger than the initial setting,
albeit spuriously. Added a saturating subtraction and a modulo to the
position calculation and overrun now seems to be working correctly

There still seems to be more overruns than should strictly be happening,
but I've been unable to pin them down and they disappear when clocking
low enough. They might even be real but it is difficult to know. But
this fix is solid
src/adc.rs Outdated
@@ -482,7 +482,7 @@ impl Buffer {

// Let's translate what we got from the DMA peripheral into a write
// position that we can compare with our read position.
let pos = self.len - remaining;
let pos = self.len.saturating_sub(remaining) % self.len;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what's happening here. First off, it's very weird that the hardware reports values for remaining that are too large, but okay, hardware is often quite weird :-)

Still, it's not clear to me what should happen in that case. The saturating sub will prevent an underflow, which is good, but are we certain that it will lead to correct behavior? Maybe there's an errata note somewhere that can shed some light on the hardware behavior.

I also don't understand what the modulo is doing. Will self.len.saturating_sub(remaining) not always result in a value that's smaller or equal to self.len? In that case the % self.len won't do anything, or am I missing something obvious?

@hannobraun
Copy link
Contributor

Thank you, @electroCutie. I've left a comment in your commit. Some additional notes:

  • There are known problems with ADC/DMA that might account for the overruns you're seeing. See Faulty DMA Buffer Overflow in adc_trig example #104 and New ADC DMA implementation #105.
  • I think it's better to move some of the explanation from your commit message into the code, as a comment. When wondering why something looks like it does, it's always nicer to have a comment right there, instead of having to hunt for the right commit message.

…ting subtract

I can't get it to do load an erroneous value into the DNR register
anymore, so I will chaulk that one up to potential operator error unless
it manifests again and I get a solid repro
let pos = self.len.saturating_sub(remaining) % self.len;
// Zero can be witnessed in remaining before the DMA reloads
// the register so we wrap the result of the subtraction around
let pos = (self.len - remaining) % self.len;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so the thing I missed before is that if remaining is zero, the % self.len will result in pos = 0 instead of pos = self.len. Makes sense.

What I don't understand yet is the wider context of this change. Under which circumstances will remaining == 0 actually cause an overrun, and why? How will this affect overrun detection?

I'm not saying this is wrong, but I'm also not convinced of the following things:

  • That this is correct, given the complexity of the surrounding code.
  • That the overruns you're seeing are actually caused by remaining == 0, given the known issue with ADC/DMA.
  • If you're experiencing overruns not caused by Faulty DMA Buffer Overflow in adc_trig example #104, that this is the right place to fix them. Maybe it should be fixed in the overrun detection code, for example.

This code is quite complex, and we're really suffering from the lack of a test suite here. I think the best way to get this merged is to do a more thorough analysis and write up the results in a comment in the appropriate place. As it is, I don't understand this fix (and its underlying problem) well enough to merge it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I'll do that. I thought I had a good handle on it but I will review #104 and see if I can really pin this down

I think I misunderstood the bug but now looking at #104 I think this is a duplicate of that bug. Lets close this merge and my version of the bug and i'll focus my efforts there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

Please note that my latest conclusion was, that this API can't be supported given the hardware behavior (#104 (comment)), and I currently favor just adopting @apgoetz's new API to replace this one (#105 (review)).

But if you can come up with a fix for the current API, that would of course be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants