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

cpu/stm32-L4: fix ADC initialization #20756

Merged
merged 1 commit into from
Jul 5, 2024

Conversation

krzysztof-cabaj
Copy link
Contributor

Contribution description

This PR fixes ADC initialization for nucleo-l4xxx boards (more details in issue #20748).
I tested this PR using nucleo-l476rg, nucleo-l496zg and nucleo-l4r5zi.

Testing procedure

Flash mentioned boards (or maybe other from L4xxx family) using tests/periph/adc and observe console.

With this PR you should see new measurements each 100 ms:

main(): This is RIOT! (Version: 2021.07-devel-10832-g0ebb6-nucleo-l4xxx-fix-ADC)

RIOT ADC peripheral driver test

This test will sample all available ADC lines once every 100ms with
a 10-bit resolution and print the sampled results to STDIO

Successfully initialized ADC_LINE(0)
Successfully initialized ADC_LINE(1)
Successfully initialized ADC_LINE(2)
Successfully initialized ADC_LINE(3)
Successfully initialized ADC_LINE(4)
Successfully initialized ADC_LINE(5)
Successfully initialized ADC_LINE(6)
ADC_LINE(0): 279
ADC_LINE(1): 320
ADC_LINE(2): 393
ADC_LINE(3): 317
ADC_LINE(4): 241
ADC_LINE(5): 278
ADC_LINE(6): 175
ADC_LINE(0): 284
ADC_LINE(1): 342
ADC_LINE(2): 391
ADC_LINE(3): 334
ADC_LINE(4): 246
ADC_LINE(5): 281
ADC_LINE(6): 178
      . . .

Issues/PRs references

Fixes #20748

@github-actions github-actions bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: cpu Area: CPU/MCU ports labels Jun 21, 2024
@crasbe
Copy link
Contributor

crasbe commented Jul 1, 2024

I just looked at the defines in the RIOT/build/stm32/cmsis/l4/Include/stm32l476xx.h lines 2564-2568:

#define ADC_CCR_CKMODE_Pos             (16U)
#define ADC_CCR_CKMODE_Msk             (0x3UL << ADC_CCR_CKMODE_Pos)           /*!< 0x00030000 */
#define ADC_CCR_CKMODE                 ADC_CCR_CKMODE_Msk                      /*!< ADC common clock source and prescaler (prescaler only for clock source synchronous) */
#define ADC_CCR_CKMODE_0               (0x1UL << ADC_CCR_CKMODE_Pos)           /*!< 0x00010000 */
#define ADC_CCR_CKMODE_1               (0x2UL << ADC_CCR_CKMODE_Pos)           /*!< 0x00020000 */

When you untangle the code from the PR of @gschorcht that was mentioned in the issue you get the following:

#define ADC_CCR_CKMODE_HCLK_1 (ADC_CCR_CKMODE_0)
...
ADC->CCR |= ADC_CCR_CKMODE_HCLK_1 << ADC_CCR_CKMODE_Pos;

=>
ADC->CCR |= ADR_CCR_CKMODE_0 << ADC_CCR_CKMODE_Pos;

=>
ADC->CCR |= (0x1UL << ADC_CCR_CKMODE_Pos) << ADC_CCR_CKMODE_Pos;

=>
ADC->CCR |= (0x1UL << 16) << 16;

=>
ADC->CCR |= 0x1UL << 32;

=>
ADC->CCR |= 0;

That means that the bit is shifted TWICE, which means it is shifted out of the register, so essentially the code ORs the register with 0. This means the change in the commit form @gschorcht is just wrong.
The only issue that was probably present before was the missing masking of the CKMODE bits. It might have worked for him if CKMODE = 0 was coincidentally the correct setting, so this didn't show up.

I would propose the following code to replace the code in lines 146-167 (and remove the defines of ADC_CCR_CKMODE_HCLK_x in lines 67 and 68):

    ADC->CCR &= ~(ADC_CCR_CKMODE);

    /* Setting ADC clock to HCLK/1 is only allowed if AHB clock prescaler is 1*/
    if (!(RCC->CFGR & RCC_CFGR_HPRE_3)) {
        /* set ADC clock to HCLK/1 */
        ADC->CCR |= (ADC_CCR_CKMODE_0);
    }
    else {
        /* set ADC clock to HCLK/2 otherwise */
        ADC->CCR |= (ADC_CCR_CKMODE_1);
    }

The proposed change is untested because I don't have any L4 Nucleos here (the L452 board definition doesn't have the ADC added yet).

@krzysztof-cabaj
Copy link
Contributor Author

krzysztof-cabaj commented Jul 1, 2024

@crasbe thanks for detailed analysis. I checked provided code using nucleo-l476rg board with tests/periph/adc and everything works perfectly.

Updated code pushed.

@crasbe
Copy link
Contributor

crasbe commented Jul 1, 2024

Good to hear that we could find a universal and elegant fix :)

@krzysztof-cabaj
Copy link
Contributor Author

The proposed change is untested because I don't have any L4 Nucleos here (the L452 board definition doesn't have the ADC added yet).

@crasbe Could you test ADC using this PR and nucleo-l452re board? I enable ADC for this board in the branch, but I couldn't test it - I don't have access to this board.

@crasbe
Copy link
Contributor

crasbe commented Jul 3, 2024

The proposed change is untested because I don't have any L4 Nucleos here (the L452 board definition doesn't have the ADC added yet).

@crasbe Could you test ADC using this PR and nucleo-l452re board? I enable ADC for this board in the branch, but I couldn't test it - I don't have access to this board.

I tested it and it hangs (as expected, because this PR is not applied to your branch).

2024-07-03 13:51:49,822 # main(): This is RIOT! (Version: 2024.07-devel-493-g61a2f-nucleo-l452re-ADC)
2024-07-03 13:51:49,823 # 
2024-07-03 13:51:49,825 # RIOT ADC peripheral driver test
2024-07-03 13:51:49,825 # 
2024-07-03 13:51:49,831 # This test will sample all available ADC lines once every 100ms with
2024-07-03 13:51:49,837 # a 10-bit resolution and print the sampled results to STDIO
2024-07-03 13:51:49,837 # 
2024-07-03 13:51:49,837 # 
*no further output*

When manually applying the fix from this PR, I get the following output:

2024-07-03 13:50:34,735 # main(): This is RIOT! (Version: 2024.07-devel-493-g61a2f-nucleo-l452re-ADC)
2024-07-03 13:50:34,735 # 
2024-07-03 13:50:34,738 # RIOT ADC peripheral driver test
2024-07-03 13:50:34,738 # 
2024-07-03 13:50:34,744 # This test will sample all available ADC lines once every 100ms with
2024-07-03 13:50:34,749 # a 10-bit resolution and print the sampled results to STDIO
2024-07-03 13:50:34,749 # 
2024-07-03 13:50:34,749 # 
2024-07-03 13:50:34,754 # Successfully initialized ADC_LINE(0)
2024-07-03 13:50:34,757 # Successfully initialized ADC_LINE(1)
2024-07-03 13:50:34,760 # Successfully initialized ADC_LINE(2)
2024-07-03 13:50:34,764 # Successfully initialized ADC_LINE(3)
2024-07-03 13:50:34,767 # Successfully initialized ADC_LINE(4)
2024-07-03 13:50:34,770 # Successfully initialized ADC_LINE(5)
2024-07-03 13:50:34,773 # Successfully initialized ADC_LINE(6)
2024-07-03 13:50:34,775 # ADC_LINE(0): 323
2024-07-03 13:50:34,776 # ADC_LINE(1): 332
2024-07-03 13:50:34,778 # ADC_LINE(2): 337
2024-07-03 13:50:34,779 # ADC_LINE(3): 343
2024-07-03 13:50:34,781 # ADC_LINE(4): 336
2024-07-03 13:50:34,782 # ADC_LINE(5): 337
2024-07-03 13:50:34,784 # ADC_LINE(6): 189
2024-07-03 13:50:34,886 # ADC_LINE(0): 325
2024-07-03 13:50:34,887 # ADC_LINE(1): 340
2024-07-03 13:50:34,889 # ADC_LINE(2): 349
2024-07-03 13:50:34,890 # ADC_LINE(3): 352
2024-07-03 13:50:34,892 # ADC_LINE(4): 348
2024-07-03 13:50:34,893 # ADC_LINE(5): 349
2024-07-03 13:50:34,895 # ADC_LINE(6): 193
...

@crasbe
Copy link
Contributor

crasbe commented Jul 3, 2024

I think you can rename this PR and commit to "cpu/stm32: fix L4 ADC initialization" (or similar), since the fix is related to the STM32L4 CPU family and not really to the Nucleo boards.

@krzysztof-cabaj krzysztof-cabaj changed the title boards/nucleo-l4xxx: fix ADC initialization cpu/stm32-L4: fix ADC initialization Jul 3, 2024
@krzysztof-cabaj
Copy link
Contributor Author

@crasbe thanks for your tests. They show that this PR fix problem with ADC initialization and that ADC configuration for nucleo-l452re works. I add doxygen documentation and add PR concerning ADC for nucleo-l452re in the following days.

The note about renaming is very good - I changed PR name.

I hope we could add this code to the RIOT master soon - as it blocks further works with ADC (for e.g. Issue #17260).

@benpicco benpicco added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Jul 4, 2024
@benpicco benpicco enabled auto-merge July 4, 2024 14:10
@riot-ci
Copy link

riot-ci commented Jul 4, 2024

Murdock results

✔️ PASSED

f6e1ce7 boards/nucleo-l4xxx: fix ADC init

Success Failures Total Runtime
10177 0 10178 13m:19s

Artifacts

@benpicco benpicco added this pull request to the merge queue Jul 4, 2024
Merged via the queue into RIOT-OS:master with commit d312d36 Jul 5, 2024
28 checks passed
@mguetschow mguetschow added this to the Release 2024.07 milestone Jul 5, 2024
@krzysztof-cabaj
Copy link
Contributor Author

@crasbe, @benpicco thanks for support with this PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

boards/nucleo-l4xxx: hang during ADC initialization
5 participants