-
Notifications
You must be signed in to change notification settings - Fork 62
Poll for completion on SPI write. #131
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
Conversation
For this to work |
We can also combine the current current and the |
Upon looking at the code again the final The STM provided HAL (in C) does clear the OVR flag when operating in write-only mode, but the procedure to clear that flag requires reading DR, then reading SR.
Along the lines of this? fn check_send(&mut self) -> nb::Result<(), Error> {
let sr = self.spi.sr.read();
Err(if sr.ovr().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if sr.modf().bit_is_set() {
nb::Error::Other(Error::ModeFault)
} else if sr.crcerr().bit_is_set() {
nb::Error::Other(Error::Crc)
} else if sr.txe().bit_is_set() && sr.bsy().bit_is_clear() {
return Ok(());
} else {
nb::Error::WouldBlock
})
} |
Yes, something like that might work. I'm actually not sure which other conditions would be reason to use |
@newAM Ping? |
Sorry for the delay, got distracted with other projects 😅 I made the modification - both the first and second implementations fix the issues mentioned (
I am not sure of the other conditions either, which makes me hesitant to change the existing implementation too much. It does feel like this could be optimized better, but I have not spent enough time with this hardware to be confident about that. |
@@ -482,7 +482,7 @@ where | |||
} | |||
|
|||
// Do one last status register check before continuing | |||
self.check_send().ok(); | |||
nb::block!(self.check_send()).ok(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still .ok()
rather than returning the result?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left it as ok()
because that better preserves the previously existing behavior.
...as for whether or not it should be ok()
or ?
that is debatable. What do you think?
I think the previous intent was to clear the overrun flag if it was set, but that requires a read to DR followed by a read access to SR to clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that before it had no tangible effect (since it didn't read from DR) and now it blocks but still does not affect the flags. It seems a bit strange if we were to call this function and identify a failure but not report it -- then again, if it didn't prevent transmission, perhaps it's best to ignore it. It may just depend on the error.
All in all, I don't really have an influencing perspective here since I'll be cherry-picking and tacking on my own changes in my project's fork (I need the non-blocking behavior in some cases). The .ok()
pattern to ignore an error seems strange to me since it looks more like a mistake, but if this is the behavior that works, I can't say much against it!
Thanks for fixing this! 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for bearing with me.
bors r+
Thanks for bearing with me as well 👍 Happy to help! |
Build succeeded: |
Closes #130
Continuing discussion from #130 :
The suggested implementation was replacing this:
With this:
The concern I have with that is it seems the last
check_send().ok()
was intended to clear theOVR
error bit that may be set due to dropped reads.Additionally, it does not seem that this works as intended, the CS still goes high before the write is completed with consecutive write calls.