cpu/stm32wl: Replace ztimer with busy_wait and fix initialization sequence #21238
+76
−23
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Contribution description
This PR fixes two issues with the ADC of the STM32WL55.
The ADC initialization routine used
ztimer
for an uncritical delay, which caused issues (a crash) when it was called from the early reset vector to check the battery status. I explained it here in greater detail: boards/nucleo-wl55jc: add ADC configuration #21235 (comment)Using ztimer for an uncritical delay is not really necessary, especially since the intended delay is 20µs and if only
ZTIMER_MSEC
was available instead ofZTIMER_USEC
, the delay was extended to 1ms.I replaced it with busy_wait and added a factor of 2, because busy_wait is not really accurate. We can wait longer, but we shouldn't push our luck by waiting shorter.
Similar to the L0, L1 and F0/G0/C0 ADC implementations, the initialization order was incorrect. The resolution setting will be ignored when the ADC is already enabled, as described in the Errata [1].
I adapted the
_adc_enable
and_adc_disable
functions from PR cpu/stm32{f0,g0,c0}: fix ADC initialization sequence #21230. At this moment it is a bit pointless to have_disable_adc
return something, but in the future someone (maybe me) wants to add a timeout to the somewhat dangerous infinite while loops and then it makes sense to have the return in place already.Also I changed the
is the ADC already initialized?
-test from checked theADEN
bit to checking if the sampling time has already been set.This should work without issues since the reset value for this register is 0.
(No fix but an improvement) Similar to the F0/G0/C0 PR from cpu/stm32{f0,g0,c0}: fix ADC initialization sequence #21230, I added the RS-register guard to avoid setting or resetting a flag that shouldn't be touched.
The issue here is that sometimes a flag is set by writing a 1 to it (typical behavior) and sometimes it is reset by writing a 1 to it. A typical RMW-cycle could potentially reset a flag, which is why the original STM32-HAL uses these guards.
The older documentation does not say that this is required, but it can't hurt. The initialization is not really time critical so we don't have to save cycles.
Testing procedure
The testing procedure is a bit of a hen-egg-problem, because for some reason the Nucleo-WL55 did not have the ADC lines configured, so PR #21235 has to be applied as well as this one. I recommend checking out PR #21235 and manually copying
cpu/stm32/periph/adc_wl.c
from this PR.The first part of this PR can be easily tested with
tests/periph/vbat
withBOARD=nucleo-wl55jc make -C tests/periph/vbat flash term
.With current master:
With this PR:
The second part of this PR can be tested with
tests/periph/adc
with withBOARD=nucleo-wl55jc make -C tests/periph/adc flash term
.With master:
With this PR:
Issues/PRs references
This has to be merged before #20971 can be merged (and tested...).
See also
[1] https://www.st.com/resource/en/errata_sheet/es0500-stm32wl55xx-stm32wl54xx-device-errata-stmicroelectronics.pdf p.13 section 2.3.2