Skip to content

nRF: Add system clock stability policy #27398

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

Merged
merged 3 commits into from
Sep 10, 2020

Conversation

nordic-krch
Copy link
Contributor

@nordic-krch nordic-krch commented Aug 6, 2020

Pull request adds clock stability policy configuration to the system clock (see #22758) and adds support to Nordic platform. Additionally, spin waiting for stable or available clock has been reworked for Nordic to allow going to idle while waiting for clock readiness (it can take up to 250 ms). Added test dedicated for Nordic platforms which validates correctness of behavior for each configuration against various clock sources.

Fixes #22758.
Fixes #26280.

@github-actions github-actions bot added area: API Changes to public APIs area: Tests Issues related to a particular existing or missing test labels Aug 6, 2020
Copy link
Contributor

@andyross andyross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No complaints about the code. But is this really a good candidate for a global API? Right now it's just the one platform that needs to care about this. Maybe we should start this out as an internal thing with the nRF timer driver and promote the kconfig API to a global one only later?

I guess my criteria for this is: if we add a kconfig value to the core kernel, and it's never inspected by or modified by any of the code or tests dealing with the core kernel, it shouldn't be a core kernel feature. ... ?

@nordic-krch
Copy link
Contributor Author

Seems to me that there is also sam0_rtc driver which seems to currently wait for the clock:

/* Synchronize GCLK. */

Not sure who is maintaining it.

Copy link
Contributor

@pabigot pabigot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question about whether EVENT_LFCLKSTART could be handled by the ISR and cleared before the spinwait that's looking for it. E.g. if something else like a bootloader had done some clock configuration so it could be triggered faster than normal.

I like the two-phase startup for LFXO to catch the distinct stages.

/* Synth source start is almost instant and LFCLKSTARTED may
* happen before calling idle. That would lead to deadlock.
*/
if (!IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the goal here, but z_clock_driver_init() will invoke z_nrf_clock_control_lf_on() which on its first entry will use the onoff manager to trigger TASK_LFCLKSTART. All that is before interrupts are locked on entry to this function.

There is a typical 1 ms startup time for this on nRF52840, but it does seem like the ISR may have already processed LFCLKSTARTED before the lock is taken, so deadlock is still possible.

Copy link
Contributor Author

@nordic-krch nordic-krch Aug 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typical 1 ms startup time for this on nRF52840, but it does seem like the ISR may have already processed LFCLKSTARTED before the lock is taken, so deadlock is still possible.

Interrupts are locked at this point of startup. I call irq_lock just to get key which is required by k_cpu_atomic_idle and irq_unlock for consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will see if i can do something to support call of z_nrf_clock_control_lf_on without that assumption.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interrupts are locked at this point of startup.

Could you expand on this?

z_clock_driver_init() at PRE_KERNEL_2/CONFIG_SYSTEM_CLOCK_INIT_PRIORITY invokes
z_nrf_clock_control_lf_on() invokes
onoff_request() invokes
lfclk_start() triggers NRF_CLOCK_TASK_LFCLKSTART then
z_nrf_clock_control_lf_on() invokes lfclk_spinwait()

Nothing on that path appears to disables interrupts, so theoretically the EVENT_LFCLKSTARTED could have been cleared by clock_event_check_and_clean() in nrf_power_clock_isr() before the subsequent lfclk_spinwait() gets control and does disable interrupt, expecting to be able to see that event itself.

What am I missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing on that path appears to disables interrupts

driver initialization is called from z_cstart which has interrupts disabled.

I have added support to spinwaiting from thread context and added test for that.

@nordic-krch nordic-krch force-pushed the clock_stability branch 2 times, most recently from 8f59953 to 9a817bd Compare August 10, 2020 06:55
@carlescufi carlescufi added the DNM This PR should not be merged (Do Not Merge) label Aug 12, 2020
@carlescufi
Copy link
Member

DNM until #27422 is merged

@pabigot pabigot self-requested a review August 24, 2020 14:13
Copy link
Contributor

@pabigot pabigot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching from comment to block because we've lost momentum and I don't want this concern to be missed.

#27398 (comment)

@nordic-krch nordic-krch force-pushed the clock_stability branch 2 times, most recently from 694b393 to 38458e6 Compare September 1, 2020 07:15
@nordic-krch nordic-krch removed the DNM This PR should not be merged (Do Not Merge) label Sep 1, 2020
@nordic-krch
Copy link
Contributor Author

Upmerged since #27422 got merged. Removed DNM.

@pabigot pabigot dismissed their stale review September 1, 2020 15:48

Question answered.

@pabigot
Copy link
Contributor

pabigot commented Sep 2, 2020

Should this be tagged for 2.4.0? @carlescufi

Copy link
Contributor

@pabigot pabigot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see the logical operators used for boolean expressions, since we're going that way for MISRA. That's the only request changes. Otherwise this looks fine by inspection.

I get failures on drivers.clock.nrf_lf_clock_start_xtal_* variants on nrf52840dk_nrf52840 running sanitycheck with --device-testing. For *=available the failure mode is that it appears that configuration doesn't output anything so the test times out, and it always fails under sanity check but passes manually. This may be a race condition specific to the test infrastructure.

I got one failure with *=no_wait:

tirzah[765]$ cat sanity-out/nrf52840dk_nrf52840/tests/drivers/clock_control/nrf_lf_clock_start/drivers.clock.nrf_lf_clock_start_xtal_no_wait/handler.log
CLOCK_CONTROL_NRF_K32SRC=XTAL
SYSTEM_CLOCK_NO_WAIT=y
SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY=n
SYSTEM_CLOCK_WAIT_FOR_STABILITY=n
Running test suite test_nrf_lf_clock_start
===================================================================
START - test_clock_check
PASS - test_clock_check
===================================================================
O	MhFE: SPSEL in thread mode does not indicate PSP
ASSERTION FAIL [esf != ((void *)0)] @ WEST_TOPDIR/zephyr/arch/arm/core/aarch32/cortex_m/fault.c:955
ESF could not be retrieved successfully. Shall never occur.
E: ***** HARD FAULT *****
E:   Fault escalation (see below)
E: ***** BUS FAULT *****
E:   Imprecise data bus error
E: r0/a1:  0x00000004  r1/a2:  0x000003bb  r2/a3:  0x00000001
E: r3/a4:  0x00000000 r12/ip:  0x00000000 r14/lr:  0x00001d71
E:  xpsr:  0x61000005
E: Faulting instruction address (r15/pc): 0x00005880
E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
E: Fault during interrupt handling
E: Current thread: 0x20000240 (main)
E: Halting system

@@ -427,17 +426,64 @@ static void lfclk_spinwait(nrf_clock_lfclk_t t)
{
nrf_clock_domain_t d = NRF_CLOCK_DOMAIN_LFCLK;
nrf_clock_lfclk_t type;
static const bool lfxo_target =
IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be || since the operands and result are essentially boolean.

Same in other locations (isr_mode next definition)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

zassert_false(on, "Clock should be off");
} else if (IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY)) {
bool is_running =
rtc_cnt | (on && (type == NRF_CLOCK_LFCLK_RC));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so for essential type this should be (rtc_cnt != 0) || (on ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

on = nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_LFCLK, &type);
k_busy_wait(100);
rtc_cnt = k_cycle_get_32();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be open to this patch at this point in the code:

--- a/tests/drivers/clock_control/nrf_lf_clock_start/src/main.c
+++ b/tests/drivers/clock_control/nrf_lf_clock_start/src/main.c
@@ -98,6 +98,18 @@ void test_main(void)
        k_busy_wait(100);
        rtc_cnt = k_cycle_get_32();
 
+       TC_PRINT("CLOCK_CONTROL_NRF_K32SRC=%s\n",
+                IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC) ? "RC"
+                : IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH) ? "SYNTH"
+                : IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL) ? "XTAL"
+                : "???");
+       TC_PRINT("SYSTEM_CLOCK_NO_WAIT=%c\n",
+                IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT) ? 'y' : 'n');
+       TC_PRINT("SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY=%c\n",
+                IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY) ? 'y' : 'n');
+       TC_PRINT("SYSTEM_CLOCK_WAIT_FOR_STABILITY=%c\n",
+                IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_STABILITY) ? 'y' : 'n');
+
        ztest_test_suite(test_nrf_lf_clock_start,
                ztest_unit_test(test_clock_check),
                ztest_unit_test(test_wait_in_thread)

This produces the following in the handler.log which is helpful when trying to correlate the build tags with the configuration:

CLOCK_CONTROL_NRF_K32SRC=SYNTH
SYSTEM_CLOCK_NO_WAIT=n
SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY=n
SYSTEM_CLOCK_WAIT_FOR_STABILITY=y
Running test suite test_nrf_lf_clock_start

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, added.

@carlescufi
Copy link
Member

@andyross could you please take a look so we can merge this in time for 2.4.0?

@PerMac
Copy link
Member

PerMac commented Sep 9, 2020

Running on this PR solves the problem with test_kernel_systicks on nrf9160dk_nrf9160. However, it introduces an error for nrf5340dk_nrf5340_cpuapp: after flashing the board hangs, and the test from tests/portability/cmsis_rtos_v1 ends with a timeout.

@nordic-krch
Copy link
Contributor Author

@PerMac thanks for running it on that PR, i will look into nrf53 issue then.

@carlescufi carlescufi added the bug The issue is a bug, or the PR is fixing a bug label Sep 9, 2020
@nordic-krch
Copy link
Contributor Author

nrf53 is fixed by #28121

@carlescufi carlescufi changed the title Add system clock stability policy nRF: Add system clock stability policy Sep 9, 2020
@carlescufi
Copy link
Member

No complaints about the code. But is this really a good candidate for a global API? Right now it's just the one platform that needs to care about this. Maybe we should start this out as an internal thing with the nRF timer driver and promote the kconfig API to a global one only later?

We have restricted it to the scope of the nRF timer for now, and after the 2.4 release we will consider expanding this to the rest of platforms.

@carlescufi
Copy link
Member

@anangl please take a look

@@ -463,13 +510,20 @@ void z_nrf_clock_control_lf_on(enum nrf_lfclk_start_mode start_mode)
__ASSERT_NO_MSG(err >= 0);
}

/* In case of simulated board leave immediately. */
if (IS_ENABLED(CONFIG_BOARD_NRF52_BSIM)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this check more generic and consistent with what is used in the Bluetooth controller:

Suggested change
if (IS_ENABLED(CONFIG_BOARD_NRF52_BSIM)) {
if (IS_ENABLED(CONFIG_SOC_SERIES_BSIM_NRFXX)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

while (!(nrfx_clock_is_running(d, (void *)&type) && (type == t))) {
/* empty */
while (!(nrfx_clock_is_running(d, (void *)&type)
&& ((type == t) || (type == CLOCK_CONTROL_NRF_K32SRC)))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work for CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_LOW_SWING and CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_FULL_SWING, as type will be NRF_CLOCK_LFCLK_Xtal then.

I'd propose to correct it and simplify a bit the logic used here as follows.
First, to change the function signature to:

static void lfclk_spinwait(enum nrf_lfclk_start_mode start_mode)

then instead of lfxo_target use something like:

	nrf_clock_lfclk_t target_type =
		/* For sources XTAL, EXT_LOW_SWING, and EXT_FULL_SWING,
		 * NRF_CLOCK_LFCLK_Xtal is returned as the type of running clock.
		 */
		(IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL) ||
		 IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_LOW_SWING) ||
		 IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_FULL_SWING))
		? NRF_CLOCK_LFCLK_Xtal
		: CLOCK_CONTROL_NRF_K32SRC;

and then use here:

	while (!(nrfx_clock_is_running(d, (void *)&type)
		 && ((type == target_type)
		     || (mode == NRF_LFCLK_START_MODE_SPINWAIT_AVAILABLE))) {

and below:

		if (target_type == NRF_CLOCK_LFCLK_Xtal
		    && (nrf_clock_lf_src_get(NRF_CLOCK) == NRF_CLOCK_LFCLK_RC)
		    && nrf_clock_event_check(NRF_CLOCK,
		    ...

In the switch in z_nrf_clock_control_lf_on() we'll have then:

	case NRF_LFCLK_START_MODE_SPINWAIT_STABLE:
	case NRF_LFCLK_START_MODE_SPINWAIT_AVAILABLE:
		lfclk_spinwait(mode);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice suggestion. Done.

Comment on lines 39 to 43
enum nrf_lfclk_start_mode {
NRF_LFCLK_START_MODE_NOWAIT,
NRF_LFCLK_START_MODE_SPINWAIT_RUNNING,
NRF_LFCLK_START_MODE_SPINWAIT_AVAILABLE,
NRF_LFCLK_START_MODE_SPINWAIT_STABLE,
};
Copy link
Member

@anangl anangl Sep 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use other prefixes here? I know, CLOCK_CONTROL_NRF_ is lengthy, but the current one is not consistent with the other stuff defined in this file.
(It's probably not something to be corrected in this PR, just spotted it here).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to CLOCK_CONTROL_NRF_LF_START_[STABLE, AVAILABLE,NOWAIT]

Added configuration for approach to starting system clock source.
There are 3 options: no wait, wait untill available, wait until
stable.

Added support for those modes in clock control driver which handles
low frequency source clock.

Signed-off-by: Krzysztof Chruscinski <[email protected]>
@nordic-krch nordic-krch force-pushed the clock_stability branch 2 times, most recently from 4ed3453 to 1df5f57 Compare September 10, 2020 14:52
Copy link
Member

@anangl anangl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. One unnecessary comment could be removed.

Comment on lines 521 to 522
case CLOCK_CONTROL_NRF_LF_START_AVAILABLE:
/* fall through. */
case CLOCK_CONTROL_NRF_LF_START_STABLE:
Copy link
Member

@anangl anangl Sep 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment here is not needed. There is no code between those two cases, so there will be no warning here. It's not a "true fall through". ;-)

Enabled going to idle when waiting for low frequency clock.
Added 2 stages of starting LF clock when XTAL is used. First
stage is starting RC and then when it is ready XTAL is started.
It is done to get event/interrupt when RC is ready which means
that LF clock is available (but not stable).

Signed-off-by: Krzysztof Chruscinski <[email protected]>
Added test which verifies various modes of waiting for system clock
(no wait, available, stable) for different clock configurations (xtal,
rc, synth).

Signed-off-by: Krzysztof Chruscinski <[email protected]>
@nordic-krch
Copy link
Contributor Author

@carlescufi since this is now nordic only maybe i could be merged.

@carlescufi carlescufi merged commit 96b6da9 into zephyrproject-rtos:master Sep 10, 2020
tejlmand added a commit to tejlmand/nrfxlib that referenced this pull request Sep 23, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

Signed-off-by: Torsten Rasmussen <[email protected]>
tejlmand added a commit to tejlmand/nrfxlib that referenced this pull request Sep 23, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

Signed-off-by: Torsten Rasmussen <[email protected]>
tejlmand added a commit to tejlmand/nrfxlib that referenced this pull request Sep 29, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

Signed-off-by: Torsten Rasmussen <[email protected]>
tejlmand added a commit to tejlmand/nrfxlib that referenced this pull request Oct 1, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

Signed-off-by: Torsten Rasmussen <[email protected]>
tejlmand added a commit to tejlmand/nrfxlib that referenced this pull request Oct 2, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

- softdevice_controller: Mark 2M and Coded PHY as supported

  These helper configs were introduced in upstream zephyr.

Signed-off-by: Torsten Rasmussen <[email protected]>
Signed-off-by: Rubin Gerritsen <[email protected]>
tejlmand added a commit to tejlmand/nrfxlib that referenced this pull request Oct 6, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

- softdevice_controller: Mark 2M and Coded PHY as supported

  These helper configs were introduced in upstream zephyr.

Signed-off-by: Torsten Rasmussen <[email protected]>
Signed-off-by: Rubin Gerritsen <[email protected]>
mbolivar-nordic pushed a commit to nrfconnect/sdk-nrfxlib that referenced this pull request Oct 6, 2020
- nrf_security: update mbedtls heap to const struct device

  Zephyr upmerge introduces device bindings const struct as part of:
  zephyrproject-rtos/zephyr#24873

  This const'ify mbedtls_heap.c init function.

- mpls: Added `select MULTITHREADING_LOCK` to Kconfig

  With the changes related to:
  nrfconnect/sdk-nrf#2861
  zephyrproject-rtos/zephyr#27398

  The mpsl clock control is no longer needed, but mpsl still requires
  MULTITHREADING_LOCK, and is therefore moved to its right location.

- softdevice_controller: Mark 2M and Coded PHY as supported

  These helper configs were introduced in upstream zephyr.

Signed-off-by: Torsten Rasmussen <[email protected]>
Signed-off-by: Rubin Gerritsen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: API Changes to public APIs area: Clock Control area: Tests Issues related to a particular existing or missing test area: Timer Timer bug The issue is a bug, or the PR is fixing a bug platform: nRF Nordic nRFx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

test_kernel_systicks from tests/portability/cmsis_rtos_v1 fails on nrf platforms RFC: Require system clock stability on startup
7 participants