zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.93k stars 6.65k forks source link

stm32h7: adc: sequence of more than 8 channels does not work #79909

Open nono313 opened 1 month ago

nono313 commented 1 month ago

Describe the bug Starting an adc scan sequence of more than 8 channels does not work on STM32H7

Tested on nucleo_h723zg with adc_sequence sample

To Reproduce

  1. create an overlay for the stm32h723 in the board folder of the adc_sequence sample (see below)
  2. update the prj.conf to add logs and reduce extra samples with
    CONFIG_LOG=y
    CONFIG_ADC_LOG_LEVEL_DBG=y
    CONFIG_SEQUENCE_SAMPLES=1
  3. go to samples/drivers/adc/adc_sequence and build the project with west build -b nucleo_h723zg . -p
  4. flash to nucleo board with west flash

Example of overlay I used:


/ {
    zephyr,user {
    };

    aliases {
        adc0 = &adc1;
    };
};

&gpiod {
    status = "okay";
};

&gpioc {
    status = "okay";
};

&gpiob {
    status = "okay";
};

&clk_lsi {
    status = "okay";
};

&clk_hsi48 {
    status = "okay";
};

&clk_hsi {
    status = "okay";
    hsi-div = <1>;
};

&clk_hse {
    clock-frequency = <DT_FREQ_M(25)>;
    status = "disabled";
};

&pll {
    div-m = <4>;
    mul-n = <34>;
    div-p = <1>;
    div-q = <68>;   /* DIVQ at 68 to get 8MHz FDCAN clock */
    div-r = <2>;
    clocks = <&clk_hsi>;
    status = "okay";
};

&pll2 {
    status = "okay";
    clocks = <&clk_hsi>;
    div-m = <4>;
    mul-n = <12>;
    div-p = <4>;
    div-q = <2>;
    div-r = <2>;
};

&rcc {
    clock-frequency = <DT_FREQ_M(544)>;
    clocks = <&pll>;
    d1cpre = <1>;
    hpre = <2>;    /* HCLK: 272   MHz */
    d1ppre = <2>;  /* APB1: 136 MHz */
    d2ppre1 = <2>; /* APB2: 136 MHz */
    d2ppre2 = <2>; /* APB3: 136 MHz */
    d3ppre = <2>;  /* APB4: 136 MHz */
};

&adc1 {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";

    pinctrl-0 = <&adc1_inp11_pc1 &adc1_inp10_pc0 &adc1_inp17_pa1 &adc1_inp16_pa0
        &adc1_inp15_pa3 &adc1_inp14_pa2 &adc1_inp19_pa5 &adc1_inp18_pa4 
        &adc1_inp7_pa7 &adc1_inp3_pa6 &adc1_inp8_pc5 &adc1_inp4_pc4
        &adc1_inp5_pb1 &adc1_inp9_pb0 &adc1_inp6_pf12 &adc1_inp2_pf11>;
    pinctrl-names = "default";
    st,adc-clock-source = <ASYNC>;  /* PLL2_P @48MHz */
    st,adc-prescaler = <1>;
    st,adc-sequencer = <FULLY_CONFIGURABLE>;
    vref-mv = <2000>;

    channel@2 {
        reg = <2>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@3 {
        reg = <3>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@4 {
        reg = <4>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@5 {
        reg = <5>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@6 {
        reg = <6>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@7 {
        reg = <7>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@8 {
        reg = <8>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@9 {
        reg = <9>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
    };

    channel@a {
        reg = <10>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,vref-mv = <2000>;
        zephyr,resolution = <16>;
     };
};

Expected behavior Sequence should start and complete in a loop and analog values should be displayed

Impact Sequence need to be split to be at most 8 channels long

Logs and console output Here is the log I have with 9 channels:

[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_start_conversion: Starting conversion
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.

When I only set 8 channels (commenting out one channel), I get this logs: in a loop:

[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
[00:00:00.000,000] <dbg> adc_stm32: adc_stm32_channel_setup: Channel setup succeeded!
- adc@40022000, channel 2, 1 sequence samples:
- - 1015 = 0mV
- adc@40022000, channel 3, 1 sequence samples:
- - 751 = 0mV
- adc@40022000, channel 4, 1 sequence samples:
- - 8 = 0mV
- adc@40022000, channel 5, 1 sequence samples:
- - 480 = 0mV
- adc@40022000, channel 6, 1 sequence samples:
- - 1002 = 0mV
- adc@40022000, channel 7, 1 sequence samples:
- - 9 = 0mV
- adc@40022000, channel 8, 1 sequence samples:
- - 13 = 0mV
- adc@40022000, channel 9, 1 sequence samples:
- - 10 = 0mV
ADC sequence reading [1]:
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_start_conversion: Starting conversion
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
[00:00:01.002,000] <dbg> adc_stm32: adc_stm32_isr: adc@40022000 ISR triggered.
- adc@40022000, channel 2, 1 sequence samples:
- - 656 = 0mV
- adc@40022000, channel 3, 1 sequence samples:
- - 436 = 0mV
- adc@40022000, channel 4, 1 sequence samples:
- - 11 = 0mV
- adc@40022000, channel 5, 1 sequence samples:
- - 350 = 0mV
- adc@40022000, channel 6, 1 sequence samples:
- - 534 = 0mV
- adc@40022000, channel 7, 1 sequence samples:
- - 14 = 0mV
- adc@40022000, channel 8, 1 sequence samples:
- - 9 = 0mV
- adc@40022000, channel 9, 1 sequence samples:
- - 11 = 0mV

Environment (please complete the following information):

Additional context

gautierg-st commented 1 month ago

Hello, I think you could have an overrun error (this can be checked in the ADC status register). Could you try increasing the st,adc-prescaler and/or the zephyr,acquisition-time?

nono313 commented 1 month ago

Hello, I think you could have an overrun error (this can be checked in the ADC status register). Could you try increasing the st,adc-prescaler and/or the zephyr,acquisition-time?

That was it, thanks. I do indeed see OVR flag set. As the OVR flag is not handled in the interrupt there is no information for the user that an overrun occurred. Should I close this issue and should OVR be handled in the driver anyway ?

gautierg-st commented 1 month ago

OVR is very tricky to handle, if it happens, more likely than not it will happen again, since timings will probably be the same the next time a measurement is made. The best way to treat OVR is to not have it happen at all by configuring the timings accordingly (mainly clock source, prescaler and sampling time). But maybe a log stating that an overrun occurred and that timings need to be adjusted would be in order.

erwango commented 2 weeks ago

@gautierg-st Could you open a PR to provide a message when OVR is seen ?