stm32f1xx-hal icon indicating copy to clipboard operation
stm32f1xx-hal copied to clipboard

DMA transfers longer than 255 bytes

Open jamwaffles opened this issue 5 years ago • 1 comments

AsSlice (used in the DMA interfaces) only defines N for N <= 255. I'd like to use the SPI interface on my Blue Pill to drive 64 addressable LEDs. To do this, each LED needs either 12 or 24 bytes, totalling 1536 bytes in the worst case.

How can I send all this data through the SPI DMA? I can't use the non-DMA interface as the timing needs to be tight.

I did try using .chunks(255):

const OFF_BYTE: u8 = 0b1100_0000;

// Set up the DMA device
let dma = dp.DMA1.split(&mut rcc.ahb);

// Connect the SPI device to the DMA
let spi_dma = spi.with_tx_dma(dma.5);

// 64 LEDs, 8 bits per LED plus one final stop bit to set the line low
let mut data: [u8; (64 * 8 * 3)] = [OFF_BYTE; (64 * 8 * 3) ];

for i in data.chunks(255) {
    let (spi_dma, _buffer) = spi_dma.write(&i).wait();
}

but that gave me this error:

error[E0597]: `data` does not live long enough
  --> src/main.rs:88:14
   |
88 |     for i in data.chunks(255) {
   |              ^^^^
   |              |
   |              borrowed value does not live long enough
   |              cast requires that `data` is borrowed for `'static`
...
96 | }
   | - `data` dropped here while still borrowed

error[E0382]: use of moved value: `spi_dma`
  --> src/main.rs:90:34
   |
66 |     let spi_dma = spi.with_tx_dma(dma.5);
   |         ------- move occurs because `spi_dma` has type `stm32f1xx_hal::dma::TxDma<stm32f1xx_hal::spi::SpiPayload<stm32f1::stm32f103::SPI2, stm32f1xx_hal::spi::Spi2NoRemap, (stm32f1xx_hal::gpio::gpiob::PB13<stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::PushPull>>, stm32f1xx_hal::gpio::gpiob::PB14<stm32f1xx_hal::gpio::Input<stm32f1xx_hal::gpio::Floating>>, stm32f1xx_hal::gpio::gpiob::PB15<stm32f1xx_hal::gpio::Alternate<stm32f1xx_hal::gpio::PushPull>>)>, stm32f1xx_hal::dma::dma1::C5>`, which does not implement the `Copy` trait
...
90 |         let (spi_dma, _buffer) = spi_dma.write(&i).wait();
   |                                  ^^^^^^^ value moved here, in previous iteration of loop

error[E0597]: `i` does not live long enough
  --> src/main.rs:90:48
   |
90 |         let (spi_dma, _buffer) = spi_dma.write(&i).wait();
   |                                  --------------^^-
   |                                  |             |
   |                                  |             borrowed value does not live long enough
   |                                  argument requires that `i` is borrowed for `'static`
91 |     }
   |     - `i` dropped here while still borrowed

error: aborting due to 3 previous errors

My lifetime-fu isn't good enough to figure this out yet :(

jamwaffles avatar Dec 21 '19 22:12 jamwaffles

Have you try to use static mut instead of local data?

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fc05710bba55dfedc42989f03d32a1b3

burrbull avatar Dec 22 '19 08:12 burrbull