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

ADC DMA blocked by another interrupt

Open franular opened this issue 1 year ago • 0 comments

I'm using an STM32F411 chip via WeAct's Blackpill and am trying to read an analog input through one pin while outputting an unrelated PWM signal through another.

The PWM signal is successfully outputted via interrupt TIM1_UP_TIM10().

The ADC can be read over DMA when DMA2_STREAM0() is the only active interrupt. The ADC can also be read directly via the ADC() interrupt while also outputting PWM the same way as before; however, trying to read ADC via DMA2_STREAM0() while outputting PWM apparently blocks the DMA2_STREAM0() interrupt after one cycle (when ADC and its DMA initialized before PWM) or several cycles (when ADC and its DMA initialized after PWM).

Here's the gist of the initialization code:

    // init adc
    let adc_config = adc_cfg::AdcConfig::default()
        .scan(adc_cfg::Scan::Enabled)
        .continuous(adc_cfg::Continuous::Continuous)
        .dma(adc_cfg::Dma::Continuous);
    let mut adc = hal::adc::Adc::adc1(dp.ADC1, true, adc_config);

    let x_pin = gpioa.pa0.into_analog();

    adc.configure_channel(
        &x_pin,
        adc_cfg::Sequence::One,
        adc_cfg::SampleTime::Cycles_480
    );
    adc.enable();

    let dma = hal::dma::StreamsTuple::new(dp.DMA2);
    let dma_config = hal::dma::config::DmaConfig::default()
        .memory_increment(true)
        .fifo_enable(true)
        .fifo_error_interrupt(true)
        .transfer_complete_interrupt(true);

    let buf = cortex_m::singleton!(: [u16; 2] = [0; 2]).unwrap();

    let mut transfer = Transfer::init_peripheral_to_memory(
        dma.0,
        adc,
        buf,
        None,
        dma_config
    );

    unsafe { cortex_m::peripheral::NVIC::unmask(Interrupt::DMA2_STREAM0) };
    cs::with(|cs| {
        ADC_TRANS.borrow(cs).replace(Some(transfer));
        ADC_TRANS
            .borrow_ref_mut(cs)
            .as_mut()
            .unwrap()
            .start(|adc| adc.start_conversion())
    });

    // init pwm
    let channel = hal::timer::Channel3::new(gpioa.pa10);
    let mut pwm = dp.TIM1.pwm_hz(channel, 32.kHz(), &clocks);

    pwm.enable(hal::timer::Channel::C3);
    pwm.listen(hal::timer::Event::Update);

    cs::with(|cs| PWM_TIM.borrow(cs).replace(Some(pwm)));
    unsafe { cortex_m::peripheral::NVIC::unmask(Interrupt::TIM1_UP_TIM10) };

From looking at this library, I'm under the impression that PWM also leverages DMA; is this causing a conflict, or is there something else I'm missing?

franular avatar Feb 07 '24 04:02 franular