-
Notifications
You must be signed in to change notification settings - Fork 2k
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
stm32/adc: make resolution flag checks consistent for all STM32 families #20780
Comments
I have access to F207 and F334. I will try to arrange access to C031. |
It looks like this is turning into a bit of a rabbit hole again 🫠 ...
while (1) {
for (unsigned i = 0; i < ADC_NUMOF; i++) {
int sample6 = adc_sample(ADC_LINE(i), ADC_RES_6BIT);
int sample8 = adc_sample(ADC_LINE(i), ADC_RES_8BIT);
int sample10 = adc_sample(ADC_LINE(i), ADC_RES_10BIT);
int sample12 = adc_sample(ADC_LINE(i), ADC_RES_12BIT);
int sample14 = adc_sample(ADC_LINE(i), ADC_RES_14BIT);
int sample16 = adc_sample(ADC_LINE(i), ADC_RES_16BIT);
printf("ADC_LINE(%u): %i %i %i %i %i %i\n", i, sample6, sample8, sample10, sample12, sample14, sample16);
}
ztimer_sleep(ZTIMER_MSEC, DELAY_MS);
}
... The variable for the sample has to be commented out, so it does not throw a compiler error. - int sample = 0;
+//int sample = 0; When I connect one of the ADC inputs to 3.3V, this is what the output looks like:
The two -1 at the end are expected, because the L073 does not support 14-bit and 16-bit conversions, but the other values shouldn't be all 4096 = 0b00001111.11111111, that is 12-bit resolution. I'm not 100% sure yet what the reason is for this behavior, but it looks like the ADC configuration in
This is not the case in the current code, the resolution (among other things) is configured with the ADC enabled, which might lead to the ADC ignoring the configuration. |
Interestingly, for the STM32L4, the behavior is different. I have a NUCLEO-L452RE here, and this is what the output looks like:
As expected, the resolution was applied correctly. The reference manual of the STM32L4 [2] page 631, section 21.4.10 explains that you're only allowed to write to the configuration when the ADC is enabled, so exactly the opposite of the L0.
Now I only have to find out how the ADCs of the other devices behave (or should behave). |
The test on the NUCLEO-L152RE does not run successfully at all, it runs into a hard fault after the first loop iteration:
(Nothing is printed after the "Context before hardfault:" message.) Furthermore the ADC seems to be stuck in 6 bit mode, I connected Pin A1 to 3.3V. The behavior is the same on the master branch (both hard fault and 6 bit). I'm not sure yet what the cause of the issue is, but it might have to do with the watchdog not being correctly configured. But first I'd have to check where exactly the test program crashes. |
Update: The L0 fix was rather easy, just move the The L1 issue is not caused by the ADC, but by However interestingly, this was not the reason why the ADC was stuck in 6-bit mode. The reason was that the resolution bits of the /* set resolution, conversion channel and single read */
+ ADC1->CR1 &= ~ADC_CR1_RES_Msk;
ADC1->CR1 |= res & ADC_CR1_RES;
ADC1->SQR1 &= ~ADC_SQR1_L;
ADC1->SQR5 = adc_config[line].chan; None of the other ADC implementations suffer from the same bug as the L1, so I'll create a PR to fix the L0 and L1 ADCs, so we can actually test #20971 🙃 |
This error is the weirdest thing. The error depends on the way the program is flashed. If you flash it with OpenOCD So my hypothesis is, that the ztimer code for the STM32L152RE does not fully configure something which makes the program crash (and crash again) and the reset of the ST-Link is somehow "harder" than the OpenOCD reset and the reset caused by the reset button. I'll open a separate issue about it, because that doesn't really has anything to do and I already put in way too much time... |
Description
As discovered in #20773 (comment), some variants of the STM32 ADC peripheral use magic numbers in an undocumented way to check if the ADC resolution has a valid value or or not:
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_f0_g0_c0.c#L103-L106
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_f2.c#L112-L114
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_f3.c#L196-L199
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_f4_f7.c#L131-L134
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_l4_wb.c#L220-L223
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_wl.c#L121-L124
Some other implementations explicitly check if the resolution value is one of the valid values, so IMO this is the better approach:
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_f1.c#L146-L149
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_l0.c#L120-L126
https://github.com/RIOT-OS/RIOT/blob/master/cpu/stm32/periph/adc_l1.c#L149-L155
I have the following STM32 boards available:
NUCLEO-F413ZH
NUCLEO-G474RE (not supported yet, seems to have the same ADC as the H7 series and quite similar to L4, just a little more options)
NUCLEO-L073RZ (irrelevant, won't be changed)
NUCLEO-L452RE
P-NUCLEO-WB55 (duplicate for L4)
So we're still missing F0/F0/C0, F2, F3 and WL boards for testing. Maybe I can get some of them from Mouser in the future, but maybe someone else has some of these boards for testing.
Useful links
STM32G474 Reference Manual: https://www.st.com/resource/en/datasheet/stm32g474cb.pdf p.591
The text was updated successfully, but these errors were encountered: