Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The ADC does not work in continuous mode if there is a small delay after starting #799

Open
faunel opened this issue Sep 4, 2024 · 0 comments

Comments

@faunel
Copy link

faunel commented Sep 4, 2024

The ADC does not work in continuous mode if there is a small delay after starting (transfer.start)
A delay of 1 ms is sufficient (line delay.delay_ms(1);).

I tested this on two boards - STM32F401CE, STM32F411CE (Black pill)
And the issue occurs on both.

Also, the ADC can suddenly stop working if there is a blocking operation in the task for a few milliseconds during the process.
There are no errors in this case.

Also, in single mode, if we start the ADC in the interrupt handler,
the ADC can also suddenly stop working.
This manifests at a start frequency of 100 kHz, Pclk2_div_2, and a small number of cycles (Cycles_112 or less).

#[init]
    fn init(cx: init::Context) -> (Shared, Local) {
        let dp = cx.device;
        let cp = cx.core;

        // Clock configuration
        let clocks = dp
            .RCC
            .constrain()
            .cfgr
            .use_hse(25.MHz())
            .sysclk(80.MHz())
            .freeze();

        // GPIO
        let gpioa = dp.GPIOA.split();

        let mut delay = cp.SYST.delay(&clocks);

        // ADC pin configuration
        let adc_pin1 = gpioa.pa1.into_analog();
        let adc_pin2 = gpioa.pa2.into_analog();

        // DMA stream
        let dma = StreamsTuple::new(dp.DMA2);

        // ADC config
        let adc_config = AdcConfig::default()
            .dma(Dma::Continuous)
            .scan(Scan::Enabled)
            .clock(Clock::Pclk2_div_8)
            .continuous(Continuous::Continuous);

        // ADC channel configuration
        let mut adc = Adc::adc1(dp.ADC1, true, adc_config);
        adc.configure_channel(&adc_pin1, Sequence::One, SampleTime::Cycles_480);
        adc.configure_channel(&adc_pin2, Sequence::Two, SampleTime::Cycles_480);
 
        let first_buffer = cortex_m::singleton!(: [u16; 2] = [0; 2]).unwrap();
        let buffer = Some(cortex_m::singleton!(: [u16; 2] = [0; 2]).unwrap());

        // DMA config
        let dma_config = DmaConfig::default()
            .transfer_complete_interrupt(true)
            .memory_increment(true)
            .double_buffer(false);

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

        transfer.start(|adc| {
            adc.start_conversion();
        });

        // It does not work with this delay.
        delay.delay_ms(1);

        (
            Shared {
                transfer
            },
            Local {
                buffer
            },
        )
    }

Added a project with an example in the attachment.
adc_bug.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant