shared-bus icon indicating copy to clipboard operation
shared-bus copied to clipboard

SpiProxy is still unsound, even in a single thread

Open GrantM11235 opened this issue 2 years ago • 1 comments

The "fix" for #8 assumes that drivers will only activate their CS right before communicating and deactivate it right afterwards and that there is no way for any other code in the same thread to do anything else in that time. However, this is not part of any API contract and drivers don't always work this way in practice.

The following hypothetical driver is perfectly valid, but using it with SpiProxy would lead to some unfortunate bugs.

pub struct DoomsdayDevice<SPI, CS> {
    spi: SPI,
    cs: CS,
}

impl<SPI, CS> DoomsdayDevice<SPI, CS>
where
    SPI: embedded_hal::blocking::spi::Write<u8>,
    CS: embedded_hal::digital::v2::OutputPin,
    CS::Error: core::fmt::Debug,
{
    pub fn new(spi: SPI, mut cs: CS) -> Self {
        // We own the SPI struct, so it is fine to just keep the CS pin active (low)
        cs.set_low().unwrap();
        Self { spi, cs }
    }

    pub fn detonate(&mut self) -> Result<(), SPI::Error> {
        // Send the super-secure password to the device, ending all life on earth
        self.spi.write(&[0x00])
    }

    pub fn split(self) -> (SPI, CS) {
        let Self { spi, mut cs } = self;
        // Set the CS pin to idle (high)
        cs.set_high().unwrap();
        (spi, cs)
    }
}

For my suggestion about how to fix this problem, see rust-embedded/embedded-hal#299

GrantM11235 avatar Aug 01 '21 01:08 GrantM11235

Ack, I am aware of this. I'm in the process of writing up a response to the issue you linked, but didn't get to finishing it yet. Sorry for the radio silence in the last week.

Rahix avatar Aug 03 '21 07:08 Rahix