-
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
cpu/nrf5x_common: fix ztimer issue on warm-boot #20665
cpu/nrf5x_common: fix ztimer issue on warm-boot #20665
Conversation
325d202
to
a49543b
Compare
void clock_start_lf(void) | ||
{ | ||
/* abort if LF clock is already running */ | ||
if (NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk) { | ||
if (clock_lf_running) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a case where this function would be called more than once anyway?
I think we could easily drop that check.
It's only called in rtt_init()
which is run once, the call in nimble_riot.c
could be guarded with a if (!IS_USED(MODULE_PERIPH_RTT))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving this check to a guard in nimble_riot.c
moves logic to somewhere where it doesn't belong to. And the product specification explicitly mentions that changing clock parameters while the clock is running is not allowed.
174bb1e
to
350399d
Compare
Thanks! |
Contribution description
We have been experiencing problems when using
ztimer
on thefeather-nrf52840-sense
boards under certain compiler versions (see inetrg/exercises#5 (comment) and following) after warm-boot (directly after flashing or after pressing the reset button on the board), while after a cold-boot (un- and re-plugging) the board would behave normally.I've spent quite some time debugging this issue and finally found the culprit: the
NRF_CLOCK->LFCLKSTAT
is apparently latched for some short time after a softreset (see this comment by Nordic, sadly it is not reported as an erratum) and wrongly reports the low-frequency clock to be running just after a reboot. Inclock_start_lf()
ofcpu/nrf5x_common/clock.c
, starting the clock is skipped iff the register reports the clock to be running. Apparently different compiler versions (reproducibly) lead to slightly different startup timings, which would explain why the issue only happens with some toolchain versions.The linked discussion suggests to add a check for the reset cause and ignoring the (wrong) state of the LFCLK after a soft reset. To avoid the interdependence with the
RESETREAS
register (which might need to be read and cleared in a future version of RIOT or be expected to be untouched by some application code), I propose a different approach with this PR: Adding a static variable that remembers whether the LFCLK has been started (by RIOT) or not. If anyone has a better suggestion for a work-around, please shout out :)The above linked discussion is about nRF52832 (locally confirmed with an
nrf52dk
), but I can confirm this issue exists on nRF52840-based boards (I have testedfeather-nrf52840-sense
,feather-nrf52840-express
,nrf52840dk
andnrf52840dongle
) as well. I have also testedcalliope-mini
(with nRF51) where I didn't see the problem, but the suggested workaround should not harm unless the user application code tinkers with LFCLK itself.While the issue exists on all tested nRF52840-based boards, it has become especially apparent on
feather-nrf52840-sense
since the reset button triggers the bootloader, which itself triggers a soft-reset into the application. But with the following diff, it is reproducible on the other nRF52840-boards as well.Testing procedure
Apply the following diff to current
master
:Compile with an affected compiler version (debian stable
arm-gcc-none-eabi 12.2.1
is known to have the problem) and flash to some nRF52840 or nRF52832 based board: After the first soft-reset (either triggered from the bootloader in case of the Adafruit boards or triggered by the application code), the reported ztimer difference will be zero and the application will hang duringztimer_sleep
as time is not advancing.With the proposed workaround added, the code should behave as expected.
Issues/PRs references
inetrg/exercises#5