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

DMA Transfer consumes peripheral

Open unpaid-bill opened this issue 3 years ago • 3 comments

Right now there aren't really any examples of both DMA and peripherals using this HAL, so I might be doing something wrong. I'm able to both build a DMA Transfer and initiate a peripheral such as the adc using this HAL, but not both at the same time.

// DMA init
let stream_0 = StreamsTuple::new(dp.DMA2).0;
let buf = singleton!(: [u16; 128] = [0; 128]).unwrap();
let dma_config = DmaConfig::default();

let adc_dma_transfer = Transfer::init(stream_0, dp.ADC1, buf, None, dma_config);  //<-- consumes dp.ADC1

// adc init
let adc_config = hal::adc::config::AdcConfig::default();
let adc_periph = Adc::adc1(dp.ADC1, true, adc_config); //<-- cannot init this peripheral. ADC1 has already been moved

I haven't dug too much into the DMA implementation but I don't think it would need ownership of the peripheral.

unpaid-bill avatar Mar 25 '21 08:03 unpaid-bill

Reading more into it, I understand I could instead hand the dma Transfer a copy of its address with something like

unsafe { &*ADC1::ptr() as *const _ as u32 }

But wouldn't it be more elegant for that to happen inside the dma module and not in the application code? The stm32f1xx-hal has dma implementations of peripherals within their respective peripheral crate, so this de/referencing happens there. Is that an approach this HAL is looking to move toward?

unpaid-bill avatar Mar 26 '21 00:03 unpaid-bill

The idea is to implement the necessary abstraction and traits to the Adc HAL type, and pass it to the Transfer API instead of the pac type. It seems that this was done already for serial, but other peripherals are still missing.

thalesfragoso avatar Mar 26 '21 00:03 thalesfragoso

I just had a look: as of now (0.10.1) the Adc traits seem to be implemented for at least ADC1; nevertheless, the adc hal types are consumed themselves. This renders the calibration data inaccessible, as can be seen in the adc_dma example. The peripheral in the Transfer structs is passed as &mut to the closures of start,pause, so I don't think we get around that.

A way to fix this special issue could be to expose a reference to the peripheral. This allows us to use for example adc.sample_to_millivolts() wherever the sampled values are consumed.

gernoteger avatar Dec 06 '21 22:12 gernoteger