mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
197 lines
5.4 KiB
C
197 lines
5.4 KiB
C
/*
|
|
* Copyright (C) 2018 Gunar Schorcht
|
|
*
|
|
* 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 cpu_esp32
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief ETS timer to ztimer mapper
|
|
*
|
|
* @author Gunar Schorcht <gunar@schorcht.net>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#define ENABLE_DEBUG 0
|
|
#include "debug.h"
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#include "esp_common.h"
|
|
#include "log.h"
|
|
|
|
#include "esp_attr.h"
|
|
#include "irq_arch.h"
|
|
#include "ztimer.h"
|
|
#include "timex.h"
|
|
|
|
#include "rom/ets_sys.h"
|
|
|
|
struct _ets_to_ztimer {
|
|
ETSTimer *ets_timer;
|
|
ztimer_t ztimer;
|
|
};
|
|
|
|
/* maximum number of ETS timer to ztimer mapper objects */
|
|
/* TODO tune the value */
|
|
#define ETS_TO_TIMER_NUM 40
|
|
|
|
/* table of ETS timer to ztimer mapper objects */
|
|
static struct _ets_to_ztimer _ets_to_ztimer_map[ETS_TO_TIMER_NUM] = {};
|
|
|
|
/**
|
|
* @brief Get the ETS timer to ztimer mapper object for the given timer.
|
|
*
|
|
* If there is no object, the function registers a new one and returns it.
|
|
* If there is no more object available, it returns NULL.
|
|
*
|
|
* @param pointer to the ETS timer
|
|
* @return pointer to the mapper object or NULL in case of error
|
|
*/
|
|
struct _ets_to_ztimer* _ets_to_ztimer_get(ETSTimer *timer)
|
|
{
|
|
/* search for an existing mapper object */
|
|
for (int i = 0; i < ETS_TO_TIMER_NUM; i++) {
|
|
if (_ets_to_ztimer_map[i].ets_timer == timer) {
|
|
return &_ets_to_ztimer_map[i];
|
|
}
|
|
}
|
|
/* search for a free mapper object */
|
|
for (int i = 0; i < ETS_TO_TIMER_NUM; i++) {
|
|
if (_ets_to_ztimer_map[i].ets_timer == NULL) {
|
|
_ets_to_ztimer_map[i].ets_timer = timer;
|
|
return &_ets_to_ztimer_map[i];
|
|
}
|
|
}
|
|
LOG_TAG_ERROR("esp_ztimer", "There is no free ETS timer to ztimer mapper "
|
|
"object available\n");
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief Free the ETS timer to ztimer mapper object for the given timer.
|
|
* @param pointer to the ETS timer
|
|
*/
|
|
void _ets_to_ztimer_free(ETSTimer *timer)
|
|
{
|
|
/* search for an existing mapper object */
|
|
for (int i = 0; i < ETS_TO_TIMER_NUM; i++) {
|
|
if (_ets_to_ztimer_map[i].ets_timer == timer) {
|
|
_ets_to_ztimer_map[i].ets_timer = NULL;
|
|
return;
|
|
}
|
|
}
|
|
DEBUG("%s There is no ETS timer to ztimer for ETS timer %p\n",
|
|
__func__, timer);
|
|
}
|
|
|
|
/* ztimer call back function, distributes ets_timer callbacks */
|
|
void IRAM_ATTR _ets_to_ztimer_callback (void *arg)
|
|
{
|
|
struct _ets_to_ztimer* e2xt = (struct _ets_to_ztimer*)arg;
|
|
|
|
assert(arg != NULL);
|
|
assert(e2xt->ets_timer != NULL);
|
|
|
|
irq_isr_enter();
|
|
|
|
/* if timer is periodic, start it again with period */
|
|
if (e2xt->ets_timer->timer_period) {
|
|
ets_timer_arm_us(e2xt->ets_timer, e2xt->ets_timer->timer_period, true);
|
|
}
|
|
/* execute the ets_timer callback function */
|
|
e2xt->ets_timer->timer_func(e2xt->ets_timer->timer_arg);
|
|
|
|
irq_isr_exit();
|
|
}
|
|
|
|
void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunc, void *parg)
|
|
{
|
|
DEBUG("%s timer=%p pfunc=%p parg=%p\n", __func__, ptimer, pfunc, parg);
|
|
|
|
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(ptimer);
|
|
|
|
assert(e2xt != NULL);
|
|
|
|
e2xt->ets_timer->timer_func = pfunc;
|
|
e2xt->ets_timer->timer_arg = parg;
|
|
|
|
e2xt->ztimer.callback = &_ets_to_ztimer_callback;
|
|
e2xt->ztimer.arg = (void*)e2xt;
|
|
}
|
|
|
|
void ets_timer_done(ETSTimer *ptimer)
|
|
{
|
|
DEBUG("%s timer=%p\n", __func__, ptimer);
|
|
|
|
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(ptimer);
|
|
|
|
assert(e2xt != NULL);
|
|
|
|
e2xt->ets_timer->timer_func = NULL;
|
|
e2xt->ets_timer->timer_arg = NULL;
|
|
}
|
|
|
|
void ets_timer_arm_us(ETSTimer *timer, uint32_t tmout, bool repeat)
|
|
{
|
|
DEBUG("%s timer=%p tmout=%"PRIu32" repeat=%d\n", __func__, timer, tmout, repeat);
|
|
|
|
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(timer);
|
|
|
|
assert(e2xt != NULL);
|
|
assert(e2xt->ztimer.callback != NULL);
|
|
|
|
tmout = (tmout + 500) / 1000;
|
|
uint32_t now = ztimer_set(ZTIMER_MSEC, &e2xt->ztimer, tmout);
|
|
|
|
/* Note: this is approximating the expiry time since for very short timeout
|
|
this might be set to a minimum value that guarantees the ISR
|
|
being executed */
|
|
e2xt->ets_timer->timer_expire = (now + tmout) * 1000;
|
|
e2xt->ets_timer->timer_period = repeat ? (tmout * 1000) : 0;
|
|
}
|
|
|
|
void ets_timer_arm(ETSTimer *timer, uint32_t tmout, bool repeat)
|
|
{
|
|
ets_timer_arm_us(timer, tmout * US_PER_MS, repeat);
|
|
}
|
|
|
|
void ets_timer_disarm(ETSTimer *timer)
|
|
{
|
|
DEBUG("%s timer=%p\n", __func__, timer);
|
|
|
|
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(timer);
|
|
|
|
assert(e2xt != NULL);
|
|
|
|
ztimer_remove(ZTIMER_MSEC, &e2xt->ztimer);
|
|
}
|
|
|
|
void ets_timer_init(void)
|
|
{
|
|
/* initialization is not necessary */
|
|
}
|
|
|
|
void ets_timer_deinit(void)
|
|
{
|
|
/* deinitialization is not necessary */
|
|
}
|
|
|
|
void os_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg)
|
|
__attribute__((alias("ets_timer_setfn")));
|
|
void os_timer_disarm(ETSTimer *ptimer)
|
|
__attribute__((alias("ets_timer_disarm")));
|
|
void os_timer_arm_us(ETSTimer *ptimer, uint32_t u_seconds, bool repeat_flag)
|
|
__attribute__((alias("ets_timer_arm_us")));
|
|
void os_timer_arm(ETSTimer *ptimer, uint32_t milliseconds, bool repeat_flag)
|
|
__attribute__((alias("ets_timer_arm")));
|
|
void os_timer_done(ETSTimer *ptimer)
|
|
__attribute__((alias("ets_timer_done")));
|