Skip to content

SpiProxy is still unsound, even in a single thread #23

@GrantM11235

Description

@GrantM11235

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions