1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #16172 from kfessel/p-zimer-sec

sys/ztimer: add ZTIMER_SEC, improve auto_init
This commit is contained in:
Francisco 2021-04-02 08:32:38 +02:00 committed by GitHub
commit 9d1d2f9e21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 442 additions and 81 deletions

View File

@ -53,6 +53,19 @@ static void _native_rtc_cb(void *arg) {
_native_rtc_alarm_callback = NULL;
}
/* RIOT does not expect DST or TZ information */
static void _remove_struct_tm_extra( struct tm * t ){
struct tm tmp = {.tm_year = t->tm_year,
.tm_mon = t->tm_mon,
.tm_mday = t->tm_mday,
.tm_hour = t->tm_hour,
.tm_min = t->tm_min,
.tm_sec = t->tm_sec,
.tm_wday = t->tm_wday
};
*t = tmp;
}
void rtc_init(void)
{
DEBUG("rtc_init\n");
@ -115,8 +128,14 @@ int rtc_set_time(struct tm *ttime)
warnx("rtc_set_time: not powered on");
return -1;
}
/* ensure there is no accidental extra information */
struct tm itime = *ttime;
_remove_struct_tm_extra(&itime);
/* mktime() and localtime are only inverse functions if tm_isdst == -1 */
itime.tm_isdst = -1;
time_t tnew = mktime(&itime);
time_t tnew = mktime(ttime);
if (tnew == -1) {
warnx("rtc_set_time: out of time_t range");
return -1;
@ -154,6 +173,9 @@ int rtc_get_time(struct tm *ttime)
}
_native_syscall_leave();
/* RIOT does not handle DST or TZ information */
_remove_struct_tm_extra(ttime);
return 0;
}
@ -171,7 +193,13 @@ int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
struct tm now;
rtc_get_time(&now);
time_t tdiff_secs = mktime(time) - mktime(&now);
/* ensure there is no accidental extra information */
struct tm intime = *time;
_remove_struct_tm_extra(&intime);
/* tm_idst are ignored for these mktime calls since
* both times carry the same (00) timezone information */
time_t tdiff_secs = mktime(&intime) - mktime(&now);
if (_native_rtc_alarm_callback) {
xtimer_remove(&_native_rtc_timer);

View File

@ -182,12 +182,20 @@
*
* For now, there are:
*
* ZTIMER_USEC: clock providing microsecond ticks
* ZTIMER_USEC: clock providing microsecond ticks, always uses a basic timer
* (ztimer_periph_timer)
*
* ZTIMER_MSEC: clock providing millisecond ticks, using a low power timer if
* available on the platform
* ZTIMER_MSEC: clock providing millisecond ticks, using a low power timer
* (ztimer_periph_rtt) if it is available on the platform
* and it running at 1kHz or above else it uses the same
* basic timer as ZTIMER_USEC does.
*
* ZTIMER_SEC: clock providing second time, possibly using epoch semantics
* ZTIMER_SEC: clock providing second time, possibly using epoch semantics,
* it will use a low power timer (ztimer_periph_rtt)
* if it is available on the platform alternately it uses
* ztimer_periph_rtc if it is available and configured
* if if these are missing it will use same basic timer
* as ZTIMER_USEC does.
*
* These pointers are defined in `ztimer.h` and can be used like this:
*
@ -595,6 +603,11 @@ extern ztimer_clock_t *const ZTIMER_USEC;
*/
extern ztimer_clock_t *const ZTIMER_MSEC;
/**
* @brief Default ztimer second clock
*/
extern ztimer_clock_t *const ZTIMER_SEC;
/**
* @brief Base ztimer for the microsecond clock (ZTIMER_USEC)
*

View File

@ -104,17 +104,36 @@ extern "C" {
#endif /* MODULE_ZTIMER_PERIPH_RTT */
/**
* @brief The minimum pm mode required for ZTIMER_USEC to run.
* @brief The minimum pm mode required for ZTIMER_TIMER to run.
*/
#ifndef CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE
#define CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE ZTIMER_CLOCK_NO_REQUIRED_PM_MODE
#ifndef CONFIG_ZTIMER_TIMER_BLOCK_PM_MODE
# ifdef CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE
# define CONFIG_ZTIMER_TIMER_BLOCK_PM_MODE CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE
# else
# define CONFIG_ZTIMER_TIMER_BLOCK_PM_MODE ZTIMER_CLOCK_NO_REQUIRED_PM_MODE
# endif
#endif
/**
* @brief The minimum pm mode required for ZTIMER_MSEC to run
* @brief The minimum pm mode required for ZTIMER_RTT to run
*/
#ifndef CONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE
#define CONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE ZTIMER_CLOCK_NO_REQUIRED_PM_MODE
#ifndef CONFIG_ZTIMER_RTT_BLOCK_PM_MODE
# ifdef CONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE
# define CONFIG_ZTIMER_RTT_BLOCK_PM_MODE CONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE
# else
# define CONFIG_ZTIMER_RTT_BLOCK_PM_MODE ZTIMER_CLOCK_NO_REQUIRED_PM_MODE
# endif
#endif
/**
* @brief The minimum pm mode required for ZTIMER_RTC to run
*/
#ifndef CONFIG_ZTIMER_RTC_BLOCK_PM_MODE
# ifdef CONFIG_ZTIMER_SEC_REQUIRED_PM_MODE
# define CONFIG_ZTIMER_RTC_BLOCK_PM_MODE CONFIG_ZTIMER_SEC_REQUIRED_PM_MODE
# else
# define CONFIG_ZTIMER_RTC_BLOCK_PM_MODE ZTIMER_CLOCK_NO_REQUIRED_PM_MODE
# endif
#endif
#ifdef __cplusplus

View File

@ -51,6 +51,10 @@ config MODULE_ZTIMER_MSEC
bool "Milliseconds"
depends on MODULE_ZTIMER_PERIPH_TIMER || MODULE_ZTIMER_PERIPH_RTT
config MODULE_ZTIMER_SEC
bool "Seconds"
depends on MODULE_ZTIMER_PERIPH_TIMER || MODULE_ZTIMER_PERIPH_RTT || MODULE_ZTIMER_PERIPH_RTC
endmenu # Clocks

View File

@ -66,6 +66,10 @@ ifneq (,$(filter ztimer_periph_timer,$(USEMODULE)))
FEATURES_REQUIRED += periph_timer
endif
ifneq (,$(filter ztimer_periph_rtc,$(USEMODULE)))
FEATURES_REQUIRED += periph_rtc
endif
ifneq (,$(filter ztimer_periph_rtt,$(USEMODULE)))
FEATURES_REQUIRED += periph_rtt
endif

View File

@ -36,6 +36,9 @@
* @}
*/
#include "kernel_defines.h"
#if IS_USED(MODULE_AUTO_INIT_ZTIMER)
#include "board.h"
#include "ztimer.h"
#include "ztimer/convert_frac.h"
@ -43,6 +46,7 @@
#include "ztimer/convert_muldiv64.h"
#include "ztimer/periph_timer.h"
#include "ztimer/periph_rtt.h"
#include "ztimer/periph_rtc.h"
#include "ztimer/config.h"
#include "log.h"
@ -52,78 +56,216 @@
#define FREQ_1MHZ 1000000LU
#define FREQ_250KHZ 250000LU
#define FREQ_1KHZ 1000LU
#define FREQ_1HZ 1LU
/* Step 0: define available ztimer-periphery by activated modules */
/* #if CONFIG_ZTIMER_USEC_TYPE_PERIPH_TIMER
* replaces #if MODULE_ZTIMER_PERIPH_TIMER
* the ztimer_periph_timer is always available
* having an (1) config defined in ztimer/config.h
*/
#if CONFIG_ZTIMER_USEC_TYPE_PERIPH_TIMER
# define ZTIMER_TIMER _ztimer_periph_timer
# define ZTIMER_TIMER_CLK _ztimer_periph_timer.super
# define ZTIMER_TIMER_FREQ CONFIG_ZTIMER_USEC_BASE_FREQ
#endif
#if MODULE_ZTIMER_PERIPH_RTT
# define ZTIMER_RTT _ztimer_periph_timer_rtt
# define ZTIMER_RTT_CLK _ztimer_periph_timer_rtt
# define ZTIMER_RTT_FREQ RTT_FREQUENCY
#endif
#if MODULE_ZTIMER_PERIPH_RTC
# define ZTIMER_RTC _ztimer_periph_timer_rtc
# define ZTIMER_RTC_CLK _ztimer_periph_timer_rtc
# define ZTIMER_RTC_FREQ FREQ_1HZ
#endif
/* Step 1: select which periphery to use for the higher level ZTIMER_*SEC
* selected periphery is marked for initialisation (INIT_ZTIMER_<periph>
* prepare defines for ztimer initialization
*/
/* ZTIMER_USEC always uses the basic timer
* basic timer is available on all boards */
#if MODULE_ZTIMER_USEC
# if CONFIG_ZTIMER_USEC_TYPE_PERIPH_TIMER
static ztimer_periph_timer_t _ztimer_periph_timer_usec = {
# ifndef INIT_ZTIMER_TIMER
# define INIT_ZTIMER_TIMER 1
# endif
#endif
/* ZTIMER_MSEC prefers ZTIMER_RTT (ztimer_periph_rtt)
* if it is available and runs at a frequency > 1kHz
* if not it falls back to use the basic timer */
#if MODULE_ZTIMER_MSEC
# if defined(ZTIMER_RTT) && ZTIMER_RTT_FREQ >= FREQ_1KHZ
# define ZTIMER_MSEC_RTT 1
# ifndef INIT_ZTIMER_RTT
# define INIT_ZTIMER_RTT 1
# endif
# if ZTIMER_RTT_FREQ != FREQ_1KHZ
# define ZTIMER_MSEC_CONVERT_LOWER_FREQ ZTIMER_RTT_FREQ
# endif
# else
# define ZTIMER_MSEC_TIMER 1
# ifndef INIT_ZTIMER_TIMER
# define INIT_ZTIMER_TIMER 1
# endif
# define ZTIMER_MSEC_CONVERT_LOWER_FREQ ZTIMER_TIMER_FREQ
# endif
#endif
/* ZTIMER_SEC prefers ZTIMER_RTT (ztimer_periph_rtt) if it is available
* if not it prefers ZTIMER_RTC (ztimer_periph_rtc) if it is available
* if not it falls back to use the basic timer */
#if MODULE_ZTIMER_SEC
# ifdef ZTIMER_RTT
# define ZTIMER_SEC_RTT
# ifndef INIT_ZTIMER_RTT
# define INIT_ZTIMER_RTT 1
# endif
# define ZTIMER_SEC_CONVERT_LOWER_FREQ ZTIMER_RTT_FREQ
# else
# ifdef ZTIMER_RTC
# define ZTIMER_SEC_RTC
# ifndef INIT_ZTIMER_RTC
# define INIT_ZTIMER_RTC 1
# endif
# else
# define ZTIMER_SEC_TIMER
# ifndef INIT_ZTIMER_TIMER
# define INIT_ZTIMER_TIMER 1
# endif
# define ZTIMER_SEC_CONVERT_LOWER_FREQ ZTIMER_TIMER_FREQ
# endif
# endif
#endif
/* Step 2: setup static memory for used ztimer-periphery */
#if INIT_ZTIMER_TIMER
static ztimer_periph_timer_t ZTIMER_TIMER = {
.min = CONFIG_ZTIMER_USEC_MIN
};
#endif
ztimer_clock_t *const ZTIMER_USEC_BASE = &_ztimer_periph_timer_usec.super;
# if CONFIG_ZTIMER_USEC_BASE_FREQ == FREQ_1MHZ
ztimer_clock_t *const ZTIMER_USEC = &_ztimer_periph_timer_usec.super;
# elif CONFIG_ZTIMER_USEC_BASE_FREQ == 250000LU
#if INIT_ZTIMER_RTT
static ztimer_periph_rtt_t ZTIMER_RTT;
#endif
#if INIT_ZTIMER_RTC
static ztimer_periph_rtc_t ZTIMER_RTC;
#endif
/* Step 3: setup constants for ztimers and memory for converters */
#if MODULE_ZTIMER_USEC
# ifdef ZTIMER_TIMER
ztimer_clock_t *const ZTIMER_USEC_BASE = &ZTIMER_TIMER_CLK;
# else
# error No suitable ZTIMER_USEC config. Basic timer configuration missing?
# endif
# if ZTIMER_TIMER_FREQ == FREQ_1MHZ
ztimer_clock_t *const ZTIMER_USEC = &ZTIMER_TIMER_CLK;
# elif ZTIMER_TIMER_FREQ == 250000LU
static ztimer_convert_shift_t _ztimer_convert_shift_usec;
ztimer_clock_t *const ZTIMER_USEC = &_ztimer_convert_shift_usec.super.super;
# else
# else
static ztimer_convert_frac_t _ztimer_convert_frac_usec;
ztimer_clock_t *const ZTIMER_USEC = &_ztimer_convert_frac_usec.super.super;
# endif
# else
# error ztimer_usec selected, but no configuration available!
# endif
#endif
#if MODULE_ZTIMER_MSEC
# if MODULE_ZTIMER_PERIPH_RTT
static ztimer_periph_rtt_t _ztimer_periph_timer_rtt_msec;
ztimer_clock_t *const ZTIMER_MSEC_BASE = &_ztimer_periph_timer_rtt_msec;
# define ZTIMER_RTT_INIT (ZTIMER_MSEC_BASE)
# if RTT_FREQUENCY != FREQ_1KHZ
static ztimer_convert_frac_t _ztimer_convert_frac_msec;
ztimer_clock_t *const ZTIMER_MSEC = &_ztimer_convert_frac_msec.super.super;
# define ZTIMER_MSEC_CONVERT_LOWER_FREQ RTT_FREQUENCY
# define ZTIMER_MSEC_CONVERT_LOWER (&_ztimer_periph_timer_rtt_msec)
# else
ztimer_clock_t *const ZTIMER_MSEC = &_ztimer_periph_timer_rtt_msec;
# endif
# elif MODULE_ZTIMER_USEC
static ztimer_convert_frac_t _ztimer_convert_frac_msec;
ztimer_clock_t *const ZTIMER_MSEC = &_ztimer_convert_frac_msec.super.super;
ztimer_clock_t *const ZTIMER_MSEC_BASE = &_ztimer_periph_timer_usec.super;
# define ZTIMER_MSEC_CONVERT_LOWER ZTIMER_USEC_BASE
# define ZTIMER_MSEC_CONVERT_LOWER_FREQ CONFIG_ZTIMER_USEC_BASE_FREQ
# ifdef ZTIMER_MSEC_RTT
ztimer_clock_t *const ZTIMER_MSEC_BASE = &ZTIMER_RTT_CLK;
# elif defined(ZTIMER_MSEC_TIMER)
ztimer_clock_t *const ZTIMER_MSEC_BASE = &ZTIMER_TIMER_CLK;
# else
# error No suitable ZTIMER_MSEC config. Maybe add USEMODULE += ztimer_usec?
# error No suitable ZTIMER_MSEC config. No rtt or basic timer?
# endif
# ifdef ZTIMER_MSEC_CONVERT_LOWER_FREQ
static ztimer_convert_frac_t _ztimer_convert_frac_msec;
ztimer_clock_t *const ZTIMER_MSEC = &_ztimer_convert_frac_msec.super.super;
# else
ztimer_clock_t *const ZTIMER_MSEC = &ZTIMER_RTT_CLK;
# endif
#endif
#if MODULE_ZTIMER_SEC
# ifdef ZTIMER_SEC_RTC
ztimer_clock_t *const ZTIMER_SEC_BASE = &ZTIMER_RTC_CLK;
ztimer_clock_t *const ZTIMER_SEC = &ZTIMER_RTC_CLK;
# elif defined(ZTIMER_SEC_RTT)
ztimer_clock_t *const ZTIMER_SEC_BASE = &ZTIMER_RTT_CLK;
# elif defined(ZTIMER_SEC_TIMER)
ztimer_clock_t *const ZTIMER_SEC_BASE = &ZTIMER_TIMER_CLK;
# else
# error No suitable ZTIMER_SEC config. No rtc, rtt or basic timer?
# endif
# ifdef ZTIMER_SEC_CONVERT_LOWER_FREQ
static ztimer_convert_frac_t _ztimer_convert_frac_sec;
ztimer_clock_t *const ZTIMER_SEC = &_ztimer_convert_frac_sec.super.super;
# endif
#endif
void ztimer_init(void)
{
#if MODULE_ZTIMER_USEC
# if CONFIG_ZTIMER_USEC_TYPE_PERIPH_TIMER
/* Step 4: initialize used ztimer-periphery */
#if INIT_ZTIMER_TIMER
LOG_DEBUG(
"ztimer_init(): ZTIMER_USEC using periph timer %u, freq %lu, width %u\n",
"ztimer_init(): ZTIMER_TIMER using periph timer %u, freq %lu, width %u\n",
CONFIG_ZTIMER_USEC_DEV, CONFIG_ZTIMER_USEC_BASE_FREQ,
CONFIG_ZTIMER_USEC_WIDTH);
ztimer_periph_timer_init(&_ztimer_periph_timer_usec, CONFIG_ZTIMER_USEC_DEV,
CONFIG_ZTIMER_USEC_BASE_FREQ,
WIDTH_TO_MAXVAL(CONFIG_ZTIMER_USEC_WIDTH));
ztimer_periph_timer_init(&ZTIMER_TIMER, CONFIG_ZTIMER_USEC_DEV,
ZTIMER_TIMER_FREQ, WIDTH_TO_MAXVAL(CONFIG_ZTIMER_USEC_WIDTH));
# ifdef MODULE_PM_LAYERED
LOG_DEBUG("ztimer_init(): ZTIMER_TIMER setting required_pm_mode to %i\n",
CONFIG_ZTIMER_TIMER_BLOCK_PM_MODE);
ZTIMER_TIMER_CLK.required_pm_mode = CONFIG_ZTIMER_TIMER_BLOCK_PM_MODE;
# endif
# if CONFIG_ZTIMER_USEC_BASE_FREQ != FREQ_1MHZ
# if CONFIG_ZTIMER_USEC_BASE_FREQ == FREQ_250KHZ
#endif
#if INIT_ZTIMER_RTT
LOG_DEBUG("ztimer_init(): initializing rtt\n");
ztimer_periph_rtt_init(&ZTIMER_RTT);
# ifdef MODULE_PM_LAYERED
LOG_DEBUG("ztimer_init(): ZTIMER_RTT setting required_pm_mode to %i\n",
CONFIG_ZTIMER_RTT_BLOCK_PM_MODE);
ZTIMER_RTT_CLK.required_pm_mode = CONFIG_ZTIMER_RTT_BLOCK_PM_MODE;
# endif
#endif
#if INIT_ZTIMER_RTC
LOG_DEBUG("ztimer_init(): initializing rtc\n");
ztimer_periph_rtc_init(&ZTIMER_RTC);
# ifdef MODULE_PM_LAYERED
LOG_DEBUG("ztimer_init(): ZTIMER_RTC setting required_pm_mode to %i\n",
CONFIG_ZTIMER_RTC_BLOCK_PM_MODE);
ZTIMER_RTC_CLK.required_pm_mode = CONFIG_ZTIMER_RTC_BLOCK_PM_MODE;
# endif
#endif
/* Step 5: initialize ztimers requested */
#if MODULE_ZTIMER_USEC
# if ZTIMER_TIMER_FREQ != FREQ_1MHZ
# if ZTIMER_TIMER_FREQ == FREQ_250KHZ
LOG_DEBUG("ztimer_init(): ZTIMER_USEC convert_shift %lu to 1000000\n",
CONFIG_ZTIMER_USEC_BASE_FREQ);
ZTIMER_TIMER_FREQ);
ztimer_convert_shift_up_init(&_ztimer_convert_shift_usec,
&_ztimer_periph_timer_usec.super, 2);
ZTIMER_USEC_BASE, 2);
# else
LOG_DEBUG("ztimer_init(): ZTIMER_USEC convert_frac %lu to 1000000\n",
CONFIG_ZTIMER_USEC_BASE_FREQ);
ztimer_convert_frac_init(&_ztimer_convert_frac_usec,
&_ztimer_periph_timer_usec.super,
FREQ_1MHZ, CONFIG_ZTIMER_USEC_BASE_FREQ);
ZTIMER_TIMER_FREQ);
ztimer_convert_frac_init(&_ztimer_convert_frac_usec, ZTIMER_USEC_BASE,
FREQ_1MHZ, ZTIMER_TIMER_FREQ);
# endif
# else
LOG_DEBUG("ztimer_init(): ZTIMER_USEC without conversion\n");
# endif
# ifdef CONFIG_ZTIMER_USEC_ADJUST_SET
LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting adjust_set value to %i\n",
@ -135,24 +277,13 @@ void ztimer_init(void)
CONFIG_ZTIMER_USEC_ADJUST_SLEEP );
ZTIMER_USEC->adjust_sleep = CONFIG_ZTIMER_USEC_ADJUST_SLEEP;
# endif
# 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->required_pm_mode = CONFIG_ZTIMER_USEC_REQUIRED_PM_MODE;
# endif
#endif
#ifdef ZTIMER_RTT_INIT
LOG_DEBUG("ztimer_init(): initializing rtt\n");
ztimer_periph_rtt_init(ZTIMER_RTT_INIT);
#endif
#if MODULE_ZTIMER_MSEC
# if ZTIMER_MSEC_CONVERT_LOWER_FREQ
LOG_DEBUG("ztimer_init(): ZTIMER_MSEC convert_frac from %lu to 1000\n",
(long unsigned)ZTIMER_MSEC_CONVERT_LOWER_FREQ);
ztimer_convert_frac_init(&_ztimer_convert_frac_msec,
ZTIMER_MSEC_CONVERT_LOWER,
ztimer_convert_frac_init(&_ztimer_convert_frac_msec, ZTIMER_MSEC_BASE,
FREQ_1KHZ, ZTIMER_MSEC_CONVERT_LOWER_FREQ);
# endif
# ifdef CONFIG_ZTIMER_MSEC_ADJUST
@ -160,10 +291,15 @@ void ztimer_init(void)
CONFIG_ZTIMER_MSEC_ADJUST);
ZTIMER_MSEC->adjust = CONFIG_ZTIMER_MSEC_ADJUST;
# endif
# ifdef MODULE_PM_LAYERED
LOG_DEBUG("ztimer_init(): ZTIMER_MSEC setting required_pm_mode to %i\n",
CONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE);
ZTIMER_MSEC->required_pm_mode = CONFIG_ZTIMER_MSEC_REQUIRED_PM_MODE;
#endif
#if MODULE_ZTIMER_SEC
# if ZTIMER_SEC_CONVERT_LOWER_FREQ
LOG_DEBUG("ztimer_init(): ZTIMER_SEC convert_frac from %lu to 1\n",
(long unsigned)ZTIMER_SEC_CONVERT_LOWER_FREQ);
ztimer_convert_frac_init(&_ztimer_convert_frac_sec, ZTIMER_SEC_BASE,
FREQ_1HZ, ZTIMER_SEC_CONVERT_LOWER_FREQ);
# endif
#endif
}
#endif /* IS_USED(MODULE_AUTO_INIT_ZTIMER) */

View File

@ -35,6 +35,9 @@
static uint32_t _gmt_civil_to_timestamp(unsigned y, unsigned m, unsigned d,
unsigned h, unsigned mi, unsigned s)
{
/* struct tm counts months from 0 to 11 */
m += 1;
if (m <= 2) {
y -= 1;
m += 12;
@ -43,7 +46,7 @@ static uint32_t _gmt_civil_to_timestamp(unsigned y, unsigned m, unsigned d,
719561) * 86400 + 3600 * h + 60 * mi + s;
}
void _timestamp_to_gmt_civil(struct tm *_tm, uint32_t epoch)
static void _timestamp_to_gmt_civil(struct tm *_tm, uint32_t epoch)
{
uint32_t s = epoch % 86400;
@ -71,6 +74,9 @@ void _timestamp_to_gmt_civil(struct tm *_tm, uint32_t epoch)
.tm_hour = h, .tm_min = m, .tm_sec = s };
*_tm = tmp;
}
/* struct tm counts months starting from 0 */
_tm->tm_mon -= 1;
}
static void _ztimer_periph_rtc_callback(void *arg)
@ -82,7 +88,7 @@ static uint32_t _ztimer_periph_rtc_now(ztimer_clock_t *clock)
{
(void)clock;
struct tm time;
struct tm time = { .tm_year = 0 };
rtc_get_time(&time);
@ -104,7 +110,7 @@ static void _ztimer_periph_rtc_set(ztimer_clock_t *clock, uint32_t val)
target = now + val;
struct tm _tm;
struct tm _tm = { .tm_year = 0 };
_timestamp_to_gmt_civil(&_tm, target);
/* TODO: ensure this doesn't underflow */

View File

@ -5,4 +5,7 @@ USEMODULE += ztimer_usec
# uncomment this to test using ztimer msec on rtt
#USEMODULE += ztimer_msec ztimer_periph_rtt
# uncomment this to test using ztimer sec on rtc
#USEMODULE += ztimer_sec ztimer_periph_rtc
include $(RIOTBASE)/Makefile.include

View File

@ -31,7 +31,10 @@
#include "test_utils/expect.h"
#ifdef MODULE_ZTIMER_MSEC
#ifdef MODULE_ZTIMER_SEC
#define ZTIMER ZTIMER_SEC
#define TICKS_PER_SEC 1
#elif MODULE_ZTIMER_MSEC
#define ZTIMER ZTIMER_MSEC
#define TICKS_PER_SEC MS_PER_SEC
#else
@ -71,11 +74,14 @@ void *timer_thread(void *arg)
msg_receive(&m);
struct timer_msg *tmsg = m.content.ptr;
uint32_t now = ztimer_now(ZTIMER);
printf("now=%lu:%lu -> every %lu.%lus: %s\n",
(now / TICKS_PER_SEC),
(now % TICKS_PER_SEC),
tmsg->interval / TICKS_PER_SEC,
tmsg->interval % TICKS_PER_SEC,
/* casts are needed to solve for sometimes TICKS_PER_SEC being UL
* result of / and % of uint32_t will always fit into uint32_t
*/
printf("now=%"PRIu32":%"PRIu32" -> every %"PRIu32".%"PRIu32"s: %s\n",
(uint32_t)(now / TICKS_PER_SEC),
(uint32_t)(now % TICKS_PER_SEC),
(uint32_t)(tmsg->interval / TICKS_PER_SEC),
(uint32_t)(tmsg->interval % TICKS_PER_SEC),
tmsg->text);
tmsg->msg.type = 12345;

View File

@ -12,6 +12,10 @@ ifeq ($(TEST_ZTIMER_CLOCK), ZTIMER_MSEC)
KCONFIG_ADD_CONFIG += $(APPDIR)/app.config.msec.test
endif
endif
ifeq ($(TEST_ZTIMER_CLOCK), ZTIMER_SEC)
USEMODULE += ztimer_sec
USEMODULE += ztimer_periph_rtc
endif
CFLAGS += -DTEST_ZTIMER_CLOCK=$(TEST_ZTIMER_CLOCK)

View File

@ -0,0 +1,8 @@
include ../Makefile.tests_common
USEMODULE += ztimer
USEMODULE += ztimer_usec
USEMODULE += ztimer_msec
USEMODULE += ztimer_sec
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,11 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini\
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \
#

View File

@ -0,0 +1,12 @@
# Introduction
This application tests the high abstraction level ztimer clocks usec, msec and sec
by locking three mutexes and waiting for them to
be unlocked by ZTIMER_USEC, ZTIMER_MSEC and ZTIMER_SEC
The tests succeeds if the board running the test does not get stuck.
ZTIMER_MSEC and ZTIMER_SEC will be configured following the rules described
in the ztimer documentation (one may want to use extra ztimer_perih_*).
Timing information is provided for human analysis it is not checked by automatic
testing, since they are system and runtime dependent, there are other tests
that (partially) cover the accuracy of timers.

View File

@ -0,0 +1,7 @@
# this file enables modules defined in Kconfig. Do not use this file for
# application configuration. This is only needed during migration.
CONFIG_MODULE_ZTIMER=y
CONFIG_MODULE_ZTIMER_PERIPH_TIMER=y
CONFIG_MODULE_ZTIMER_USEC=y
CONFIG_MODULE_ZTIMER_MSEC=y
CONFIG_MODULE_ZTIMER_SEC=y

77
tests/ztimer_xsec/main.c Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2021 TUBA Freiberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief high level ztimer test application
*
* @author Karl Fessel <karl.fessel@ovgu.de>
*
*
* @}
*/
#include <stdio.h>
#include "ztimer.h"
#include "mutex.h"
/* only header information is used we do not need to use MODULE_TIMEX */
#include "timex.h"
typedef struct named_lock {
char *name;
mutex_t mut;
uint32_t release_time;
} named_lock_t;
void release(void *arg);
static named_lock_t sec_lock = { .name = "SEC", .mut = MUTEX_INIT_LOCKED };
static named_lock_t msec_lock = { .name = "MSEC", .mut = MUTEX_INIT_LOCKED };
static named_lock_t usec_lock = { .name = "USEC", .mut = MUTEX_INIT_LOCKED };
static ztimer_t sec_tim = { .callback = release, .arg = &sec_lock };
static ztimer_t msec_tim = { .callback = release, .arg = &msec_lock };
static ztimer_t usec_tim = { .callback = release, .arg = &usec_lock };
void release(void *arg)
{
named_lock_t *e = arg;
e->release_time = (uint32_t)ztimer_now(ZTIMER_USEC);
puts(e->name);
mutex_unlock(&e->mut);
}
int main(void)
{
puts("starting ztimers");
/* start a timer on each high level ztimer*/
ztimer_set(ZTIMER_SEC, &sec_tim, 1);
ztimer_set(ZTIMER_MSEC, &msec_tim, 200);
ztimer_set(ZTIMER_USEC, &usec_tim, 100 * US_PER_MS);
printf("time %s:\t%" PRIu32 "\n", "Wait", (uint32_t)ztimer_now(ZTIMER_USEC));
puts("waiting for locks");
/* wait for mutexes */
mutex_lock(&sec_lock.mut);
mutex_lock(&msec_lock.mut);
mutex_lock(&usec_lock.mut);
printf("time %s:\t%" PRIu32 "\n", sec_lock.name, sec_lock.release_time);
printf("time %s:\t%" PRIu32 "\n", msec_lock.name, msec_lock.release_time);
printf("time %s:\t%" PRIu32 "\n", usec_lock.name, usec_lock.release_time);
printf("SUCCESS!\n");
return 0;
}

View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
# Copyright (C) 2021 TUBA Freiberg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
import sys
from testrunner import run
def testfunc(child):
child.expect_exact("starting ztimers")
child.expect_exact("waiting for locks")
child.expect_exact("USEC")
child.expect_exact("MSEC")
child.expect_exact("SEC")
child.expect_exact("SUCCESS!")
if __name__ == "__main__":
sys.exit(run(testfunc))