Skip to content
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

ztimer: fix required_pm_mode initialization #15911

Closed
wants to merge 3 commits into from

Conversation

vincent-d
Copy link
Member

Contribution description

This might be flawed, but from my understanding:

  • the required_pm_mode should be applied to the 'base' clock (i.e. the periph_timer or periph_rtt clock)
  • 'convert' clocks do not have pm requirement

This PR sets required_pm_mode on ZTIMER_USEC_BASE and ZTIMER_MSEC_BASE. Setting this field is also moved before those clocks are used as they can be used in ztimer_convert_frac_init().
I also changed 'convert' clocks init so they set their internal required_pm_mode to ZTIMER_CLOCK_NO_REQUIRED_PM_MODE instead of nothing (which makes it 0, thus blocking a power mode by error).

As a last minor change, I fixed the initialization of 'adjust' parameter for the ZTIMER_MSEC clock as the field was renamed.

Testing procedure

I tested with our main application and checked that pm was behaving as expected. Before this change, it could never go to sleep.

Vincent Dupont added 3 commits February 2, 2021 10:36
For ZTIMER_USEC and ZTIMER_MSEC, the required_pm_mode should be set on
the base clock (ZTIMER_USEC_BASE and ZTIMER_MSEC_BASE respectively) as
they represent the hardware clocks that have pm constraints.
convert and convert_frac clocks do not have om constraints, thus setting
their required_pm_mode to ZTIMER_CLOCK_NO_REQUIRED_PM_MODE.
adjust do not exist anymore and have been replaced by adjust_set and
adjust_sleep.
@vincent-d vincent-d added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: timers Area: timer subsystems labels Feb 2, 2021
@vincent-d vincent-d requested a review from maribu February 2, 2021 09:49
@kaspar030
Copy link
Contributor

@jue89 I think this change is valid, could you double check?

@jue89
Copy link
Contributor

jue89 commented Feb 2, 2021

Good catch! I never unblocked PM mode 0 before ... so this bug never showed up on my application.

Code-wise this looks good to me, too.
Unfortunately, I have no Board at hand, currently. I could test tomorrow on a samr30-xpro.

Furthermore, no board use CONFIG_ZTIMER_.*_ADJUST, no fixes required there as well.

@jue89 jue89 self-requested a review February 2, 2021 15:13
@kfessel
Copy link
Contributor

kfessel commented Feb 5, 2021

#15715 or this one has to be merged first the other has to be modified

my first impression is that #15715 should go first and this should modifie ZTIMER_SEC after rebase

also this PR should investigate if "ZTIMER_CLOCK_NO_REQUIRED_PM_MODE" is a good(safe) default

@kfessel
Copy link
Contributor

kfessel commented Feb 5, 2021

it is not ztimer(which scale ever) that needs a specific pm but its base timer there for the configuration value should be
(CONFIG_ZTIMER_RTT_REQUIRED_PM_MODE or CONFIG_ZTIMER_RTC_REQUIRED_PM_MODE)

@kfessel
Copy link
Contributor

kfessel commented Feb 5, 2021

I am also very fine with rebaseing and editing #15715 after this is merged. If this is faster.
The safe default investigation can be part of another PR. (pm is blocked by default therefor the basic default is safe until unblocked).
Maybe the change of the configuration logic even thoug this touches it should be part of an other PR.
I am not sure how to rename the ZTIMER_USEC_REQUIRED_PM_MODE maybe it is ZTIMER_TIM(ER0)_REQUIRED_PM_MODE

Copy link
Contributor

@jue89 jue89 left a comment

Choose a reason for hiding this comment

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

As advertised, I've tested this PR using the samr30-xpro. Sorry that this took so long ...

Power-savings are still achieved - so I'm fine with this PR. Just some minor suggestions.

Hacked-together test based on the hello-world example
diff --git a/examples/hello-world/Makefile b/examples/hello-world/Makefile
index 258d8e9baf..b72257d9ff 100644
--- a/examples/hello-world/Makefile
+++ b/examples/hello-world/Makefile
@@ -12,6 +12,16 @@ RIOTBASE ?= $(CURDIR)/../..
 # development process:
 DEVELHELP ?= 1
 
+USEMODULE += gnrc_netdev_default
+USEMODULE += auto_init_gnrc_netif
+
+USEMODULE += ztimer ztimer_usec ztimer_msec ztimer_periph_rtt ztimer_xtimer_compat
+USEMODULE += pm_layered
+
+CFLAGS += '-DCONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE=0'
+CFLAGS += '-DCONFIG_ZTIMER_USEC_REQUIRED_PM_MODE=1'
+CFLAGS += '-DPM_BLOCKER_INITIAL=0x00000000'
+
 # Change this to 0 show compiler invocation lines by default:
 QUIET ?= 1
 
diff --git a/examples/hello-world/main.c b/examples/hello-world/main.c
index f51bf8c0a0..fd915fb6b5 100644
--- a/examples/hello-world/main.c
+++ b/examples/hello-world/main.c
@@ -21,6 +21,14 @@
 
 #include <stdio.h>
 
+#include "net/netif.h"
+#include "ztimer.h"
+#include "timex.h"
+
+static void callback (void * arg) {
+       puts((char*) arg);
+}
+
 int main(void)
 {
     puts("Hello World!");
@@ -28,5 +36,20 @@ int main(void)
     printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
     printf("This board features a(n) %s MCU.\n", RIOT_MCU);
 
+    /* The SAM-R30 board boots with its netif enabled and draws several mA of current. */
+    /* Send it to sleep mode ... */
+    netif_t *iface = netif_iter(NULL);
+    netopt_state_t state = NETOPT_STATE_SLEEP;
+    netif_set_opt(iface, NETOPT_STATE, 0, &state, sizeof(netopt_state_t));
+
+    /* 1. Run a callback after 3s */
+    static ztimer_t cb_timer = {.callback = callback, .arg = "Hello World"};
+    ztimer_set(ZTIMER_USEC, &cb_timer, 3 * US_PER_SEC);
+
+    /* 2. Sleep the current thread for 60s */
+    ztimer_sleep(ZTIMER_MSEC, 60 * MS_PER_SEC);
+
+    while (true) {}
+
     return 0;
 }

