1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/openwsn/contrib/sctimer_ztimer.c
Francisco Molina 844ccfbeb3
pkg/OpenWSN: initial import
Co-authored-by: Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
Co-authored-by: Jose Alamos <jose.alamos@haw-hamburg.de>
Co-authored-by: Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
2020-06-30 13:08:36 +02:00

164 lines
5.0 KiB
C

/*
* Copyright (C) 2020 Inria
*
* 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 pkg_openwsn
* @{
*
* @file
* @brief Ztimer based adaptation of "sctimer" bsp module
*
* For details on the implementation check pkg/openwsn/doc.txt
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#include "sctimer.h"
#include "debugpins.h"
#include "ztimer.h"
#include "ztimer/convert.h"
#include "ztimer/convert_frac.h"
#include "ztimer/convert_shift.h"
#include "ztimer/config.h"
#include "periph_conf.h"
#define LOG_LEVEL LOG_NONE
#include "log.h"
/**
* @brief Maximum counter difference to not consider an ISR late, this
* should account for the largest timer interval OpenWSN
* scheduler might work with. When running only the stack this
* should not be more than SLOT_DURATION, but when using cjoin
* it is 65535ms
*/
#ifndef SCTIMER_LOOP_THRESHOLD
#define SCTIMER_LOOP_THRESHOLD (2 * PORT_TICS_PER_MS * 65535)
#endif
#if CONFIG_ZTIMER_MSEC_BASE_FREQ > 32768U
static ztimer_convert_frac_t _ztimer_convert_frac_32768;
#define ZTIMER_32768_CONVERT_LOWER_FREQ CONFIG_ZTIMER_MSEC_BASE_FREQ
#define ZTIMER_32768_CONVERT_LOWER (ZTIMER_MSEC_BASE)
/* cppcheck-suppress preprocessorErrorDirective
* (reason: cppcheck fails to see that CONFIG_ZTIMER_MSEC_BASE_FREQ
* is set in ztimer/config.h to a non zero value */
#elif (CONFIG_ZTIMER_MSEC_BASE_FREQ < 32768U) && \
((32768U % CONFIG_ZTIMER_MSEC_BASE_FREQ) == 0)
static ztimer_convert_shift_t _ztimer_convert_shift_32768;
#define ZTIMER_32768_CONVERT_HIGHER_FREQ CONFIG_ZTIMER_MSEC_BASE_FREQ
#define ZTIMER_32768_CONVERT_HIGHER (ZTIMER_MSEC_BASE)
#elif (CONFIG_ZTIMER_MSEC_BASE_FREQ < 32768U) && \
((32768U % CONFIG_ZTIMER_MSEC_BASE_FREQ) != 0)
#error No suitable ZTIMER_MSEC_BASE config. Maybe add USEMODULE += ztimer_usec?
#endif
static sctimer_cbt _sctimer_cb;
static ztimer_t _ztimer_sctimer;
static ztimer_clock_t *ZTIMER_32768 = NULL;
static void sctimer_isr_internal(void *arg)
{
(void)arg;
if (_sctimer_cb != NULL) {
debugpins_isr_set();
_sctimer_cb();
debugpins_isr_clr();
}
}
void sctimer_init(void)
{
#if CONFIG_ZTIMER_MSEC_BASE_FREQ > 32768U
ZTIMER_32768 = &_ztimer_convert_frac_32768.super.super;
/* cppcheck-suppress preprocessorErrorDirective
* (reason: cppcheck fails to see that CONFIG_ZTIMER_MSEC_BASE_FREQ
* is set in ztimer/config.h to a non zero value */
#elif (CONFIG_ZTIMER_MSEC_BASE_FREQ < 32768U) && \
(32768U % CONFIG_ZTIMER_MSEC_BASE_FREQ == 0)
ZTIMER_32768 = &_ztimer_convert_shift_32768.super.super;
#elif CONFIG_ZTIMER_MSEC_BASE_FREQ == 32768U
ZTIMER_32768 = ZTIMER_MSEC_BASE;
#else
#error Invalid ZTIMER_MSEC_BASE_FREQ config. Maybe add USEMODULE += ztimer_usec?
#endif
#if defined(ZTIMER_32768_CONVERT_LOWER)
LOG_DEBUG("[sctimer]: ZTIMER_32768 convert_frac from %lu to 32768\n",
(long unsigned)ZTIMER_32768_CONVERT_LOWER_FREQ);
ztimer_convert_frac_init(&_ztimer_convert_frac_32768,
ZTIMER_32768_CONVERT_LOWER,
SCTIMER_FREQUENCY,
ZTIMER_32768_CONVERT_LOWER_FREQ);
#elif defined(ZTIMER_32768_CONVERT_HIGHER)
LOG_DEBUG("[sctimer]: ZTIMER_32768 convert_shift %lu to 32768\n",
(long unsigned)ZTIMER_32768_CONVERT_HIGHER_FREQ);
ztimer_convert_shift_up_init(&_ztimer_convert_shift_32768,
ZTIMER_32768_CONVERT_HIGHER,
__builtin_ctz(SCTIMER_FREQUENCY /
CONFIG_ZTIMER_MSEC_BASE_FREQ));
#endif
_ztimer_sctimer.callback = sctimer_isr_internal;
}
void sctimer_set_callback(sctimer_cbt cb)
{
_sctimer_cb = cb;
}
void sctimer_setCompare(uint32_t val)
{
unsigned state = irq_disable();
uint32_t now = ztimer_now(ZTIMER_32768);
/* if the next compare value (isr) to schedule is already later than
the required value, but close enough to think we have been slow
in scheduling it, trigger the ISR right away */
if (now > val) {
if (now - val < SCTIMER_LOOP_THRESHOLD) {
ztimer_set(ZTIMER_32768, &_ztimer_sctimer, 0);
}
else {
ztimer_set(ZTIMER_32768, &_ztimer_sctimer,
UINT32_MAX - now + val);
}
}
else {
ztimer_set(ZTIMER_32768, &_ztimer_sctimer, val - now);
}
irq_restore(state);
LOG_DEBUG("[sctimer]: set cb to %" PRIu32 " at %" PRIu32 "\n",
val, now);
}
uint32_t sctimer_readCounter(void)
{
uint32_t now = ztimer_now(ZTIMER_32768);
LOG_DEBUG("[sctimer]: now %" PRIu32 "\n", now);
return now;
}
void sctimer_enable(void)
{
/* not supported, sctimer does not control RTT or ztimer */
}
void sctimer_disable(void)
{
/* not supported, sctimer does not control RTT or ztimer */
}