Skip to content

SPI implementation doesn't follow embedded-hal requirements for CS #87

Closed
rust-embedded/embedded-hal
#443
@adamgreig

Description

@adamgreig

As far as I can tell*, the current implementation for SPIBus and SPIDevice via spidev will assert CS around any of the SPIBus methods like read() and write(), because that's what spidev 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 on SPIBus, 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:

fn write_data(&mut self, data: &[u8]) -> Result<(), Self::Error> {
    self.spi.transaction(|bus| {
        bus.write(&[0])?;
        bus.write(data)
    });
}

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 only transaction() 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's transfer_multiple() alongside the cs_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, using flush() 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...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions