-
Notifications
You must be signed in to change notification settings - Fork 217
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
SPI: Implement more SPI traits from embedded-hal 1.0.0-alpha.8 #101
Conversation
Hope you don't mind me documenting what I've done so far for myself. You can safely ignore this message. UpdateFixed the transfer performance. Previously the FIFO was filled and read from in copies of 4 bytes size each. Now instead we use a The implementation is broken since it only works when calling Consecutive transfers now take ~370 us, down from the previous ~2ms in debug builds. For release builds, transfer time dropped from 48 us to 14.12 us. Added an example that performs a big transfer of 256 bytes length. Edit: See bold text. |
Regarding those ~2ms .... is that for release or debug builds? |
@bjoernQ Debug builds, now that you mention it. Good point, I completely forgot about that... |
@bjoernQ Would you prefer to have a separate example to demo the SPI loopback with the |
Probably it's better to separate them since they should be as less confusing as possible. However, be careful regarding CI since eh1 is not a default feature (for reasons). Also, after a clean checkout |
@bjoernQ Understood. I made it a separate file now and wrapped |
Another - maybe easier and probably better - solution would be to add something like this to the cargo.toml:
This would prevent the example to be built if the required features are not activated. TBH I never tried this myself |
@bjoernQ I'm starting to think This works, and I added it to the PR now. Thanks for sharing! This leaves three TODOs from above, what's your opinion on these? |
Great! For the For the other things: @jessebraham what do you think? You are more into the EH1 things |
For the SpiDevice trait I have an open draft pull request. It's got a few things that need to be fixed but it is a working implementation |
Sorry I'm not going to be able to get to this for a day or two probably. Will take a look ASAP. |
Oh cool! Clever idea to split the SPI part into a separate But how exactly does the |
Given that |
It does have a permanent effect but I was just playing with reconnecting the cs pin to the GPIO peripheral after flushing the bus. I didn't get the chance to test it but I think that would fix the issue |
I wore the send bytes specifically because it doesn't read bytes after writing so a device that only needs to write doesn't spend time reading. But it is bad naming and quite a bit of duplication which was discussed in the PR |
Sorry for taking so long to get to this. Hopefully this helps, if you have any additional questions let me know.
No strong opinion here. I would choose
For the sake of pushing forward on this PR, maybe this could be done after in a subsequent PR? I'm frankly not super familiar with the newer traits (especially for
If everything is |
That's what I'm aiming for now anyway.
That's true of course, but the current code doesn't even impose a runtime check. Tbh I have no idea what happens on a write without a MOSI line attached, I guess it does nothing? I'll try to get the merge conflicts fixed, let me check what happened... |
bb9ca64
to
ca733d1
Compare
1b8385a
to
e6cb3e9
Compare
@jessebraham @bjoernQ CI passed, I have nothing more to add at this point. :) |
esp-hal-common/src/spi.rs
Outdated
where | ||
T: Instance, | ||
{ | ||
/// See also: [`send_bytes`]. |
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 guess this send_bytes comment can be removed/renamed
Thanks for the PR! Just testing this out, seems like the s2 & s3 examples don't work... probably not this PR because I can't get the normal loopback example to work on these chips, @bjoernQ, @jessebraham is this the case for you too? |
Also for me the normal loopback example doesn't work on S2 and S3 anymore on this branch while they do work fine on |
That's interesting... I only have the regular esp32 here, but I just double-checked: Both the regular loopback example and the one for embedded-hal 1 work fine. I also didn't touch the regular loopback example, only the HAL it's using. Going through the changes I don't see what may break here... |
Found an oversight while working on some other SPI-related code. From the commit message:
Tested the examples again here on my PC, they still work. |
as counterpart to `send_bytes` that is responsible only for reading bytes received via SPI.
to use `send_bytes` and `read_bytes` under the hood and remove duplicate code.
that is re-exported when the `eh1` feature flag is active. This removes lots of duplicate `#[cfg(...)]` macros previously part of the code.
traits from the `embedded-hal 1.0.0-alpha.8`.
and bump the SPI speed to 1 MHz.
This cuts down the time between consecutive transfers from about 2 ms to less than 1 ms.
cutting down the time between transfers from just below 1 ms to ~370 us. The implementation is currently broken in that it will always fill the entire FIFO from the input it is given, even if that isn't FIFO-sized...
and compile a dummy instead when the "eh1" feature isn't present.
in normal builds, where the feature flag "eh1" isn't given. Building the example directly via `cargo build --example spi_eh1_loopback` will now print an error that this requires a feature flag to be active.
and drop `send_bytes` instead. Previoulsy, both served the same purpose, but `send_bytes` was introduced more recently and is hence less likely to cause breaking changes in existing code.
to all targets.
The previous `read` implementation would only read the contents of the SPI receive FIFO and return that as data. However, the `SpiBusRead` trait defines that while reading, bytes should be written out to the bus (Because SPI is transactional, without writing nothing can be read). Reimplements the `embedded-hal` traits to correctly implement this behavior.
All esp variants except for the esp32s2 have a 64 byte FIFO, whereas the esp32s2 has a 72 byte FIFO.
by reverting to the old method of reading 32 bytes at a time and assembling the return buffer from that. It turns out that the previous `core::slice::from_raw_parts()` doesn't work for the esp32s2 and esp32s3 variants, returning bogus data even though the correct data is present in the registers.
140dedf
to
1938c90
Compare
Sort of lost track of these, heh...
Correct, should be fixed now! |
Looks good to me and the examples work fine 👍 |
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 the PR @har7an!
Hi,
as the title suggests, this PR implements the
SpiBusWrite
andSpiBus
traits from the latestembedded-hal
alpha release as documented here.I'm putting this up here in case someone is interested in having a preliminary look. Things that I'd still like to implement:
Currently we have
send_bytes
andwrite_bytes
, both doing the same thing really, what should I do with that?SpiDevice
trait so we can share theSpiBus
when we want toIdeally this goes in tandem with some sort of marker trait that prohibits creating a
SpiDevice
from aSpiBus
that has aCS
pin associated? Or maybe we make theSpiDevice
the default and drop theCS
from the bus entirely?While the code is in fact infallible (apart from the
unsafe
parts of course), I think it would be nice to have e.g. aReadOnly
andWriteOnly
that is returned when writing withoutmosi
and reading withoutmiso
, respectively. I guess these could be enforced at compile time with more types and abstractions, but tbh these abstractions make me all fuzzy in the head... Or should we keep the current behavior where nothing happens?SpiBus::transfer
with buffers much bigger than the 64 bytes SPI FIFOtransfer_in_place
(currently broken)I only have an ESP32 here for testing, so I'm looking forward to get some feedback from anyone who cares to test this on other ESP32 boards/chips. I have implemented a new test
esp32-hal/examples/spi_eh1_loopback.rs
that performs a very simple demo as of currently.