0
votes

I am trying to write a Rust device driver using STM32 SPI DMA. SPI DMA code is quite easy if you look at the stm32f1xx-hal example, but the traits are very complex. I cannot figure out how to get the compiler to accept the following code which fails on the wait call.

impl<SPI, REMAP, PINS, CH> DeviceDriver<SpiTxDma<SPI, REMAP, PINS, CH>>
where SpiTxDma<SPI, REMAP, PINS, CH>: WriteDma<&'static mut [u8], u8>,
{
    pub fn send(&mut self) {
        if let (Some(spi), Some(buf)) = (self.spi.take(), self.buf.take()) {
            let transfer = spi.write(buf);
            let (buf, spi) = transfer.wait();
            self.buf = Some(buf);
            self.spi = Some(spi);
        }
    }
}

The error:

25 |             let (buf, spi) = txdma.wait();
   |                                    ^^^^ method not found in `Transfer<stm32f1xx_hal::dma::R, &mut [u8], TxDma<SpiPayload<SPI, REMAP, PINS>, CH>>`

However, if I replace the CH type parameter with a fixed struct name C5, it compiles fine.

Why would fixing a type parameter, changing nothing else, cause the code to compile/fail?

Obviously, the above won't work in a playground, so here's the (non)buildable repo.

1

1 Answers

1
votes

The wait method is only defined if TxDma<SpiPayload<SPI, REMAP, PINS>, CH> implements TransferPayload, which is the case for the concrete type C5 but not for the unconstrained type parameter CH. Try adding a constraint to your code:

impl<SPI, REMAP, PINS, CH> DeviceDriver<SpiTxDma<SPI, REMAP, PINS, CH>>
where SpiTxDma<SPI, REMAP, PINS, CH>: WriteDma<&'static mut [u8], u8>,
      TxDma<SpiPayload<SPI, REMAP, PINS>, CH>: TransferPayload,
{
    pub fn send(&mut self) {
        if let (Some(spi), Some(buf)) = (self.spi.take(), self.buf.take()) {
            let transfer = spi.write(buf);
            let (buf, spi) = transfer.wait();
            self.buf = Some(buf);
            self.spi = Some(spi);
        }
    }
}