-
Notifications
You must be signed in to change notification settings - Fork 60
SPI blocking transfers do not wait for completion. #130
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
Comments
stm32f1xx-hal implementation: https://github.com/stm32-rs/stm32f1xx-hal/blob/master/src/spi.rs#L492 The difference does appear to be that the Back to this crate, what is the purpose of this line here? As far as I know reads to |
Comparing two different generations of a peripheral (or software implementations) is typically not too useful. I guess the problem here is that you're assuming that the transfer is completed by the time the send call returns but it actually is buffered. Maybe we should add a busy check before changing the mode to bidi. Reading
|
Is this a bad assumption to make? I asked in the Rust Embedded element chat and the consensus seemed to agree that the implementation of the traits should block for completion. |
Well, depends on what the goal is. If you want best possible write performance without complicated implementations (i.e. DMA) it makes total sense to use the built-in buffer. I'm not quite sure what happened in your first example since the trace doesn't quite seem to line up with the code, there could be other issues with a software NSS implementation, too. |
I took a look through the awesome embedded list, I could not find a device driver where they made the assumption that the For example, the ENC28J60 crate will not work with the fn read_buffer_memory(&mut self, addr: Option<u16>, buf: &mut [u8]) -> Result<(), E> {
if let Some(addr) = addr {
self.write_control_register(bank0::Register::ERDPTL, addr.low())?;
self.write_control_register(bank0::Register::ERDPTH, addr.high())?;
}
self.ncs.set_low();
self.spi.write(&[Instruction::RBM.opcode()])?;
self.spi.transfer(buf)?;
self.ncs.set_high();
Ok(())
}
I am not sure I understand what you mean here. The trace not lining up is the issue, specifically the fact that CS goes high before the transfer is complete is unexpected. The rest of the trace looks correct to me.
Any ideas? I am happy to investigate further! |
? How would you see such a thing? If you have a write-only driver there's no problem at all (and those are quite common, e.g. for displays).
Is that an assumption or did you verify that? I appreciate that the pattern you're using might be a problem in general but it would be nice to have some hard evidence. And again, I think the problem might actually be the turn-around from
I understand that but I am puzzled about how little data seems to be transferred before the loss of sync... what's the SPI clock?
Yeah, but again that that's a completely different generation of SPI peripheral which means you can't just assume that using the F1 mechanisms would just work for F0, too. It would be great if you could insert a busy check loop in |
I made the assumption (perhaps a bad one, sorry!) that any crate using the blocking
I tried it out, and it appears that even for write only this is still a problem. cs.set_low().unwrap();
spi.write(&[0x12, 0x34, 0x56, 0x78]);
cs.set_high().unwrap(); That code (or similar) also produces a clipped chip-select. Full code here: https://github.com/newAM/stm32f0xx-hal-issue-130/blob/example1/src/main.rs#L70
It was a problem I had a while ago, but I did not dive into it at the time. Here is a reproduction: https://github.com/newAM/stm32f0xx-hal-issue-130
10kHz, though this can be reproduced at higher frequencies.
The point I am trying to make is that there is a gap in behavior between the F0 and F1 that should not exist. Polling the
Happy to help debug this! 👍 I tried it out, and the problem still exists :( This is the same as above, just a bare write, since that is a better minimal reproduction. stm32f0xx-hal: https://github.com/newAM/stm32f0xx-hal/tree/issue-130 Edit: I should also mention that all of the above was done with a Nucleo F070RB (original post was with a |
Well, yes. The problem is the data is still in the hardware buffer when the call returns which isn't a problem if one uses hardware CS or
10kHz explains a lot.
Okay, let's poll the |
500kHz is not reasonably fast, SPI was meant for multi-MHz operation. 😅 Please go ahead to PR a change. Probably the easiest and most sensible and correct change would be to replace Lines 485 to 486 in fa3f2c2
by
|
Just throwing this out there... As far as I can tell, the current implementation has a race condition if you invoke This should be resolved by the discussed fixes in #131. I've validated that it avoids the overruns I encountered in my case. In theory, fixing this requires the new "busy" check that was proposed; that being said, the FIFO only takes a few extra cycles to clear, so even just doing the reads to check if there is space in the TX buffer is enough. Not that I'm fond of that 🙂 |
Yes, that it is correct and mentioned before. This needs to be fixed.
You're assuming people would run SPI at high speeds. Something that doesn't necessarily seem to be true as I've learned by this issue. 😅 |
I do it for ease of debug with my low end equipment. 😀 |
Problem
When doing a SPI transfer with the blocking traits the CS line goes high before the transfer is completed.
Expected Behavior
When I add some hacky polling for the
BSY
bit (0x80
) in the SPI status register to that code, the transfer works as expected, with the CS line going high only after completion of the SPI bus activity.This seems to be a case of under-specified behavior in the embedded-hal (which is fixed in 1.0.0), the docs do not specify if the
blocking
part is just blocking for buffer space, after which the function returns, or blocking for buffer space, and polling for completion.I think this is a bug though, because despite the under-specification other STM32 embedded HAL traits do block for completion (such as the stm32f1 which I also tested), this appears to be the odd one out.
Other Information
I am using a STM32F070CBTx.
Relevant
Cargo.toml
:The text was updated successfully, but these errors were encountered: