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

sys/ztimer/Makefilde.dep: periph_rtt as FEATURES_OPTIONAL #14013

Closed
wants to merge 1 commit into from

Conversation

fjmolinas
Copy link
Contributor

Contribution description

If ztimer_msec is used include periph_rtt as an optional features,
and if used include ztimer_periph_rtt.

This is based on the expectation that you want ZTIMER_MSEC to run in sleep mode.

Testing procedure

  • boards not providing rtt don't include ztimer_periph_rtt
BOARD=nucleo-l152re USEMODULE=ztimer_msec make -C examples/hello-world/ --no-print-directory info-modules | grep rtt
  • boards providing it do
BOARD=nucleo-l073rz USEMODULE=ztimer_msec make -C examples/hello-world/ --no-print-directory info-modules | grep rtt
periph_init_rtt
periph_rtt
ztimer_periph_rtt

If ztimer_msec is used include periph_rtt as an optional feature,
and if used include ztimer_periph_rtt.
@fjmolinas fjmolinas added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: sys Area: System labels May 4, 2020
@kaspar030
Copy link
Contributor

I think I didn't make this a global default because some RTT cannot do 1000/1024 HZ. IIRC, some are glued to e.g., 1Hz. So I left it to be set in the board or cpu Makefile.dep.

@fjmolinas
Copy link
Contributor Author

I think I didn't make this a global default because some RTT cannot do 1000/1024 HZ. IIRC, some are glued to e.g., 1Hz. So I left it to be set in the board or cpu Makefile.dep.

Ok, that is true, so it needs RTT_FREQUENCY to be configurable, another reason for me to keep working on that.

@jue89
Copy link
Contributor

jue89 commented May 4, 2020

Another thought: To gain any power saving benefit by sourcing ZTIMER_MSEC from periph_rtt, the board must also specify CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE (introduced in #13722) to block and unblock the right pm mode. So some explicit configuration must take place anyhow.

@jue89
Copy link
Contributor

jue89 commented May 7, 2020

FYI: In #14031 I'm adding ztimer_periph_rtt if ztimer_msec ist used. Thus, ztimer_msec is based on the RTT for this board.

@fjmolinas
Copy link
Contributor Author

I think there is a question here on whether you always want periph_rtt for ztimer_msec, this does not seem that clear to me anymore.

@jue89
Copy link
Contributor

jue89 commented Jun 30, 2020

I think there is a question here on whether you always want periph_rtt for ztimer_msec, this does not seem that clear to me anymore.

I came to the conclusion that this is at least a good default. A timer system based on periph_rtt allows for easy power management, that just works.

@fjmolinas
Copy link
Contributor Author

I think there is a question here on whether you always want periph_rtt for ztimer_msec, this does not seem that clear to me anymore.

I came to the conclusion that this is at least a good default. A timer system based on periph_rtt allows for easy power management, that just works.

Depends on the platform, for sam0 there are 180us delays on every read/write to rtt, this adds up fast, and could lead to +-1ms offsets, this might break applications, and therefore you might not want to use rtt as your timer source.

@maribu
Copy link
Member

maribu commented Sep 15, 2020

Gentle reminder ;-)

@fjmolinas
Copy link
Contributor Author

Gentle reminder ;-)

I don't think there was a conclusion here, I kind of contested my own PR hahhaha.

@jue89
Copy link
Contributor

jue89 commented Sep 17, 2020

After thinking some time about it, I would recommend to handle this at board-level. (Or cpu-level?)
Some boards are predestined for battery applications, some aren't. So we can pull-in ztimer_periph_rtt if ztimer_msec ist used.

This reminds me of fixing #14031 ;)

@fjmolinas
Copy link
Contributor Author

After thinking some time about it, I would recommend to handle this at board-level. (Or cpu-level?)
Some boards are predestined for battery applications, some aren't. So we can pull-in ztimer_periph_rtt if ztimer_msec ist used.

I'm still unsure about this because of #14013 (comment), 180us can be waaaay too much for some applications.

@jue89
Copy link
Contributor

jue89 commented Sep 17, 2020

I'm still unsure about this because of #14013 (comment), 180us can be waaaay too much for some applications.

Are you thinking of a certain application, which would break? (I'm asking bc we are actually living with that high delay.)

@fjmolinas
Copy link
Contributor Author

Are you thinking of a certain application, which would break? (I'm asking bc we are actually living with that high delay.)

I was using this for TSCH, and it was severely hindering the performance.

@maribu
Copy link
Member

maribu commented Sep 17, 2020

Depends on the platform, for sam0 there are 180us delays on every read/write to rtt, this adds up fast, and could lead to +-1ms offsets, this might break applications, and therefore you might not want to use rtt as your timer source.

IMO ± MAX(TICK_DURATION_OF_VIRTUAL_CLOCK, TICK_DURATION_OF_UNDERLYING_CLOCK) is what you have to expect as lower bound of accuracy. In case of ZTIMER_MSEC, you should expect, thus, at least ± 1ms IMO. (As lower bound I mean that even with optimal fine tuning, no load on the system, etc. you don't get reproducible better than that. I don't want to say that it is impossible to occasionally get better by chance.)

Also note that we don't expect the millisecond clock to be used for short running timers. And for long running timers the RTT likely has the lower clock drift - so even in scenarios that don't care about power consumption using the RTT for long running timers might be the better option.

@maribu
Copy link
Member

maribu commented Sep 17, 2020

One good argument against is ROM consumption.

@fjmolinas
Copy link
Contributor Author

IMO ± MAX(TICK_DURATION_OF_VIRTUAL_CLOCK, TICK_DURATION_OF_UNDERLYING_CLOCK) is what you have to expect as lower bound of accuracy. In case of ZTIMER_MSEC, you should expect, thus, at least ± 1ms IMO. (As lower bound I mean that even with optimal fine tuning, no load on the system, etc. you don't get reproducible better than that. I don't want to say that it is impossible to occasionally get better by chance.)

Ok makes sense, to be fair in my case I was using the RTT but setting a 32Khz based ZTIMER,. So I'm convinced.

@fjmolinas
Copy link
Contributor Author

Ok makes sense, to be fair in my case I was using the RTT but setting a 32Khz based ZTIMER,. So I'm convinced.

So the remaining question is BOARD based approach or enable globally. We could filter by cpu that would not be able to do msec, from the top of my mind the only one is kinetis.

@kaspar030
Copy link
Contributor

So the remaining question is BOARD based approach or enable globally. We could filter by cpu that would not be able to do msec, from the top of my mind the only one is kinetis.

I think we need compile time information about the RTT's capability ("can it do 1-32khz?"). So it might be most suitable to model this as feature, e.g., "periph_rtt_32khz".

@fjmolinas
Copy link
Contributor Author

Reposting from #16334 (comment)

This issue had also been tackled in #14013, but came to the same issues.

I thought for RTT we should have features exposing 1Khz, 32Khz capabilities, maybe more later as needed. So FEATURES_PROVIDED += periph_rtt_1khz FEATURES_PROVIDED += periph_rtt_32khz. In most cases, the underlying clock is 32Khz except for espandatmega. The trouble with the later is that it depends on the actual clock backend, so I think it's easier to model this as capabilities instead of the actual clock speed. So maybe ztimer_rtt_32khandztimer_rtt_1khzare more fitting since it will only mean I can get an1khz or 32khz ztimer_rttfrom myperiph_rtt. And in all cases where RTT_FREQUENCY` is higher than the target frequency, this can be achieved, and if it's lower, it can if the target frequency is power2 of the actual frequency.

But then how to configure it? So far it's compile-time, so conflict between configurations should be caught, for OpenWSN I set the highest possible speed, and for a lot of platforms, I made the RTT_FREQUENCY configurable and add RTT_MAX_FREQUENCY. Is there any reason to not set the max frequency as the default frequency?

So to summarize:

  • ztimer_rtt_32kh and ztimer_rtt_1khz features
  • set RTT_FREQUENCY to RTT_MAX_FREQUENCY if ztimer_rtt_32kh and ztimer_rtt_1khz are used, with CFLAGS.

@maribu
Copy link
Member

maribu commented Apr 16, 2021

Note 32.000 kHz crystals do exist, while most boards actually use 32.768 kHz crystals.

Also note that the feature is not really ztimer specific. How about calling the features

periph_rtt_1000hz, periph_rtt_1024hz, periph_rtt_32768hz, and periph_rtt_32000hz?

This would be especially useful for ztimer, as periph_rtt_1000hz would requires no frequency conversion, periph_rtt_32000hz could use shifting for frequency conversion, while the other two have to use frac for conversion.

@jue89
Copy link
Contributor

jue89 commented Apr 16, 2021

As stated in #16334 - I would do the following (haven't tried - just an idea):

  • if ztimer_msec is used, pull in ztimer_periph_rtt and ztimer_periph_timer, so both modules are compiled.
  • once ztimer/auto_init.c is compiled, the pre-processor selects one of them based on RTT_FREQUENCY. This is already implemented: https://github.com/RIOT-OS/RIOT/blob/master/sys/ztimer/auto_init.c#L103-L119
  • only one backend gets initialized (i.e. symbols of that backend are called)
  • the linker throws out the unused backend

Pro: ztimer_msec can always be used - no matter what has been configured in the board.h or periph_conf.h. I think this is very important when RIOT core features like GNRC are migrated to ztimer_msec.

Con: One backend may be compiled without being used.

Modelling the RTT frequency as a feature doesn't scale, as @maribu already pointed out.

What do you think?

@fjmolinas
Copy link
Contributor Author

Note 32.000 kHz crystals do exist, while most boards actually use 32.768 kHz crystals.

Also note that the feature is not really ztimer specific. How about calling the features

periph_rtt_1000hz, periph_rtt_1024hz, periph_rtt_32768hz, and periph_rtt_32000hz?

This would be especially useful for ztimer, as periph_rtt_1000hz would requires no frequency conversion, periph_rtt_32000hz could use shifting for frequency conversion, while the other two have to use frac for conversion.

Sure. That makes sense as well, it will just need more though on how to translate used features to configuration of the RTT.

@fjmolinas
Copy link
Contributor Author

fjmolinas commented Apr 16, 2021

I find this not transparent, you see both modules getting pulled in, you think cool, I'm using RTT I'll have low power, and actually, because the default frequency for that BOARD is 1Hz, you are not.

@jue89
Copy link
Contributor

jue89 commented Apr 16, 2021

I find this not transparent, you see both modules getting pulled in, you think cool, I'm using RTT I'll have low power, and actually, because the default frequency for that BOARD is 1Hz, you are not.

How about displaying a warning, if ztimer_periph_rtt is not used?

@fjmolinas
Copy link
Contributor Author

This would be especially useful for ztimer, as periph_rtt_1000hz would require no frequency conversion, periph_rtt_32000hz could use shifting for frequency conversion, while the other two have to use frac for conversion.

I think we should probably list our goals then because there are a lot of mixed requirements.

The basic most important one is:

(1) use a low power timer backend when possible (so use ztimer_periph_rtt when possible)

PKG/Module needs:

(2) OpenWSN needs at least 30us resolution from the ztimer_rtt backend.

And because of different modules with conflicting or overlapping needs:

(3) solve different configuration requirements: e.g. OpenWSN wanting the highest resolution, all ztimer_msec users wanting only 1ms resolution (both can be achieved with conversion)

Then nice to have:

(4) configuring the timer backend in the most efficient way (no frequency conversion if needed, shifting over frac)

For this modeling with periph_rtt_1000hz periph_rtt_1024hz periph_rtt_32768hz periph_rtt_32000hz targets only (4), but it does not allow for cases like atmega and esp32 to say that they can provide a ztimer_ms on rtt without getting into scalability issues.

What other needs are there?

@fjmolinas
Copy link
Contributor Author

I find this not transparent, you see both modules getting pulled in, you think cool, I'm using RTT I'll have low power, and actually, because the default frequency for that BOARD is 1Hz, you are not.

How about displaying a warning, if ztimer_periph_rtt is not used?

I think this is a patch, but not a complete solution, since you don't know what's going to happen from the dependency resolution. But we could have this as a first step since its probably the fastest to get rolling (and it's kind of there anyway)

@fjmolinas
Copy link
Contributor Author

I think this is a patch, but not a complete solution, since you don't know what's going to happen from the dependency resolution. But we could have this as a first step since its probably the fastest to get rolling (and it's kind of there anyway)

A patch is not the right word here, It's a solution for the current situation and allows to simply add ztimer_periph_rtt to the build, but we still need to figure out the configuration of the RTT properly and handling overlapping/conflicting configurations.

What do you think?

It sound good as a first step.

@jue89
Copy link
Contributor

jue89 commented Apr 16, 2021

Once Kconfig is first citizen, one could configure RTT_FREQUENCY and Kconfig can select ztimer_periph_rtt or ztimer_periph_timer accordingly, if I understood Kconfig correctly?! Or am I expecting too much from Kconfig?

@fjmolinas
Copy link
Contributor Author

Once Kconfig is first citizen, one could configure RTT_FREQUENCY and Kconfig can select ztimer_periph_rtt or ztimer_periph_timer accordingly, if I understood Kconfig correctly?! Or am I expecting too much from Kconfig?

AFAIK dependencies are solved before configuration, and in this case RTT_FREQUENCY is a module configuration, it seems weird for a Module configuration to resolve some dependency, @leandrolanzieri.

@leandrolanzieri
Copy link
Contributor

Once Kconfig is first citizen, one could configure RTT_FREQUENCY and Kconfig can select ztimer_periph_rtt or ztimer_periph_timer accordingly, if I understood Kconfig correctly?! Or am I expecting too much from Kconfig?

AFAIK dependencies are solved before configuration, and in this case RTT_FREQUENCY is a module configuration, it seems weird for a Module configuration to resolve some dependency, @leandrolanzieri.

I did not look specifically at the details discussed here, but in Kconfig the symbols that represent configurations and modules are all evaluated at the same time. So if I understood correctly, it is possible to do something like:


config RTT_FREQUENCY
    int "RTT Frequency"
    default 1000  #  configurable or defined by hardware perhaps?

menuconfig ZTIMER
    bool "Ztimer"

if ZTIMER

config ZTIMER_PERIPH_TIMER
    bool "Ztimer periph Timer"
    default y if !ZTIMER_PERIPH_RTT

config ZTIMER_PERIPH_RTT
    bool "Ztimer periph RTT"
    default y
    depends on RTT_FREQUENCY >= 1000

endif

@leandrolanzieri
Copy link
Contributor

it seems weird for a Module configuration to resolve some dependency

I don't know if it is weird to depend on a given configuration of one module to be able to activate another that uses it. I agree it is something we are not used to do currently, as we split the dependency resolution and the configuration of modules into steps. But if we can get the whole picture simultaneously I may even allow to have more control and validation of configurations.

@fjmolinas fjmolinas requested review from kaspar030 and removed request for kaspar030 April 19, 2021 07:59
@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 22, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@fjmolinas
Copy link
Contributor Author

Superseded by #16553

@fjmolinas fjmolinas closed this Sep 10, 2021
@fjmolinas fjmolinas deleted the pr_ztimer_periph_rtt branch September 10, 2021 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: sys Area: System Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants