cancel
Showing results for 
Search instead for 
Did you mean: 

Bug in STM32H7 HAL for ADC Injected Channel 18

Kilian Nötzold
Associate III

When for ADC2 Channel 18 is selected as Injected Channel and initialized via “HAL_ADCEx_InjectedConfigChannel�? it will return HAL_ERROR.

When no other ADC it will fail in line 2288 2286*. When another ADC is enabled it will fail in line 2277 2275*.

HAL File: stm32h7xx_hal_adc_ex.c

HAL Version: V1.2.0 V1.3.0

I think the block from line 2229 2227* to 2290 2288* should be included in the else in line 2223 2221*.

Btw the comment in line 2245 2243* is wrong the Temp. sensor it is channel 18

It can easily reproduce by code generation of STM32CubeMX.

1.     Enable ADC2 -> In18

2.     Config ADC2 In18 as Injected Channel

Or use the attached CubeMX project.

*edit for Version V1.3.0

Thanks

7 REPLIES 7

>>HAL Version: V1.2.0

Not current, check if it was addressed in V1.3.0

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Kilian Nötzold
Associate III

Hello Clive,

tanks for the info. Unfortunately V1.3.0 it shows the same behavior.

I have edited the line numbers in the previous post to match the new version.

@STOne-32​ @Imen DAHMEN​ ​ 

STM32Cube_FW_H7_V1.3.0\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_adc.c

Quarter Battery is CH17, and not on ADC1

         /* If Channel 18 is selected, enable VBAT measurement path.          */

         /* Note: VBAT internal internal channels available on ADC1 and ADC3  */

         else if ((sConfig->Channel == ADC_CHANNEL_VBAT_DIV4) && ((hadc->Instance == ADC3)))

         {

           SET_BIT(tmpADC_Common->CCR, ADC_CCR_VBATEN);

         }

STM32Cube_FW_H7_V1.3.0\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_adc_ex.c

All channels wrongly commented

       /* If Channel 17 is selected, enable Temp. sensor measurement path   */

       /* Note: Temp. sensor internal channels available only on ADC3       */

       if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) &&

           (hadc->Instance == ADC3))

       {

         SET_BIT(tmpADC_Common->CCR, ADC_CCR_TSEN);

         /* Delay for temperature sensor stabilization time */

         while(WaitLoopIndex < ADC_TEMPSENSOR_DELAY_US)

         {

           WaitLoopIndex++;

         }

       }

       /* If Channel 18 is selected, enable VBAT measurement path           */

       /* Note: VBAT internal internal channels available only on ADC3      */

       else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT_DIV4) &&

                (hadc->Instance == ADC3))

       {

         SET_BIT(tmpADC_Common->CCR, ADC_CCR_VBATEN);

       }

       /* If Channel 0 is selected, enable VREFINT measurement path         */

       /* Note: VREFINT internal channels available only on ADC3            */

       else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) &&

                (hadc->Instance == ADC3))

       {

         SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);

       }

       else

       {

         /* Discrepancy found out between ADC instance and internal

            channel request */

         SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);

         tmp_hal_status = HAL_ERROR;

       }

The error reported above occurs because the top level test doesn't qualify for ADC3 and it causes a drop through to a HAL_ERROR

   /* If the requested internal measurement path has already been enabled,  */

   /* bypass the configuration processing.                                  */

   if (( (sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) &&

         (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_TSEN))           ) ||

       ( (sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT_DIV4)      &&

         (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VBATEN))         ) ||

       ( (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT)   &&

         (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VREFEN)))

      )

   {

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

   /* If the requested internal measurement path has already been enabled,  */

   /* bypass the configuration processing.                                  */

   if (( (sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) &&

         (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_TSEN))           ) ||

       ( (sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT_DIV4)      &&

         (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VBATEN))         ) ||

       ( (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT)   &&

         (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VREFEN)))

      )

   {

     /* Configuration of common ADC parameters (continuation)               */

     /* Software is allowed to change common parameters only when all ADCs  */

     /* of the common group are disabled.                                   */

     if ((ADC_IS_ENABLE(hadc) == RESET)  &&

         (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )

     {

       /* If Channel 17 is selected, enable Temp. sensor measurement path   */

       /* Note: Temp. sensor internal channels available only on ADC3       */

       if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) &&

           (hadc->Instance == ADC3))

       {

         SET_BIT(tmpADC_Common->CCR, ADC_CCR_TSEN);

         /* Delay for temperature sensor stabilization time */

         while(WaitLoopIndex < ADC_TEMPSENSOR_DELAY_US)

         {

           WaitLoopIndex++;

         }

       }

       /* If Channel 18 is selected, enable VBAT measurement path           */

       /* Note: VBAT internal internal channels available only on ADC3      */

       else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT_DIV4) &&

                (hadc->Instance == ADC3))

       {

         SET_BIT(tmpADC_Common->CCR, ADC_CCR_VBATEN);

       }

       /* If Channel 0 is selected, enable VREFINT measurement path         */

       /* Note: VREFINT internal channels available only on ADC3            */

       else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) &&

                (hadc->Instance == ADC3))

       {

         SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);

       }

       else

       {

         /* Discrepancy found out between ADC instance and internal

            channel request */

         SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);

         tmp_hal_status = HAL_ERROR;

       }

     }

     /* If the requested internal measurement path has already been enabled */

     /* and other ADC of the common group are enabled, internal             */

     /* measurement paths cannot be enabled.                                */

     else

     {

       /* Update ADC state machine to error */

       SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);

       tmp_hal_status = HAL_ERROR;

     }

   }

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

@Kilian Nötzold​ definitely a complete mess, flagged to staff.

   /* Configuration of common ADC parameters                                */

   if((hadc->Instance == ADC1) || (hadc->Instance == ADC2))

   {

     /* Pointer to the common control register                                */

     tmpADC_Common = ADC12_COMMON_REGISTER(hadc);

   }

   else

   {

     /* Pointer to the common control register                                */

     tmpADC_Common = ADC3_COMMON_REGISTER(hadc);

   } // MOVE THIS BRACE OVER/AROUND THE OFFENDING CODE FOR ADC3 BELOW

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Kilian Nötzold
Associate III

@Community member​ Thanks for informing ST.

Whoever is taking care on this topic should also check if a similar issue exists in stm32h7xx_hal_adc.c staring in line 2548 as the code looks Identical. I haven’t looked deeper into but at least the comments are messed in the same way.

FYI The same issue exists for stm32h7xx_hal_adc.c