1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/ztimer/mock.c
2023-05-02 09:53:16 +02:00

174 lines
4.7 KiB
C

/*
* Copyright (C) 2018 Eistec AB
* 2020 Kaspar Schleiser <kaspar@schleiser.de>
* 2020 Freie Universität Berlin
* 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 sys_ztimer_mock
*
* @{
*
* @file
* @brief ztimer mock implementation
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @}
*/
#include <stdint.h>
#include <inttypes.h>
#include "assert.h"
#include "ztimer/mock.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/* Functions for controlling the mock clock below */
void ztimer_mock_advance(ztimer_mock_t *self, uint32_t val)
{
DEBUG(
"zmock_advance: start now=0x%08" PRIx32 " + 0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->now, val, self->target, self->armed);
while (val) {
uint32_t step =
self->armed ? (self->target < val ? self->target : val) : val;
DEBUG(
"zmock_advance: step now=0x%08" PRIx32 " + 0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->now, step, self->target, self->armed);
self->now = (self->now + step) & self->mask;
if (self->armed) {
/* Update target */
if (step >= self->target) {
/* Target was hit */
ztimer_mock_fire(self);
}
else {
self->target -= step;
}
}
val -= step;
}
DEBUG(
"zmock_advance: done now=0x%08" PRIx32 " + 0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->now, val, self->target, self->armed);
}
void ztimer_mock_jump(ztimer_mock_t *self, uint32_t target)
{
self->now = target & self->mask;
DEBUG("zmock_jump: now=0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->now, self->target, self->armed);
/* Do not touch target */
}
void ztimer_mock_fire(ztimer_mock_t *self)
{
DEBUG("zmock_fire: now=0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->now, self->target, self->armed);
self->target = 0;
self->armed = 0;
/* Execute ztimer core interrupt handler */
ztimer_handler(&self->super);
}
/* Implementations for the standard ztimer operations below */
static void ztimer_mock_op_set(ztimer_clock_t *clock, uint32_t val)
{
ztimer_mock_t *self = (ztimer_mock_t *)clock;
assert(self->running == 1);
++self->calls.set;
self->target = val & self->mask;
self->armed = 1;
DEBUG(
"zmock_set: %3u now=0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->calls.set, self->now, self->target, self->armed);
}
static uint32_t ztimer_mock_op_now(ztimer_clock_t *clock)
{
ztimer_mock_t *self = (ztimer_mock_t *)clock;
++self->calls.now;
DEBUG(
"zmock_now: %3u now=0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->calls.now, self->now, self->target, self->armed);
return self->now;
}
static void ztimer_mock_op_cancel(ztimer_clock_t *clock)
{
ztimer_mock_t *self = (ztimer_mock_t *)clock;
assert(self->running == 1);
++self->calls.cancel;
DEBUG(
"zmock_cancel: %3u now=0x%08" PRIx32 ", target=0x%08" PRIx32 " (%u)\n",
self->calls.cancel, self->now, self->target, self->armed);
self->armed = 0;
}
#if MODULE_ZTIMER_ONDEMAND
static void ztimer_mock_op_start(ztimer_clock_t *clock)
{
ztimer_mock_t *self = (ztimer_mock_t *)clock;
++self->calls.start;
DEBUG("zmock_start: %3u\n", self->calls.start);
self->running = 1;
}
static void ztimer_mock_op_stop(ztimer_clock_t *clock)
{
ztimer_mock_t *self = (ztimer_mock_t *)clock;
assert(self->armed == 0);
++self->calls.stop;
DEBUG("zmock_stop: %3u\n", self->calls.stop);
self->running = 0;
}
#endif
static const ztimer_ops_t ztimer_mock_ops = {
.set = ztimer_mock_op_set,
.now = ztimer_mock_op_now,
.cancel = ztimer_mock_op_cancel,
#if MODULE_ZTIMER_ONDEMAND
.start = ztimer_mock_op_start,
.stop = ztimer_mock_op_stop,
#endif
};
void ztimer_mock_init(ztimer_mock_t *self, unsigned width)
{
uint32_t max_value = (~((uint32_t)0ul)) >> (32 - width);
*self = (ztimer_mock_t){
.mask = max_value,
.super = { .ops = &ztimer_mock_ops, .max_value = max_value },
};
#if !MODULE_ZTIMER_ONDEMAND
/* turn the timer on by default if ondemand feature is not used */
self->running = 1;
#endif
DEBUG("zmock_init: %p width=%u mask=0x%08" PRIx32 " running=%u\n", (void *)self, width,
self->mask, self->running);
if (max_value < UINT32_MAX) {
self->super.ops->set(&self->super, self->super.max_value >> 1);
}
}