-
Notifications
You must be signed in to change notification settings - Fork 46
SPI implementation doesn't follow embedded-hal requirements for CS #87
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
huh, yeah bus sharing with linux drivers / other applications is certainly an interesting problem, for now i think the recommendation is probably don't do this :-/ for unshared use i would just set -edit-: it looks like spidev has a |
How do you drive CS manually if that flag is set? Even if we don't worry about sharing with other applications, just having the SpiBus methods not change CS and instead driving it inside SpiDevice::transaction would be a big improvement. |
ahh, i have always just used a separate GPIO (or patched the device tree to disable CS1, never succeeded with CS0) and driven it as a normal digital pin. it does seem like there should be an API for CS assert/deassert tho. |
We've been discussing this on and off at the weekly meetings, currently the hope is that we can get away without changing the SPI traits but probably documenting where edge cases and constraints exist. For example, in embedded-hal we may document that some implementations will require a transaction contains only 0+ writes followed by 0-1 reads, and that anything else (e.g. write-read-write) will error, and therefore suggest drivers aiming for maximum compatibility follow that suggestion. On the Linux side the hope is we can do something like...
I don't have much experience with embedded Linux, does this sound at all sensible? |
Let's keep this open until we actually fix this issue here. |
Had an issue moving to new raspbian kernel. /boot/config.txt: on my rust lib i'm using something like:
on new 6.1 kernel, it doesn't work.
|
@adamgreig this approach seems pretty reasonable to me... on linux we build the transaction buffers anyway so checking they work is not big, just need to make sure we guide folks to the right approach for their application. IMO it's an oversight that there's not an ioctl to assert HW CS / grab process-exclusive access to the device so this kind of unsoundness can be mitigated, but, trying to implement that upstream in spidev is pretty low on my list...
@RaulTrombin if you want to use software CS you have to disconnect these from the kernel. as you've discovered i've spent some time in the past trying to generate an overlay without the CS0 pin allocated without success, either because i'm missing something or there's a fundamental requirement to have a CS pin attached. for the moment it is easiest to just, use a different pin. |
We have switched to an operation-slice interface instead of a closure since |
What do you think of still going ahead with the plan to split spi into two structs, one that just does SpiBus and one that just does SpiDevice, as described above? I think it would still be useful, as a documentation aid if nothing else, as otherwise it's not really clear why you can use the same struct with both traits ATM. Should I make a separate issue? |
Sorry I missed that. Yes, would you mind copying that part and creating a dedicated issue? |
As far as I can tell*, the current implementation for
SPIBus
andSPIDevice
viaspidev
will assert CS around any of theSPIBus
methods likeread()
andwrite()
, because that's whatspidev
does for each transfer by default.However, the
SPIDevice::transaction()
method expects CS to be asserted once at the start, remain asserted for the duration of the closure, then become deasserted afterwards. Since the closure just calls those methods onSPIBus
, CS is toggled for every transfer inside the transaction, which will break drivers.For example, if a driver has some function that's given a buffer of data to send, and needs to prepend a command byte:
It wants to have CS assert, a 0 byte written, the data written, and then CS de-asserted, but instead CS is asserted/deasserted around both the one-byte write of 0 and the multi-byte write for data.
Ideally, the
SPIBus
methods would not touch CS at all, and onlytransaction()
would somehow assert CS at the start and deassert it at the end. I'm not sure if the Linux spidev interface actually allows for such a thing though, and even if it did, the way it grants you a "bus" that's actually shared with other devices means we sort of break the HAL trait assumptions anyway.I think using
spidev
'stransfer_multiple()
alongside thecs_change
setting it might be possible to do the right thing here, though I'm not completely sure how... if transfers were queued up only to be executed at the end of the transaction, usingflush()
inside the transaction wouldn't work, or would still cause excess CS state changes. Still, it might be better than the current situation?* Right now I can only test this on a remote device and infer what's not working by how a chip isn't responding, so I might be totally wrong here...
The text was updated successfully, but these errors were encountered: