-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
nrf: Fix non-running LFCLK #13339
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
Closed
Closed
nrf: Fix non-running LFCLK #13339
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Code size report:
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #13339 +/- ##
=======================================
Coverage 98.39% 98.39%
=======================================
Files 161 161
Lines 21078 21078
=======================================
Hits 20739 20739
Misses 339 339 ☔ View full report in Codecov by Sentry. |
It destroys a few manual alignments, but these seem minor compared to the benefit of automated code style consistency. Signed-off-by: Christian Walther <cwalther@gmx.ch>
Under some circumstances, after a hard reset, the low-frequency clock would not be running. This caused time.ticks_ms() to return 0, time.sleep_ms() to get stuck, and other misbehavior. A soft reboot would return it to a working state. The cause was a race condition that was hit when the bootloader would itself turn LFCLK on, but turn it off again shortly before launching the main application (this apparently happens with the Adafruit bootloader from https://github.com/fanoush/ds-d6/tree/master/micropython). Stopping the clock is an asynchronous operation and it continues running for a short time after the stop command is given. When MicroPython checked whether to start it by looking at the LFCLKSTAT register (nrf_clock_lf_is_running) during that time, it would mistakenly not be started again. What MicroPython should be looking at is not whether the clock is running at this time, but whether a start/stop command has been given, which is indicated by the LFCLKRUN register (nrf_clock_lf_start_task_status_get). It is not clearly documented, but empirically LFCLKRUN is not just set when the LFCLKSTART task is triggered, but also cleared when the LFCLKSTOP task is triggered, which is exactly what we need. The matter is complicated by the fact that the nRF52832 has an anomaly (see [errata](https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev3/ERR/nRF52832/Rev3/latest/anomaly_832_132.html?cp=5_2_1_0_1_33)) where starting the LFCLK will not work between 66µs and 138µs after it last stopped. Apply a workaround for that. See nrfx_clock_lfclk_start() in micropython/lib/nrfx/drivers/src/nrfx_clock.c for reference, but I am not using that because it also does other things and makes the code larger. Signed-off-by: Christian Walther <cwalther@gmx.ch>
Rebased on master to deal with the STATIC removal, no other changes required. |
Thanks! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
As discussed in #13062 (post): under some circumstances, after a hard reset (power-on or
machine.reset()
), the low-frequency clock would not be running. This causedtime.ticks_ms()
to return 0,time.sleep_ms()
to get stuck, and other misbehavior. A soft reboot would return it to a working state.The cause was a race condition that was hit when the bootloader would itself turn LFCLK on, but turn it off again shortly before launching the main application (this apparently happens with the Adafruit bootloader from https://github.com/fanoush/ds-d6/tree/master/micropython). Stopping the clock is an asynchronous operation and it continues running for a short time after the stop command is given. When MicroPython checked whether to start it by looking at the LFCLKSTAT register (
nrf_clock_lf_is_running
) during that time, it would mistakenly not be started again. What MicroPython should be looking at is not whether the clock is running at this time, but whether a start/stop command has been given, which is indicated by the LFCLKRUN register (nrf_clock_lf_start_task_status_get
). It is not clearly documented, but empirically LFCLKRUN is not just set when the LFCLKSTART task is triggered, but also cleared when the LFCLKSTOP task is triggered, which is exactly what we need.The matter is complicated by the fact that the nRF52832 has an anomaly (see errata) where starting the LFCLK will not work between 66µs and 138µs after it last stopped. Apply a workaround for that. See
nrfx_clock_lfclk_start()
in micropython/lib/nrfx/drivers/src/nrfx_clock.c for reference, but I am not using that because it also does other things and makes the code larger.Tested on a DS-D6 with nRF52832 (where the issue would occur) and on an Adafruit ItsyBitsy nRF52840 (where it would not, but just to check that I didn’t break anything). (By the way, would a board definition for the ItsyBitsy nRF52840 be welcome? I had to make one because it’s the only nRF52840 board I have.)