japaric / stm32f103xx-hal

HAL for the STM32F103xx family of microcontrollers
Apache License 2.0
115 stars 40 forks source link

ownership in serial+DMA #105

Closed burrbull closed 5 years ago

burrbull commented 5 years ago

Serial transfer function .write_all takes ownership of tx and channel, so I can't use it in loops:

for _ in 0..5 {
    let (_, _c, _tx) = tx.write_all(c, b" jumps").wait();
                       ^^ value moved here in previous iteration of loop
}

or something I don't understand?

TeXitoi commented 5 years ago

If you need synchronous write, use https://japaric.github.io/stm32f103xx-hal/stm32f103xx_hal/serial/struct.Tx.html#impl-Write%3Cu8%3E

If you want DMA, you'll need to jungle a bit with the ownership of the pins. Option::take is a common workaround.

TeXitoi commented 5 years ago

Something like

let mut tx = Some(tx);
let mut c = Some(c);
for _ in 0..5 {
    let (_, c_back, tx_back) = tx.take().write_all(c.take(), b" jumps").wait();
    tx = Some(tx_back);
    c = Some(c_back);
}

That's needed to be sure that you will not mess up everything by using the tx and c during the DMA transfer.

burrbull commented 5 years ago

Interesting solution. Thanks.

TeXitoi commented 5 years ago

You can also fold:

n write(s1: String, s2: String) -> (String, String) {
    println!("{} {}", s1, s2);
    (s2, s1)
}

fn main() {
    let mut s1 = Some("toto".to_string());
    let mut s2 = Some("tata".to_string());
    println!("loop");
    for _ in 0..5 {
        let (s1_back, s2_back) = write(s1.take().unwrap(), s2.take().unwrap());
        s1 = Some(s1_back);
        s2 = Some(s2_back);
    }
    println!("fold");
    let (s1, s2) = (0..5).fold((s1.unwrap(), s2.unwrap()), |(s1, s2), _| write(s1, s2));
    println!("final: {} {}", s1, s2);
}