Comment on lines +169 to +170
LOG_DEBUG("ztimer_init(): ZTIMER_MSEC setting adjust_sleep value to %i\n",
CONFIG_ZTIMER_USEC_ADJUST_SLEEP );
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
LOG_DEBUG("ztimer_init(): ZTIMER_MSEC setting adjust_sleep value to %i\n",
CONFIG_ZTIMER_USEC_ADJUST_SLEEP );
LOG_DEBUG("ztimer_init(): ZTIMER_MSEC setting adjust_sleep value to %i\n",
CONFIG_ZTIMER_USEC_ADJUST_SLEEP);

Comment on lines +114 to +118
# ifdef MODULE_PM_LAYERED
LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting required_pm_mode to %i\n",
CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE);
ZTIMER_USEC_BASE->required_pm_mode = CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE;
# endif
Copy link
Contributor

@jue89 jue89 Feb 8, 2021

Choose a reason for hiding this comment

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

This section can cause errors during compilation if CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE is configured with the wrongly typed value:

In file included from /home/jue/Projects/RIOT/sys/ztimer/auto_init.c:48:
/home/jue/Projects/RIOT/sys/ztimer/auto_init.c: In function 'ztimer_init':
/home/jue/Projects/RIOT/sys/ztimer/auto_init.c:115:15: error: format '%i' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Werror=format=]
  115 |     LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting required_pm_mode to %i\n",
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This happens, if I use the defines made by the cpu vendor.

I'd say the easy solution is to set ZTIMER_USEC_BASE->required_pm_mode and then print that value. If I'm familiar enough with GCC and clang this should fix casting issues due to implicit casting.

Suggested change
# ifdef MODULE_PM_LAYERED
LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting required_pm_mode to %i\n",
CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE);
ZTIMER_USEC_BASE->required_pm_mode = CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE;
# endif
# ifdef MODULE_PM_LAYERED
ZTIMER_USEC_BASE->required_pm_mode = CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE;
LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting required_pm_mode to "PRIu8"\n",
ZTIMER_USEC_BASE->required_pm_mode);
# endif

The same goes with the respective MSEC section.

What do you think?
Maybe @kaspar030 has an opinion on this, too?

Copy link
Member

Choose a reason for hiding this comment

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

If you apply this, please use the past tense in the debug message. (setting -> set)

@kfessel
Copy link
Contributor

kfessel commented Feb 9, 2021

@vincent-d: would you please check if current #15715 also fixes this.
I moved the PM_MODE configuration to the ZTIMER hardware bases.
basically I did what I wrote in my comments.

@fjmolinas
Copy link
Contributor

ping @vincent-d :)

@kfessel
Copy link
Contributor

kfessel commented Apr 4, 2021

@vincent-d: #16172 should have solved fix this.

@vincent-d
Copy link
Member Author

@kfessel sorry for the long delay. Indeed, it should fix the initialization order issue. But if I'm not mistaken, the convert clock pm mode is still not initialized, though.

@kfessel
Copy link
Contributor

kfessel commented Apr 14, 2021

@vincent-d: I think we don't need to init the convert_clocks (highlevel like *SEC) pm_mode_block if we init the base clocks (rtt timer or rtc) pm_mode_block

@maribu
Copy link
Member

maribu commented Apr 14, 2021

I also changed 'convert' clocks init so they set their internal required_pm_mode to ZTIMER_CLOCK_NO_REQUIRED_PM_MODE instead of nothing (which makes it 0, thus blocking a power mode by error).

This makes a lot of sense to me. I didn't check to confirm that this does actually cause issues. But IMO purely virtual clocks should use ZTIMER_CLOCK_NO_REQUIRED_PM_MODE just because this is the most sensible value there - so even if there is currently no code relying on their value being sensible.

@maribu
Copy link
Member

maribu commented Apr 14, 2021

@vincent-d: Care to rebase and update?

@kfessel
Copy link
Contributor

kfessel commented Apr 14, 2021

ztimer/convert.c
ztimer/convert_frac.c
ztimer/convert_muldiv64.c
ztimer/convert_shift.c

need their init fuctions

super.super.block_pm_mode = ZTIMER_CLOCK_NO_REQUIRED_PM_MODE,

it just worked cause i never activated pm_mode 0

@fjmolinas
Copy link
Contributor

Any updates here?

@fjmolinas
Copy link
Contributor

ztimer/convert.c
ztimer/convert_frac.c
ztimer/convert_muldiv64.c
ztimer/convert_shift.c

need their init fuctions

super.super.block_pm_mode = ZTIMER_CLOCK_NO_REQUIRED_PM_MODE,

it just worked cause i never activated pm_mode 0

@kfessel can you provide a patch for what you identified is missing here?

@kfessel
Copy link
Contributor

kfessel commented Jun 18, 2021

see #16573

@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 22, 2021
@fjmolinas
Copy link
Contributor

see #16573

This PR is now addressed with #16573 being in.

@fjmolinas fjmolinas closed this Jun 28, 2021
@fjmolinas fjmolinas removed this from the Release 2021.07 milestone Jun 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: timers Area: timer subsystems CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants