xtensa/esp32-s2: Adds support to rt_timer and systimer to ESP32-S2.

This commit is contained in:
Sara Souza 2021-09-17 19:13:51 -03:00 committed by Gustavo Henrique Nihei
parent 64e8322974
commit fba6fa2dc1
8 changed files with 2001 additions and 77 deletions

View File

@ -173,6 +173,7 @@ endchoice # On-board Crystal Frequency
config ESP32S2_RT_TIMER config ESP32S2_RT_TIMER
bool "Real-time Timer" bool "Real-time Timer"
select ESP32S2_TIMER
default n default n
config ESP32S2_PARTITION config ESP32S2_PARTITION

View File

@ -85,3 +85,7 @@ endif
ifeq ($(CONFIG_ESP32S2_FREERUN),y) ifeq ($(CONFIG_ESP32S2_FREERUN),y)
CHIP_CSRCS += esp32s2_freerun.c CHIP_CSRCS += esp32s2_freerun.c
endif endif
ifeq ($(CONFIG_ESP32S2_RT_TIMER),y)
CHIP_CSRCS += esp32s2_rt_timer.c
endif

View File

@ -0,0 +1,838 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/esp32s2_rt_timer.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this args for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/kthread.h>
#include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h>
#include "xtensa.h"
#include "xtensa_attr.h"
#include "hardware/esp32s2_soc.h"
#include "hardware/esp32s2_system.h"
#include "hardware/esp32s2_systimer.h"
#include "esp32s2_tim.h"
#include "esp32s2_rt_timer.h"
#include "esp32s2_clockconfig.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_SCHED_HPWORKPRIORITY
# if CONFIG_ESP32S2_RT_TIMER_TASK_PRIORITY >= CONFIG_SCHED_HPWORKPRIORITY
# error "RT timer priority should be smaller than high-prio workqueue"
# endif
#endif
#define RT_TIMER_TASK_NAME CONFIG_ESP32S2_RT_TIMER_TASK_NAME
#define RT_TIMER_TASK_PRIORITY CONFIG_ESP32S2_RT_TIMER_TASK_PRIORITY
#define RT_TIMER_TASK_STACK_SIZE CONFIG_ESP32S2_RT_TIMER_TASK_STACK_SIZE
/* Timer running at 80 MHz */
#define CYCLES_PER_USEC 80
#define USEC_TO_CYCLES(u) ((u) * CYCLES_PER_USEC)
#define CYCLES_TO_USEC(c) ((c) / CYCLES_PER_USEC)
/****************************************************************************
* Private Types
****************************************************************************/
struct esp32s2_rt_priv_s
{
int pid;
sem_t toutsem;
struct list_node runlist;
struct list_node toutlist;
struct esp32s2_tim_dev_s *timer;
};
/****************************************************************************
* Private Data
****************************************************************************/
static struct esp32s2_rt_priv_s g_rt_priv =
{
.pid = -EINVAL,
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: start_rt_timer
*
* Description:
* Start the timer by inserting it into the running list and reset the
* hardware timer alarm value if this timer is at the head of the list.
* Larger timeouts go to the end of the list (tail).
*
* Input Parameters:
* timer - RT timer pointer
* timeout - Timeout value
* repeat - repeat mode (true: enabled, false: disabled)
*
* Returned Value:
* None.
*
****************************************************************************/
static void start_rt_timer(struct rt_timer_s *timer,
uint64_t timeout,
bool repeat)
{
irqstate_t flags;
struct rt_timer_s *temp_p;
bool inserted = false;
uint64_t counter;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
flags = enter_critical_section();
/* Only idle timer can be started */
if (timer->state == RT_TIMER_IDLE)
{
/* Calculate the timer's alarm value */
ESP32S2_TIM_GETCTR(priv->timer, &counter);
counter = CYCLES_TO_USEC(counter);
timer->timeout = timeout;
timer->alarm = timer->timeout + counter;
if (repeat)
{
timer->flags |= RT_TIMER_REPEAT;
}
else
{
timer->flags &= ~RT_TIMER_REPEAT;
}
/* Scan the timer list and insert the new timer into previous
* node of timer whose alarm value is larger than new one
*/
list_for_every_entry(&priv->runlist, temp_p, struct rt_timer_s, list)
{
if (temp_p->alarm > timer->alarm)
{
list_add_before(&temp_p->list, &timer->list);
inserted = true;
break;
}
}
/* If we didn't find a larger one, insert the new timer at the tail
* of the list.
*/
if (!inserted)
{
list_add_tail(&priv->runlist, &timer->list);
}
timer->state = RT_TIMER_READY;
/* If this timer is at the head of the list */
if (timer == container_of(priv->runlist.next,
struct rt_timer_s, list))
{
/* Reset the hardware timer alarm */
ESP32S2_TIM_SETALRVL(priv->timer, USEC_TO_CYCLES(timer->alarm));
ESP32S2_TIM_SETALRM(priv->timer, true);
}
}
else
{
tmrwarn("WARN: Timer not in idle mode.\n"\
"Only idle timer can be started!\n");
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: stop_rt_timer
*
* Description:
* Stop the timer by removing it from the running list and reset the
* hardware timer alarm value if this timer is at the head of list.
*
* Input Parameters:
* timer - RT timer pointer
*
* Returned Value:
* None.
*
****************************************************************************/
static void stop_rt_timer(struct rt_timer_s *timer)
{
irqstate_t flags;
bool ishead;
struct rt_timer_s *next_timer;
uint64_t alarm;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
flags = enter_critical_section();
/* "start" function can set the timer's repeat flag, and "stop" function
* should remove this flag.
*/
timer->flags &= ~RT_TIMER_REPEAT;
/* Only timers in "ready" state can be stopped */
if (timer->state == RT_TIMER_READY)
{
/* Check if the timer is at the head of the list */
if (timer == container_of(priv->runlist.next,
struct rt_timer_s, list))
{
ishead = true;
}
else
{
ishead = false;
}
list_delete(&timer->list);
timer->state = RT_TIMER_IDLE;
/* If the timer is at the head of the list */
if (ishead)
{
if (!list_is_empty(&priv->runlist))
{
/* Set the value from the next timer as the new hardware timer
* alarm value.
*/
next_timer = container_of(priv->runlist.next,
struct rt_timer_s,
list);
alarm = next_timer->alarm;
ESP32S2_TIM_SETALRVL(priv->timer, USEC_TO_CYCLES(alarm));
ESP32S2_TIM_SETALRM(priv->timer, true);
}
}
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: delete_rt_timer
*
* Description:
* Delete the timer by removing it from the list, then set the timer's
* state to "RT_TIMER_DELETE" and finally insert it into the work list
* to let the rt-timer's thread to delete it and free the resources.
*
* Input Parameters:
* timer - RT timer pointer
*
* Returned Value:
* None.
*
****************************************************************************/
static void delete_rt_timer(struct rt_timer_s *timer)
{
int ret;
irqstate_t flags;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
flags = enter_critical_section();
if (timer->state == RT_TIMER_READY)
{
stop_rt_timer(timer);
}
else if (timer->state == RT_TIMER_TIMEOUT)
{
list_delete(&timer->list);
}
else if (timer->state == RT_TIMER_DELETE)
{
goto exit;
}
list_add_after(&priv->toutlist, &timer->list);
timer->state = RT_TIMER_DELETE;
/* Wake up the thread to process deleted timers */
ret = nxsem_post(&priv->toutsem);
if (ret < 0)
{
tmrerr("ERROR: Failed to post sem ret=%d\n", ret);
}
exit:
leave_critical_section(flags);
}
/****************************************************************************
* Name: rt_timer_thread
*
* Description:
* RT timer working thread: Waits for a timeout semaphore, scans
* the timeout list and processes all the timers in the list.
*
* Input Parameters:
* argc - Not used
* argv - Not used
*
* Returned Value:
* 0.
*
****************************************************************************/
static int rt_timer_thread(int argc, char *argv[])
{
int ret;
irqstate_t flags;
struct rt_timer_s *timer;
enum rt_timer_state_e raw_state;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
while (1)
{
/* Waiting for all timers to time out */
ret = nxsem_wait(&priv->toutsem);
if (ret)
{
tmrerr("ERROR: Wait priv->toutsem error=%d\n", ret);
assert(0);
}
flags = enter_critical_section();
/* Process all the timers in list */
while (!list_is_empty(&priv->toutlist))
{
/* Get the first timer in the list */
timer = container_of(priv->toutlist.next,
struct rt_timer_s, list);
/* Cache the raw state to decide how to deal with this timer */
raw_state = timer->state;
/* Delete the timer from the list */
list_delete(&timer->list);
/* Set timer's state to idle so it can be restarted by the user. */
timer->state = RT_TIMER_IDLE;
leave_critical_section(flags);
if (raw_state == RT_TIMER_TIMEOUT)
{
timer->callback(timer->arg);
}
else if (raw_state == RT_TIMER_DELETE)
{
kmm_free(timer);
}
/* Enter critical section for next scanning list */
flags = enter_critical_section();
if (raw_state == RT_TIMER_TIMEOUT)
{
/* Check if the timer is in "repeat" mode */
if (timer->flags & RT_TIMER_REPEAT)
{
start_rt_timer(timer, timer->timeout, true);
}
}
}
leave_critical_section(flags);
}
return 0;
}
/****************************************************************************
* Name: rt_timer_isr
*
* Description:
* Hardware timer interrupt service routine.
*
* Input Parameters:
* irq - Not used
* context - Not used
* arg - Not used
*
* Returned Value:
* 0.
*
****************************************************************************/
static int rt_timer_isr(int irq, void *context, void *arg)
{
int ret;
irqstate_t flags;
struct rt_timer_s *timer;
uint64_t alarm;
uint64_t counter;
bool wake = false;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
/* Clear interrupt register status */
ESP32S2_TIM_ACKINT(priv->timer);
flags = enter_critical_section();
/* Check if there is a timer running */
if (!list_is_empty(&priv->runlist))
{
/**
* When stop/delete timer, in the same time the hardware timer
* interrupt triggers, function "stop/delete" remove the timer
* from running list, so the 1st timer is not which triggers.
*/
timer = container_of(priv->runlist.next, struct rt_timer_s, list);
ESP32S2_TIM_GETCTR(priv->timer, &counter);
counter = CYCLES_TO_USEC(counter);
if (timer->alarm <= counter)
{
/* Remove the first timer from the running list and add it to
* the timeout list.
*
* Set the timer's state to be RT_TIMER_TIMEOUT to avoid
* other operations.
*/
list_delete(&timer->list);
timer->state = RT_TIMER_TIMEOUT;
list_add_after(&priv->toutlist, &timer->list);
wake = true;
/* Check if there is a timer running */
if (!list_is_empty(&priv->runlist))
{
/* Reset hardware timer alarm with next timer's alarm value */
timer = container_of(priv->runlist.next,
struct rt_timer_s, list);
alarm = timer->alarm;
ESP32S2_TIM_SETALRVL(priv->timer, USEC_TO_CYCLES(alarm));
}
}
/* If there is a timer in the list, the alarm should be enabled */
ESP32S2_TIM_SETALRM(priv->timer, true);
}
if (wake)
{
/* Wake up the thread to process timed-out timers */
ret = nxsem_post(&priv->toutsem);
if (ret < 0)
{
tmrerr("ERROR: Failed to post sem ret=%d\n", ret);
}
}
leave_critical_section(flags);
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: rt_timer_create
*
* Description:
* Create a RT timer from the provided arguments.
*
* Input Parameters:
* args - Input RT timer creation arguments
* timer_handle - Output RT timer handle pointer
*
* Returned Value:
* 0 is returned on success. Otherwise, a negated errno value is returned.
*
****************************************************************************/
int rt_timer_create(const struct rt_timer_args_s *args,
struct rt_timer_s **timer_handle)
{
struct rt_timer_s *timer;
timer = (struct rt_timer_s *)kmm_malloc(sizeof(*timer));
if (!timer)
{
tmrerr("ERROR: Failed to allocate %d bytes\n", sizeof(*timer));
return -ENOMEM;
}
timer->callback = args->callback;
timer->arg = args->arg;
timer->flags = RT_TIMER_NOFLAGS;
timer->state = RT_TIMER_IDLE;
list_initialize(&timer->list);
*timer_handle = timer;
return 0;
}
/****************************************************************************
* Name: rt_timer_start
*
* Description:
* Start the RT timer.
*
* Input Parameters:
* timer - RT timer pointer
* timeout - Timeout value
* repeat - repeat mode (true: enabled, false: disabled)
*
* Returned Value:
* None
*
****************************************************************************/
void rt_timer_start(struct rt_timer_s *timer,
uint64_t timeout,
bool repeat)
{
stop_rt_timer(timer);
start_rt_timer(timer, timeout, repeat);
}
/****************************************************************************
* Name: rt_timer_stop
*
* Description:
* Stop the RT timer.
*
* Input Parameters:
* timer - RT timer pointer
*
* Returned Value:
* None
*
****************************************************************************/
void rt_timer_stop(struct rt_timer_s *timer)
{
stop_rt_timer(timer);
}
/****************************************************************************
* Name: rt_timer_delete
*
* Description:
* Stop and delete the RT timer.
*
* Input Parameters:
* timer - RT timer pointer
*
* Returned Value:
* None
*
****************************************************************************/
void rt_timer_delete(struct rt_timer_s *timer)
{
delete_rt_timer(timer);
}
/****************************************************************************
* Name: rt_timer_time_us
*
* Description:
* Get current counter value of the RT timer in microseconds.
*
* Input Parameters:
* None
*
* Returned Value:
* Time of the RT timer in microseconds.
*
****************************************************************************/
uint64_t IRAM_ATTR rt_timer_time_us(void)
{
uint64_t counter;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
ESP32S2_TIM_GETCTR(priv->timer, &counter);
counter = CYCLES_TO_USEC(counter);
return counter;
}
/****************************************************************************
* Name: rt_timer_get_alarm
*
* Description:
* Get the remaining time to the next timeout.
*
* Input Parameters:
* None
*
* Returned Value:
* Timestamp of the nearest timer event in microseconds.
*
****************************************************************************/
uint64_t IRAM_ATTR rt_timer_get_alarm(void)
{
irqstate_t flags;
uint64_t counter;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
uint64_t alarm_value = 0;
flags = enter_critical_section();
ESP32S2_TIM_GETCTR(priv->timer, &counter);
counter = CYCLES_TO_USEC(counter);
ESP32S2_TIM_GETALRVL(priv->timer, &alarm_value);
alarm_value = CYCLES_TO_USEC(alarm_value);
if (alarm_value <= counter)
{
alarm_value = 0;
}
else
{
alarm_value -= counter;
}
leave_critical_section(flags);
return alarm_value;
}
/****************************************************************************
* Name: rt_timer_calibration
*
* Description:
* Adjust current RT timer by a certain value.
*
* Input Parameters:
* time_us - adjustment to apply to the RT timer in microseconds.
*
* Returned Value:
* None.
*
****************************************************************************/
void IRAM_ATTR rt_timer_calibration(uint64_t time_us)
{
uint64_t counter;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
irqstate_t flags;
flags = enter_critical_section();
ESP32S2_TIM_GETCTR(priv->timer, &counter);
counter = CYCLES_TO_USEC(counter);
counter += time_us;
ESP32S2_TIM_SETCTR(priv->timer, USEC_TO_CYCLES(counter));
ESP32S2_TIM_RLD_NOW(priv->timer);
leave_critical_section(flags);
}
/****************************************************************************
* Name: esp32s2_rt_timer_init
*
* Description:
* Initialize ESP32-S2 RT timer.
*
* Input Parameters:
* None
*
* Returned Value:
* 0 is returned on success. Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp32s2_rt_timer_init(void)
{
int pid;
irqstate_t flags;
struct esp32s2_tim_dev_s *tim;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
uint32_t xtal_clk;
uint16_t pre;
uint16_t ticks;
tim = esp32s2_tim_init(SYSTIMER_COMP0);
if (tim == NULL)
{
tmrerr("ERROR: Failed to initialize ESP32-S2 Systimer 0\n");
return -EINVAL;
}
nxsem_init(&priv->toutsem, 0, 0);
pid = kthread_create(RT_TIMER_TASK_NAME,
RT_TIMER_TASK_PRIORITY,
RT_TIMER_TASK_STACK_SIZE,
rt_timer_thread,
NULL);
if (pid < 0)
{
tmrerr("ERROR: Failed to create RT timer task error=%d\n", pid);
esp32s2_tim_deinit(tim);
return pid;
}
list_initialize(&priv->runlist);
list_initialize(&priv->toutlist);
priv->pid = pid;
priv->timer = tim;
flags = enter_critical_section();
/* ESP32-S2 hardware timer configuration, acc. TRM V1.0
* Systimer is clocked by APB_CLK.
* APB_CLK is determined by the source clock of CPU_CLK:
* CPU_CLK source | APB_CLK
* PLL_CLK | 80 MHz
* XTAL_CLK | CPU_CLK = XTAL_CLK / (SYSTEM_PRE_DIV_CNT + 1)
* The systimer period is determined by the step value.
* The step value is 1/(APB_CLK*ticks).
* On ESP32-S2, systimer has a mechanism that automatically
* detects which is the APB_CLK source and uses the step value
* configured for that specific source clock.
*/
/* PLL step = 1/(80 MHz * t) s, t = 1 -> 80 cycles per us */
ESP32S2_TIM_SETSTEP(priv->timer, ESP32S2_TIM_PLL_CLK, 1);
/* XTAL step = 1/((XTAL_CLK/(DIV +1)) * t) s
* To achieve the same 80 cycles per us,
* t = [(80 MHz * (DIV+1)) / XTAL_CLK]
* Example: XTAL_CLK = 40 MHz and DIV = 3, then t should be
* = ((80 MHz * 4) / 40 MHz) = 8.
*/
xtal_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_CLK_XTAL_FREQ);
pre = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT);
ticks = ((80 * (pre + 1)) / (xtal_clk));
ESP32S2_TIM_SETSTEP(priv->timer, ESP32S2_TIM_XTAL_CLK, ticks);
/* 1) Set Time-Delay work mode.
* 2) Clear the counter.
* 3) Set the ISR.
* 4) Enable timeout interrupt.
* 5) Start the counter.
* NOTE: No interrupt will be triggered until ESP32S2_TIM_SETALRM is set.
*/
ESP32S2_TIM_SETWORKMODE(priv->timer, ESP32S2_TIM_DELAY_ALRM);
ESP32S2_TIM_CLEAR(priv->timer);
ESP32S2_TIM_SETISR(priv->timer, rt_timer_isr, NULL);
ESP32S2_TIM_ENABLEINT(priv->timer);
leave_critical_section(flags);
return 0;
}
/****************************************************************************
* Name: esp32s2_rt_timer_deinit
*
* Description:
* Deinitialize ESP32-S2 RT timer.
*
* Input Parameters:
* None
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32s2_rt_timer_deinit(void)
{
irqstate_t flags;
struct esp32s2_rt_priv_s *priv = &g_rt_priv;
flags = enter_critical_section();
ESP32S2_TIM_DISABLEINT(priv->timer);
ESP32S2_TIM_SETISR(priv->timer, NULL, NULL);
esp32s2_tim_deinit(priv->timer);
priv->timer = NULL;
leave_critical_section(flags);
if (priv->pid != -EINVAL)
{
kthread_delete(priv->pid);
priv->pid = -EINVAL;
}
nxsem_destroy(&priv->toutsem);
}

View File

@ -0,0 +1,250 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/esp32s2_rt_timer.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_RT_TIMER_H
#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_RT_TIMER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <sys/types.h>
#include <nuttx/list.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define RT_TIMER_NOFLAGS (0) /* Timer supports no feature */
#define RT_TIMER_REPEAT (1 << 0) /* Timer supports repeat mode */
/****************************************************************************
* Public Types
****************************************************************************/
/**
* RT timer state
*/
enum rt_timer_state_e
{
RT_TIMER_IDLE, /* Timer is not counting */
RT_TIMER_READY, /* Timer is counting */
RT_TIMER_TIMEOUT, /* Timer timed out */
RT_TIMER_DELETE /* Timer is to be delete */
};
/**
* RT timer data structure
*/
struct rt_timer_s
{
uint64_t timeout; /* Timeout value */
uint64_t alarm; /* Timeout period */
void (*callback)(void *arg); /* Callback function */
void *arg; /* Private data */
uint16_t flags; /* Supported features */
enum rt_timer_state_e state; /* Timer state */
struct list_node list; /* Working list */
};
/**
* RT timer creation arguments data structure
*/
struct rt_timer_args_s
{
void (*callback)(void *arg); /* Callback function */
void *arg; /* Private data */
};
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: rt_timer_create
*
* Description:
* Create a RT timer from the provided arguments.
*
* Input Parameters:
* args - Input RT timer creation arguments
* timer_handle - Output RT timer handle pointer
*
* Returned Value:
* 0 is returned on success. Otherwise, a negated errno value is returned.
*
****************************************************************************/
int rt_timer_create(const struct rt_timer_args_s *args,
struct rt_timer_s **timer_handle);
/****************************************************************************
* Name: rt_timer_start
*
* Description:
* Start the RT timer.
*
* Input Parameters:
* timer - RT timer pointer
* timeout - Timeout value
* repeat - repeat mode (true: enabled, false: disabled)
*
* Returned Value:
* None
*
****************************************************************************/
void rt_timer_start(struct rt_timer_s *timer,
uint64_t timeout,
bool repeat);
/****************************************************************************
* Name: rt_timer_stop
*
* Description:
* Stop the RT timer.
*
* Input Parameters:
* timer - RT timer pointer
*
* Returned Value:
* None
*
****************************************************************************/
void rt_timer_stop(struct rt_timer_s *timer);
/****************************************************************************
* Name: rt_timer_delete
*
* Description:
* Stop and delete the RT timer.
*
* Input Parameters:
* timer - RT timer pointer
*
* Returned Value:
* None
*
****************************************************************************/
void rt_timer_delete(struct rt_timer_s *timer);
/****************************************************************************
* Name: rt_timer_time_us
*
* Description:
* Get time of the RT timer in microseconds.
*
* Input Parameters:
* None
*
* Returned Value:
* Time of the RT timer in microseconds.
*
****************************************************************************/
uint64_t rt_timer_time_us(void);
/****************************************************************************
* Name: rt_timer_get_alarm
*
* Description:
* Get the timestamp when the next timeout is expected to occur.
*
* Input Parameters:
* None
*
* Returned Value:
* Timestamp of the nearest timer event in microseconds.
*
****************************************************************************/
uint64_t rt_timer_get_alarm(void);
/****************************************************************************
* Name: rt_timer_calibration
*
* Description:
* Adjust current RT timer by a certain value.
*
* Input Parameters:
* time_us - adjustment to apply to the RT timer in microseconds.
*
* Returned Value:
* None.
*
****************************************************************************/
void rt_timer_calibration(uint64_t time_us);
/****************************************************************************
* Name: esp32s2_rt_timer_init
*
* Description:
* Initialize ESP32-S2 RT timer.
*
* Input Parameters:
* None
*
* Returned Value:
* 0 is returned on success. Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp32s2_rt_timer_init(void);
/****************************************************************************
* Name: esp32s2_rt_timer_deinit
*
* Description:
* Deinitialize ESP32-S2 RT timer.
*
* Input Parameters:
* None
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32s2_rt_timer_deinit(void);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_RT_TIMER_H */

View File

@ -33,6 +33,8 @@
#include "xtensa.h" #include "xtensa.h"
#include "hardware/esp32s2_tim.h" #include "hardware/esp32s2_tim.h"
#include "hardware/esp32s2_system.h"
#include "hardware/esp32s2_systimer.h"
#include "esp32s2_tim.h" #include "esp32s2_tim.h"
#include "esp32s2_cpuint.h" #include "esp32s2_cpuint.h"
@ -75,6 +77,9 @@ static void esp32s2_tim_setclksrc(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_clksrc_e src); enum esp32s2_tim_clksrc_e src);
static void esp32s2_tim_setpre(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_setpre(struct esp32s2_tim_dev_s *dev,
uint16_t pre); uint16_t pre);
static void esp32s2_tim_setstep(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_clksrc_e src,
uint16_t ticks);
static void esp32s2_tim_getcounter(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_getcounter(struct esp32s2_tim_dev_s *dev,
uint64_t *value); uint64_t *value);
static void esp32s2_tim_setcounter(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_setcounter(struct esp32s2_tim_dev_s *dev,
@ -82,8 +87,14 @@ static void esp32s2_tim_setcounter(struct esp32s2_tim_dev_s *dev,
static void esp32s2_tim_reload_now(struct esp32s2_tim_dev_s *dev); static void esp32s2_tim_reload_now(struct esp32s2_tim_dev_s *dev);
static void esp32s2_tim_getalarmvalue(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_getalarmvalue(struct esp32s2_tim_dev_s *dev,
uint64_t *value); uint64_t *value);
static void esp32s2_tim_getperiod(struct esp32s2_tim_dev_s *dev,
uint32_t *value);
static void esp32s2_tim_setalarmvalue(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_setalarmvalue(struct esp32s2_tim_dev_s *dev,
uint64_t value); uint64_t value);
static void esp32s2_tim_setperiod(struct esp32s2_tim_dev_s *dev,
uint32_t value);
static void esp32s2_tim_setworkmode(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_work_mode_e mode);
static void esp32s2_tim_setalarm(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_setalarm(struct esp32s2_tim_dev_s *dev,
bool enable); bool enable);
static void esp32s2_tim_setautoreload(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_setautoreload(struct esp32s2_tim_dev_s *dev,
@ -110,10 +121,14 @@ struct esp32s2_tim_ops_s esp32s2_tim_ops =
.getcounter = esp32s2_tim_getcounter, .getcounter = esp32s2_tim_getcounter,
.setclksrc = esp32s2_tim_setclksrc, .setclksrc = esp32s2_tim_setclksrc,
.setpre = esp32s2_tim_setpre, .setpre = esp32s2_tim_setpre,
.setstep = NULL,
.setcounter = esp32s2_tim_setcounter, .setcounter = esp32s2_tim_setcounter,
.reloadnow = esp32s2_tim_reload_now, .reloadnow = esp32s2_tim_reload_now,
.getalarmvalue = esp32s2_tim_getalarmvalue, .getalarmvalue = esp32s2_tim_getalarmvalue,
.getperiod = NULL,
.setalarmvalue = esp32s2_tim_setalarmvalue, .setalarmvalue = esp32s2_tim_setalarmvalue,
.setperiod = NULL,
.setworkmode = NULL,
.setalarm = esp32s2_tim_setalarm, .setalarm = esp32s2_tim_setalarm,
.setautoreload = esp32s2_tim_setautoreload, .setautoreload = esp32s2_tim_setautoreload,
.setisr = esp32s2_tim_setisr, .setisr = esp32s2_tim_setisr,
@ -123,6 +138,34 @@ struct esp32s2_tim_ops_s esp32s2_tim_ops =
.checkint = esp32s2_tim_checkint .checkint = esp32s2_tim_checkint
}; };
/* ESP32S2 SYSTIMER ops */
struct esp32s2_tim_ops_s esp32s2_systim_ops =
{
.start = NULL, /* Systimer doesn't support releasing counter */
.stop = NULL, /* Systimer doesn't support halting counter */
.clear = esp32s2_tim_clear,
.setmode = NULL,
.getcounter = esp32s2_tim_getcounter,
.setclksrc = NULL,
.setpre = NULL,
.setstep = esp32s2_tim_setstep,
.setcounter = esp32s2_tim_setcounter,
.reloadnow = esp32s2_tim_reload_now,
.getalarmvalue = esp32s2_tim_getalarmvalue,
.getperiod = esp32s2_tim_getperiod,
.setalarmvalue = esp32s2_tim_setalarmvalue,
.setperiod = esp32s2_tim_setperiod,
.setworkmode = esp32s2_tim_setworkmode,
.setalarm = esp32s2_tim_setalarm,
.setautoreload = NULL,
.setisr = esp32s2_tim_setisr,
.enableint = esp32s2_tim_enableint,
.disableint = esp32s2_tim_disableint,
.ackint = esp32s2_tim_ackint,
.checkint = esp32s2_tim_checkint
};
#ifdef CONFIG_ESP32S2_TIMER0 #ifdef CONFIG_ESP32S2_TIMER0
/* TIMER0 */ /* TIMER0 */
@ -188,6 +231,22 @@ struct esp32s2_tim_priv_s g_esp32s2_tim3_priv =
}; };
#endif #endif
#ifdef CONFIG_ESP32S2_RT_TIMER
/* SYSTIMER */
struct esp32s2_tim_priv_s g_esp32s2_tim4_priv =
{
.ops = &esp32s2_systim_ops,
.gid = -ENODEV, /* There's no group in systimer */
.tid = SYSTIMER_COMP0, /* Systimer contains 1 counter and 3 comps */
.int_pri = ESP32S2_INT_PRIO_DEF,
.periph = ESP32S2_PERI_SYSTIMER_TARGET0, /* Peripheral ID */
.irq = ESP32S2_IRQ_SYSTIMER_TARGET0, /* Interrupt ID */
.cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */
.inuse = false,
};
#endif
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -374,6 +433,37 @@ static void esp32s2_tim_setpre(struct esp32s2_tim_dev_s *dev,
} }
} }
/****************************************************************************
* Name: esp32s2_tim_setstep
*
* Description:
* Set the timer increment step, i.e, defines the time interval in ticks
* used by the counter.
* NOTE: dev pointer is not used because this feature is not available
* for Generic Timers and it doesn't rely in any systimer comparator.
*
* Parameters:
* src - Define the clock source for the ticks.
* ticks - Number of ticks to define 1 increment step.
*
****************************************************************************/
static void esp32s2_tim_setstep(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_clksrc_e src,
uint16_t ticks)
{
if (src == ESP32S2_TIM_PLL_CLK)
{
REG_SET_FIELD(SYSTIMER_STEP_REG, SYSTIMER_TIMER_PLL_STEP,
ticks & SYSTIMER_TIMER_PLL_STEP_V);
}
else if(src == ESP32S2_TIM_XTAL_CLK)
{
REG_SET_FIELD(SYSTIMER_STEP_REG, SYSTIMER_TIMER_XTAL_STEP,
ticks & SYSTIMER_TIMER_XTAL_STEP_V);
}
}
/**************************************************************************** /****************************************************************************
* Name: esp32s2_tim_getcounter * Name: esp32s2_tim_getcounter
* *
@ -396,34 +486,55 @@ static void esp32s2_tim_getcounter(struct esp32s2_tim_dev_s *dev,
DEBUGASSERT(dev); DEBUGASSERT(dev);
*value = 0; *value = 0;
if (priv->tid == SYSTIMER_COMP0)
if (priv->tid == TIMER0)
{ {
/* Dummy value (0 or 1) to latch the counter value to read it */ /* Latch counter */
putreg32(BIT(0), TIMG_T0UPDATE_REG(priv->gid)); modifyreg32(SYSTIMER_UPDATE_REG, 0, SYSTIMER_TIMER_UPDATE);
/* Wait until result is ready */
while (!REG_GET_FIELD(SYSTIMER_UPDATE_REG,
SYSTIMER_TIMER_VALUE_VALID));
/* Read value */ /* Read value */
value_32 = getreg32(TIMG_T0HI_REG(priv->gid)); /* High 32 bits */ value_32 = getreg32(SYSTIMER_VALUE_HI_REG); /* High 32 bits */
*value |= (uint64_t)value_32; *value |= (uint64_t)value_32;
*value <<= SHIFT_32; *value <<= SHIFT_32;
value_32 = getreg32(TIMG_T0LO_REG(priv->gid)); /* Low 32 bits */ value_32 = getreg32(SYSTIMER_VALUE_LO_REG); /* Low 32 bits */
*value |= (uint64_t)value_32; *value |= (uint64_t)value_32;
} }
else else
{ {
/* Dummy value (0 or 1) to latch the counter value to read it */ if (priv->tid == TIMER0)
{
/* Dummy value (0 or 1) to latch the counter value to read it */
putreg32(BIT(0), TIMG_T1UPDATE_REG(priv->gid)); putreg32(BIT(0), TIMG_T0UPDATE_REG(priv->gid));
/* Read value */ /* Read value */
value_32 = getreg32(TIMG_T1HI_REG(priv->gid)); /* High 32 bits */ value_32 = getreg32(TIMG_T0HI_REG(priv->gid)); /* High 32 bits */
*value |= (uint64_t)value_32; *value |= (uint64_t)value_32;
*value <<= SHIFT_32; *value <<= SHIFT_32;
value_32 = getreg32(TIMG_T1LO_REG(priv->gid)); /* Low 32 bits */ value_32 = getreg32(TIMG_T0LO_REG(priv->gid)); /* Low 32 bits */
*value |= (uint64_t)value_32; *value |= (uint64_t)value_32;
}
else
{
/* Dummy value (0 or 1) to latch the counter value to read it */
putreg32(BIT(0), TIMG_T1UPDATE_REG(priv->gid));
/* Read value */
value_32 = getreg32(TIMG_T1HI_REG(priv->gid)); /* High 32 bits */
*value |= (uint64_t)value_32;
*value <<= SHIFT_32;
value_32 = getreg32(TIMG_T1LO_REG(priv->gid)); /* Low 32 bits */
*value |= (uint64_t)value_32;
}
} }
} }
@ -436,6 +547,7 @@ static void esp32s2_tim_getcounter(struct esp32s2_tim_dev_s *dev,
* the auto-reload before. * the auto-reload before.
* If you want the counter to be loaded instantly, call * If you want the counter to be loaded instantly, call
* esp32s2_tim_reload_now() after this function. * esp32s2_tim_reload_now() after this function.
* NOTE: Systimer has 1 counter for 3 comparators.
* *
* Parameters: * Parameters:
* dev - Pointer to the timer driver struct. * dev - Pointer to the timer driver struct.
@ -444,7 +556,7 @@ static void esp32s2_tim_getcounter(struct esp32s2_tim_dev_s *dev,
****************************************************************************/ ****************************************************************************/
static void esp32s2_tim_setcounter(struct esp32s2_tim_dev_s *dev, static void esp32s2_tim_setcounter(struct esp32s2_tim_dev_s *dev,
uint64_t value) uint64_t value)
{ {
struct esp32s2_tim_priv_s *priv = (struct esp32s2_tim_priv_s *)dev; struct esp32s2_tim_priv_s *priv = (struct esp32s2_tim_priv_s *)dev;
uint64_t low_64 = value & UINT32_MAX; uint64_t low_64 = value & UINT32_MAX;
@ -454,15 +566,23 @@ static void esp32s2_tim_setcounter(struct esp32s2_tim_dev_s *dev,
/* Set the counter value */ /* Set the counter value */
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
putreg32((uint32_t)low_64, TIMG_T0LOADLO_REG(priv->gid)); putreg32((uint32_t)low_64, SYSTIMER_LOAD_LO_REG);
putreg32((uint32_t)high_64, TIMG_T0LOADHI_REG(priv->gid)); putreg32((uint32_t)high_64, SYSTIMER_LOAD_HI_REG);
} }
else else
{ {
putreg32((uint32_t)low_64, TIMG_T1LOADLO_REG(priv->gid)); if (priv->tid == TIMER0)
putreg32((uint32_t)high_64, TIMG_T1LOADHI_REG(priv->gid)); {
putreg32((uint32_t)low_64, TIMG_T0LOADLO_REG(priv->gid));
putreg32((uint32_t)high_64, TIMG_T0LOADHI_REG(priv->gid));
}
else
{
putreg32((uint32_t)low_64, TIMG_T1LOADLO_REG(priv->gid));
putreg32((uint32_t)high_64, TIMG_T1LOADHI_REG(priv->gid));
}
} }
} }
@ -486,13 +606,20 @@ static void esp32s2_tim_reload_now(struct esp32s2_tim_dev_s *dev)
/* Dummy value to trigger reloading */ /* Dummy value to trigger reloading */
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
putreg32(BIT(0), TIMG_T0LOAD_REG(priv->gid)); putreg32(BIT(31), SYSTIMER_LOAD_REG);
} }
else else
{ {
putreg32(BIT(0), TIMG_T1LOAD_REG(priv->gid)); if (priv->tid == TIMER0)
{
putreg32(BIT(0), TIMG_T0LOAD_REG(priv->gid));
}
else
{
putreg32(BIT(0), TIMG_T1LOAD_REG(priv->gid));
}
} }
} }
@ -501,6 +628,8 @@ static void esp32s2_tim_reload_now(struct esp32s2_tim_dev_s *dev)
* *
* Description: * Description:
* Get the alarm value. * Get the alarm value.
* NOTE: For systimer, the returned alarm value is the Time-Delay Alarm.
* See TRM for more details.
* *
* Parameters: * Parameters:
* dev - Pointer to the timer driver struct. * dev - Pointer to the timer driver struct.
@ -520,21 +649,63 @@ static void esp32s2_tim_getalarmvalue(struct esp32s2_tim_dev_s *dev,
/* Read value */ /* Read value */
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
value_32 = getreg32(TIMG_T0ALARMHI_REG(priv->gid)); /* High 32 bits */ value_32 = getreg32(SYSTIMER_TARGET0_HI_REG); /* High 32 bits */
*value |= (uint64_t)value_32; *value |= (uint64_t)value_32;
*value <<= SHIFT_32; *value <<= SHIFT_32;
value_32 = getreg32(TIMG_T0ALARMLO_REG(priv->gid)); /* Low 32 bits */ value_32 = getreg32(SYSTIMER_TARGET0_LO_REG); /* Low 32 bits */
*value |= (uint64_t)value_32; *value |= (uint64_t)value_32;
} }
else else
{ {
value_32 = getreg32(TIMG_T1ALARMHI_REG(priv->gid)); /* High 32 bits */ if (priv->tid == TIMER0)
*value |= (uint64_t)value_32; {
*value <<= SHIFT_32; value_32 = getreg32(TIMG_T0ALARMHI_REG(priv->gid)); /* High 32 bits */
value_32 = getreg32(TIMG_T1ALARMLO_REG(priv->gid)); /* Low 32 bits */ *value |= (uint64_t)value_32;
*value |= (uint64_t)value_32; *value <<= SHIFT_32;
value_32 = getreg32(TIMG_T0ALARMLO_REG(priv->gid)); /* Low 32 bits */
*value |= (uint64_t)value_32;
}
else
{
value_32 = getreg32(TIMG_T1ALARMHI_REG(priv->gid)); /* High 32 bits */
*value |= (uint64_t)value_32;
*value <<= SHIFT_32;
value_32 = getreg32(TIMG_T1ALARMLO_REG(priv->gid)); /* Low 32 bits */
*value |= (uint64_t)value_32;
}
}
}
/****************************************************************************
* Name: esp32s2_tim_getperiod
*
* Description:
* This function is only available for Systimer. And it's intended to get
* the alarm when it's working on periodic mode.
*
* Parameters:
* dev - Pointer to the timer driver struct.
* value - Pointer to retrieve the current configured alarm value.
*
****************************************************************************/
static void esp32s2_tim_getperiod(struct esp32s2_tim_dev_s *dev,
uint32_t *value)
{
struct esp32s2_tim_priv_s *priv = (struct esp32s2_tim_priv_s *)dev;
DEBUGASSERT(dev);
*value = 0;
/* Read value */
if (priv->tid == SYSTIMER_COMP0)
{
*value = REG_GET_FIELD(SYSTIMER_TARGET0_CONF_REG,
SYSTIMER_TARGET0_PERIOD);
} }
} }
@ -562,15 +733,81 @@ static void esp32s2_tim_setalarmvalue(struct esp32s2_tim_dev_s *dev,
/* Set an alarm value */ /* Set an alarm value */
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
putreg32((uint32_t)low_64, TIMG_T0ALARMLO_REG(priv->gid)); putreg32((uint32_t)low_64, SYSTIMER_TARGET0_LO_REG);
putreg32((uint32_t)high_64, TIMG_T0ALARMHI_REG(priv->gid)); putreg32((uint32_t)high_64, SYSTIMER_TARGET0_HI_REG);
} }
else else
{ {
putreg32((uint32_t)low_64, TIMG_T1ALARMLO_REG(priv->gid)); if (priv->tid == TIMER0)
putreg32((uint32_t)high_64, TIMG_T1ALARMHI_REG(priv->gid)); {
putreg32((uint32_t)low_64, TIMG_T0ALARMLO_REG(priv->gid));
putreg32((uint32_t)high_64, TIMG_T0ALARMHI_REG(priv->gid));
}
else
{
putreg32((uint32_t)low_64, TIMG_T1ALARMLO_REG(priv->gid));
putreg32((uint32_t)high_64, TIMG_T1ALARMHI_REG(priv->gid));
}
}
}
/****************************************************************************
* Name: esp32s2_tim_setperiod
*
* Description:
* This function is only available for Systimer. And it's intended to set
* the alarm when it's working on periodic mode.
*
* Parameters:
* dev - Pointer to the timer driver struct.
* value - Period value.
*
****************************************************************************/
static void esp32s2_tim_setperiod(struct esp32s2_tim_dev_s *dev,
uint32_t value)
{
struct esp32s2_tim_priv_s *priv = (struct esp32s2_tim_priv_s *)dev;
DEBUGASSERT(dev);
/* Read value */
if (priv->tid == SYSTIMER_COMP0)
{
REG_SET_FIELD(SYSTIMER_TARGET0_CONF_REG,
SYSTIMER_TARGET0_PERIOD, value);
}
}
/****************************************************************************
* Name: esp32s2_tim_setworkmode
*
* Description:
* This function is only available for Systimer. And it's intended to set
* the work mode: Time-Delay alarm mode or periodic alarm mode.
*
* Parameters:
* dev - Pointer to the timer driver struct.
* value - Period value.
*
****************************************************************************/
static void esp32s2_tim_setworkmode(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_work_mode_e mode)
{
struct esp32s2_tim_priv_s *priv = (struct esp32s2_tim_priv_s *)dev;
DEBUGASSERT(dev);
/* Read value */
if (priv->tid == SYSTIMER_COMP0)
{
REG_SET_FIELD(SYSTIMER_TARGET0_CONF_REG,
SYSTIMER_TARGET0_PERIOD_MODE, mode);
} }
} }
@ -594,26 +831,46 @@ static void esp32s2_tim_setalarm(struct esp32s2_tim_dev_s *dev,
DEBUGASSERT(dev); DEBUGASSERT(dev);
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
if (enable) if (enable)
{ {
modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0, TIMG_T0_ALARM_EN_M); modifyreg32(SYSTIMER_TARGET0_CONF_REG, 0,
SYSTIMER_TARGET0_WORK_EN);
} }
else else
{ {
modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_ALARM_EN_M, 0); modifyreg32(SYSTIMER_TARGET0_CONF_REG,
SYSTIMER_TARGET0_WORK_EN, 0);
} }
} }
else else
{ {
if (enable) if (priv->tid == TIMER0)
{ {
modifyreg32(TIMG_T1CONFIG_REG(priv->gid), 0, TIMG_T1_ALARM_EN_M); if (enable)
{
modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0,
TIMG_T0_ALARM_EN_M);
}
else
{
modifyreg32(TIMG_T0CONFIG_REG(priv->gid),
TIMG_T0_ALARM_EN_M, 0);
}
} }
else else
{ {
modifyreg32(TIMG_T1CONFIG_REG(priv->gid), TIMG_T1_ALARM_EN_M, 0); if (enable)
{
modifyreg32(TIMG_T1CONFIG_REG(priv->gid),
0, TIMG_T1_ALARM_EN_M);
}
else
{
modifyreg32(TIMG_T1CONFIG_REG(priv->gid),
TIMG_T1_ALARM_EN_M, 0);
}
} }
} }
} }
@ -729,7 +986,14 @@ static int esp32s2_tim_setisr(struct esp32s2_tim_dev_s *dev,
esp32s2_free_cpuint(priv->periph); esp32s2_free_cpuint(priv->periph);
} }
priv->cpuint = esp32s2_alloc_levelint(priv->int_pri); if (priv->tid == SYSTIMER_COMP0)
{
priv->cpuint = esp32s2_alloc_edgeint(priv->int_pri);
}
else
{
priv->cpuint = esp32s2_alloc_levelint(priv->int_pri);
}
if (priv->cpuint < 0) if (priv->cpuint < 0)
{ {
@ -765,7 +1029,7 @@ errout:
* Name: esp32s2_tim_enableint * Name: esp32s2_tim_enableint
* *
* Description: * Description:
* Enable a level Interrupt at the alarm if it is set. * Enable Interrupt at the alarm if it is set.
* *
* Parameters: * Parameters:
* dev - Pointer to the timer driver struct. * dev - Pointer to the timer driver struct.
@ -778,15 +1042,26 @@ static void esp32s2_tim_enableint(struct esp32s2_tim_dev_s *dev)
DEBUGASSERT(dev); DEBUGASSERT(dev);
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0, TIMG_T0_LEVEL_INT_EN_M); modifyreg32(SYSTIMER_INT_ENA_REG, 0, SYSTIMER_SYSTIMER_INT0_ENA_M);
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid), 0, TIMG_T0_INT_ENA_M);
} }
else else
{ {
modifyreg32(TIMG_T1CONFIG_REG(priv->gid), 0, TIMG_T1_LEVEL_INT_EN_M); if (priv->tid == TIMER0)
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid), 0, TIMG_T1_INT_ENA_M); {
modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0,
TIMG_T0_LEVEL_INT_EN_M);
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid), 0,
TIMG_T0_INT_ENA_M);
}
else
{
modifyreg32(TIMG_T1CONFIG_REG(priv->gid), 0,
TIMG_T1_LEVEL_INT_EN_M);
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid), 0,
TIMG_T1_INT_ENA_M);
}
} }
} }
@ -794,7 +1069,7 @@ static void esp32s2_tim_enableint(struct esp32s2_tim_dev_s *dev)
* Name: esp32s2_tim_disableint * Name: esp32s2_tim_disableint
* *
* Description: * Description:
* Disable a level Interrupt at the alarm if it is set. * Disable a Interrupt at the alarm if it is set.
* *
* Parameters: * Parameters:
* dev - Pointer to the timer driver struct. * dev - Pointer to the timer driver struct.
@ -807,15 +1082,26 @@ static void esp32s2_tim_disableint(struct esp32s2_tim_dev_s *dev)
DEBUGASSERT(dev); DEBUGASSERT(dev);
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_LEVEL_INT_EN_M, 0); modifyreg32(SYSTIMER_INT_ENA_REG, SYSTIMER_SYSTIMER_INT0_ENA_M, 0);
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid), TIMG_T0_INT_ENA_M, 0);
} }
else else
{ {
modifyreg32(TIMG_T1CONFIG_REG(priv->gid), TIMG_T1_LEVEL_INT_EN_M, 0); if (priv->tid == TIMER0)
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid), TIMG_T1_INT_ENA_M, 0); {
modifyreg32(TIMG_T0CONFIG_REG(priv->gid),
TIMG_T0_LEVEL_INT_EN_M, 0);
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid),
TIMG_T0_INT_ENA_M, 0);
}
else
{
modifyreg32(TIMG_T1CONFIG_REG(priv->gid),
TIMG_T1_LEVEL_INT_EN_M, 0);
modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->gid),
TIMG_T1_INT_ENA_M, 0);
}
} }
} }
@ -836,13 +1122,22 @@ static void esp32s2_tim_ackint(struct esp32s2_tim_dev_s *dev)
DEBUGASSERT(dev); DEBUGASSERT(dev);
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
modifyreg32(TIMG_INT_CLR_TIMERS_REG(priv->gid), 0, TIMG_T0_INT_CLR_M); modifyreg32(SYSTIMER_INT_CLR_REG, 0, SYSTIMER_SYSTIMER_INT0_CLR_M);
} }
else else
{ {
modifyreg32(TIMG_INT_CLR_TIMERS_REG(priv->gid), 0, TIMG_T1_INT_CLR_M); if (priv->tid == TIMER0)
{
modifyreg32(TIMG_INT_CLR_TIMERS_REG(priv->gid), 0,
TIMG_T0_INT_CLR_M);
}
else
{
modifyreg32(TIMG_INT_CLR_TIMERS_REG(priv->gid), 0,
TIMG_T1_INT_CLR_M);
}
} }
} }
@ -868,15 +1163,23 @@ static int esp32s2_tim_checkint(struct esp32s2_tim_dev_s *dev)
DEBUGASSERT(dev); DEBUGASSERT(dev);
if (priv->tid == TIMER0) if (priv->tid == SYSTIMER_COMP0)
{ {
reg_value = getreg32(TIMG_INT_ST_TIMERS_REG(priv->gid)); reg_value = getreg32(SYSTIMER_INT_RAW_REG);
ret = REG_MASK(reg_value, TIMG_T0_INT_ST); ret = REG_MASK(reg_value, SYSTIMER_SYSTIMER_INT0_RAW);
} }
else else
{ {
reg_value = getreg32(TIMG_INT_ST_TIMERS_REG(priv->gid)); if (priv->tid == TIMER0)
ret = REG_MASK(reg_value, TIMG_T1_INT_ST); {
reg_value = getreg32(TIMG_INT_ST_TIMERS_REG(priv->gid));
ret = REG_MASK(reg_value, TIMG_T0_INT_ST);
}
else
{
reg_value = getreg32(TIMG_INT_ST_TIMERS_REG(priv->gid));
ret = REG_MASK(reg_value, TIMG_T1_INT_ST);
}
} }
return ret; return ret;
@ -912,7 +1215,7 @@ struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer)
switch (timer) switch (timer)
{ {
#ifdef CONFIG_ESP32S2_TIMER0 #ifdef CONFIG_ESP32S2_TIMER0
case 0: case TIMER0:
{ {
tim = &g_esp32s2_tim0_priv; tim = &g_esp32s2_tim0_priv;
break; break;
@ -920,7 +1223,7 @@ struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer)
#endif #endif
#ifdef CONFIG_ESP32S2_TIMER1 #ifdef CONFIG_ESP32S2_TIMER1
case 1: case TIMER1:
{ {
tim = &g_esp32s2_tim1_priv; tim = &g_esp32s2_tim1_priv;
break; break;
@ -928,7 +1231,7 @@ struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer)
#endif #endif
#ifdef CONFIG_ESP32S2_TIMER2 #ifdef CONFIG_ESP32S2_TIMER2
case 2: case TIMER2:
{ {
tim = &g_esp32s2_tim2_priv; tim = &g_esp32s2_tim2_priv;
break; break;
@ -936,18 +1239,28 @@ struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer)
#endif #endif
#ifdef CONFIG_ESP32S2_TIMER3 #ifdef CONFIG_ESP32S2_TIMER3
case 3: case TIMER3:
{ {
tim = &g_esp32s2_tim3_priv; tim = &g_esp32s2_tim3_priv;
break; break;
} }
#endif #endif
default: #ifdef CONFIG_ESP32S2_RT_TIMER
case SYSTIMER_COMP0:
{ {
tmrerr("ERROR: unsupported TIMER %d\n", timer); tim = &g_esp32s2_tim4_priv;
goto errout;
/* Enable Systimer peripheral clock and reset it */
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, 0, SYSTEM_SYSTIMER_CLK_EN);
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, 0, SYSTEM_SYSTIMER_RST);
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_SYSTIMER_RST, 0);
modifyreg32(SYSTIMER_CONF_REG, 0, SYSTIMER_CLK_EN
| SYSTIMER_CLK_FO);
break;
} }
#endif
} }
/* Verify if it is in use */ /* Verify if it is in use */
@ -962,7 +1275,6 @@ struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer)
tim = NULL; tim = NULL;
} }
errout:
return (struct esp32s2_tim_dev_s *)tim; return (struct esp32s2_tim_dev_s *)tim;
} }

View File

@ -42,12 +42,16 @@
#define ESP32S2_TIM_CLEAR(d) ((d)->ops->clear(d)) #define ESP32S2_TIM_CLEAR(d) ((d)->ops->clear(d))
#define ESP32S2_TIM_SETMODE(d, m) ((d)->ops->setmode(d, m)) #define ESP32S2_TIM_SETMODE(d, m) ((d)->ops->setmode(d, m))
#define ESP32S2_TIM_SETPRE(d, p) ((d)->ops->setpre(d, p)) #define ESP32S2_TIM_SETPRE(d, p) ((d)->ops->setpre(d, p))
#define ESP32S2_TIM_SETSTEP(d, s, t) ((d)->ops->setstep(d, s, t))
#define ESP32S2_TIM_GETCTR(d, v) ((d)->ops->getcounter(d, v)) #define ESP32S2_TIM_GETCTR(d, v) ((d)->ops->getcounter(d, v))
#define ESP32S2_TIM_CLK_SRC(d, s) ((d)->ops->setclksrc(d, s)) #define ESP32S2_TIM_CLK_SRC(d, s) ((d)->ops->setclksrc(d, s))
#define ESP32S2_TIM_SETCTR(d, v) ((d)->ops->setcounter(d, v)) #define ESP32S2_TIM_SETCTR(d, v) ((d)->ops->setcounter(d, v))
#define ESP32S2_TIM_RLD_NOW(d) ((d)->ops->reloadnow(d)) #define ESP32S2_TIM_RLD_NOW(d) ((d)->ops->reloadnow(d))
#define ESP32S2_TIM_GETALRVL(d, v) ((d)->ops->getalarmvalue(d, v)) #define ESP32S2_TIM_GETALRVL(d, v) ((d)->ops->getalarmvalue(d, v))
#define ESP32S2_TIM_GETPERIOD(d, v) ((d)->ops->getperiod(d, v))
#define ESP32S2_TIM_SETALRVL(d, v) ((d)->ops->setalarmvalue(d, v)) #define ESP32S2_TIM_SETALRVL(d, v) ((d)->ops->setalarmvalue(d, v))
#define ESP32S2_TIM_SETPERIOD(d, v) ((d)->ops->setperiod(d, v))
#define ESP32S2_TIM_SETWORKMODE(d, v) ((d)->ops->setworkmode(d, v))
#define ESP32S2_TIM_SETALRM(d, e) ((d)->ops->setalarm(d, e)) #define ESP32S2_TIM_SETALRM(d, e) ((d)->ops->setalarm(d, e))
#define ESP32S2_TIM_SETARLD(d, e) ((d)->ops->setautoreload(d, e)) #define ESP32S2_TIM_SETARLD(d, e) ((d)->ops->setautoreload(d, e))
#define ESP32S2_TIM_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) #define ESP32S2_TIM_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg))
@ -56,10 +60,13 @@
#define ESP32S2_TIM_ACKINT(d) ((d)->ops->ackint(d)) #define ESP32S2_TIM_ACKINT(d) ((d)->ops->ackint(d))
#define ESP32S2_TIM_CHECKINT(d) ((d)->ops->checkint(d)) #define ESP32S2_TIM_CHECKINT(d) ((d)->ops->checkint(d))
#define TIMER0 0 #define TIMER0 0 /* Timer group 0 timer 0 */
#define TIMER1 1 #define TIMER1 1 /* Timer group 0 timer 1 */
#define TIMER2 2 #define TIMER2 2 /* Timer group 1 timer 0 */
#define TIMER3 3 #define TIMER3 3 /* Timer group 1 timer 1 */
#define SYSTIMER_COMP0 4 /* Systimer comparator 0 */
#define SYSTIMER_COMP1 5 /* Systimer comparator 1 */
#define SYSTIMER_COMP2 6 /* Systimer comparator 2 */
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
@ -73,12 +80,21 @@ enum esp32s2_tim_mode_e
ESP32S2_TIM_MODE_UP, ESP32S2_TIM_MODE_UP,
}; };
/* Systimer Work modes */
enum esp32s2_tim_work_mode_e
{
ESP32S2_TIM_DELAY_ALRM,
ESP32S2_TIM_PERIOD_ALRM,
};
/* Timer mode */ /* Timer mode */
enum esp32s2_tim_clksrc_e enum esp32s2_tim_clksrc_e
{ {
ESP32S2_TIM_APB_CLK, ESP32S2_TIM_APB_CLK, /* Available only for Generic Timers */
ESP32S2_TIM_XTAL_CLK, ESP32S2_TIM_XTAL_CLK, /* Available for both Generic Timers and Systimer */
ESP32S2_TIM_PLL_CLK /* Available only for Systimer */
}; };
/* ESP32-S2 TIM device */ /* ESP32-S2 TIM device */
@ -105,6 +121,9 @@ struct esp32s2_tim_ops_s
void (*setmode)(struct esp32s2_tim_dev_s *dev, void (*setmode)(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_mode_e mode); enum esp32s2_tim_mode_e mode);
void (*setpre)(struct esp32s2_tim_dev_s *dev, uint16_t pre); void (*setpre)(struct esp32s2_tim_dev_s *dev, uint16_t pre);
void (*setstep)(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_clksrc_e src,
uint16_t ticks);
void (*getcounter)(struct esp32s2_tim_dev_s *dev, void (*getcounter)(struct esp32s2_tim_dev_s *dev,
uint64_t *value); uint64_t *value);
void (*setclksrc)(struct esp32s2_tim_dev_s *dev, void (*setclksrc)(struct esp32s2_tim_dev_s *dev,
@ -113,8 +132,12 @@ struct esp32s2_tim_ops_s
void (*reloadnow)(struct esp32s2_tim_dev_s *dev); void (*reloadnow)(struct esp32s2_tim_dev_s *dev);
void (*getalarmvalue)(struct esp32s2_tim_dev_s *dev, void (*getalarmvalue)(struct esp32s2_tim_dev_s *dev,
uint64_t *value); uint64_t *value);
void (*getperiod)(struct esp32s2_tim_dev_s *dev, uint32_t *value);
void (*setalarmvalue)(struct esp32s2_tim_dev_s *dev, void (*setalarmvalue)(struct esp32s2_tim_dev_s *dev,
uint64_t value); uint64_t value);
void (*setperiod)(struct esp32s2_tim_dev_s *dev, uint32_t value);
void (*setworkmode)(struct esp32s2_tim_dev_s *dev,
enum esp32s2_tim_work_mode_e);
void (*setalarm)(struct esp32s2_tim_dev_s *dev, bool enable); void (*setalarm)(struct esp32s2_tim_dev_s *dev, bool enable);
void (*setautoreload)(struct esp32s2_tim_dev_s *dev, bool enable); void (*setautoreload)(struct esp32s2_tim_dev_s *dev, bool enable);

View File

@ -0,0 +1,484 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/hardware/esp32s2_systimer.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_SYSTIMER_H
#define __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_SYSTIMER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "esp32s2_soc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* SYSTIMER_CONF_REG register
* Configure system timer clock
*/
#define SYSTIMER_CONF_REG (DR_REG_SYSTIMER_BASE + 0x0)
/* SYSTIMER_CLK_EN : R/W; bitpos: [31]; default: 0;
* register clock enable
*/
#define SYSTIMER_CLK_EN (BIT(31))
#define SYSTIMER_CLK_EN_M (SYSTIMER_CLK_EN_V << SYSTIMER_CLK_EN_S)
#define SYSTIMER_CLK_EN_V 0x00000001
#define SYSTIMER_CLK_EN_S 31
/* SYSTIMER_CLK_FO : R/W; bitpos: [0]; default: 0;
* system timer force clock enable
*/
#define SYSTIMER_CLK_FO (BIT(0))
#define SYSTIMER_CLK_FO_M (SYSTIMER_CLK_FO_V << SYSTIMER_CLK_FO_S)
#define SYSTIMER_CLK_FO_V 0x00000001
#define SYSTIMER_CLK_FO_S 0
/* SYSTIMER_LOAD_REG register
* load value to system timer
*/
#define SYSTIMER_LOAD_REG (DR_REG_SYSTIMER_BASE + 0x4)
/* SYSTIMER_TIMER_LOAD : WO; bitpos: [31]; default: 0;
* load value to system timer
*/
#define SYSTIMER_TIMER_LOAD (BIT(31))
#define SYSTIMER_TIMER_LOAD_M (SYSTIMER_TIMER_LOAD_V << SYSTIMER_TIMER_LOAD_S)
#define SYSTIMER_TIMER_LOAD_V 0x00000001
#define SYSTIMER_TIMER_LOAD_S 31
/* SYSTIMER_LOAD_HI_REG register
* High 32-bit load to system timer
*/
#define SYSTIMER_LOAD_HI_REG (DR_REG_SYSTIMER_BASE + 0x8)
/* SYSTIMER_TIMER_LOAD_HI : R/W; bitpos: [31:0]; default: 0;
* High 32-bit load to system timer
*/
#define SYSTIMER_TIMER_LOAD_HI 0xFFFFFFFF
#define SYSTIMER_TIMER_LOAD_HI_M (SYSTIMER_TIMER_LOAD_HI_V << SYSTIMER_TIMER_LOAD_HI_S)
#define SYSTIMER_TIMER_LOAD_HI_V 0xFFFFFFFF
#define SYSTIMER_TIMER_LOAD_HI_S 0
/* SYSTIMER_LOAD_LO_REG register
* Low 32-bit load to system timer
*/
#define SYSTIMER_LOAD_LO_REG (DR_REG_SYSTIMER_BASE + 0xc)
/* SYSTIMER_TIMER_LOAD_LO : R/W; bitpos: [31:0]; default: 0;
* Low 32-bit load to system timer
*/
#define SYSTIMER_TIMER_LOAD_LO 0xFFFFFFFF
#define SYSTIMER_TIMER_LOAD_LO_M (SYSTIMER_TIMER_LOAD_LO_V << SYSTIMER_TIMER_LOAD_LO_S)
#define SYSTIMER_TIMER_LOAD_LO_V 0xFFFFFFFF
#define SYSTIMER_TIMER_LOAD_LO_S 0
/* SYSTIMER_STEP_REG register
* system timer accumulation step
*/
#define SYSTIMER_STEP_REG (DR_REG_SYSTIMER_BASE + 0x10)
/* SYSTIMER_TIMER_PLL_STEP : R/W; bitpos: [19:10]; default: 1;
* system timer accumulation step when using PLL
*/
#define SYSTIMER_TIMER_PLL_STEP 0x000003FF
#define SYSTIMER_TIMER_PLL_STEP_M (SYSTIMER_TIMER_PLL_STEP_V << SYSTIMER_TIMER_PLL_STEP_S)
#define SYSTIMER_TIMER_PLL_STEP_V 0x000003FF
#define SYSTIMER_TIMER_PLL_STEP_S 10
/* SYSTIMER_TIMER_XTAL_STEP : R/W; bitpos: [9:0]; default: 80;
* system timer accumulation step when using XTAL
*/
#define SYSTIMER_TIMER_XTAL_STEP 0x000003FF
#define SYSTIMER_TIMER_XTAL_STEP_M (SYSTIMER_TIMER_XTAL_STEP_V << SYSTIMER_TIMER_XTAL_STEP_S)
#define SYSTIMER_TIMER_XTAL_STEP_V 0x000003FF
#define SYSTIMER_TIMER_XTAL_STEP_S 0
/* SYSTIMER_TARGET0_HI_REG register
* System timer target0 high 32-bit
*/
#define SYSTIMER_TARGET0_HI_REG (DR_REG_SYSTIMER_BASE + 0x14)
/* SYSTIMER_TIMER_TARGET0_HI : R/W; bitpos: [31:0]; default: 0;
* System timer target0 high 32-bit
*/
#define SYSTIMER_TIMER_TARGET0_HI 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET0_HI_M (SYSTIMER_TIMER_TARGET0_HI_V << SYSTIMER_TIMER_TARGET0_HI_S)
#define SYSTIMER_TIMER_TARGET0_HI_V 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET0_HI_S 0
/* SYSTIMER_TARGET0_LO_REG register
* System timer target0 low 32-bit
*/
#define SYSTIMER_TARGET0_LO_REG (DR_REG_SYSTIMER_BASE + 0x18)
/* SYSTIMER_TIMER_TARGET0_LO : R/W; bitpos: [31:0]; default: 0;
* System timer target0 low 32-bit
*/
#define SYSTIMER_TIMER_TARGET0_LO 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET0_LO_M (SYSTIMER_TIMER_TARGET0_LO_V << SYSTIMER_TIMER_TARGET0_LO_S)
#define SYSTIMER_TIMER_TARGET0_LO_V 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET0_LO_S 0
/* SYSTIMER_TARGET1_HI_REG register
* System timer target1 high 32-bit
*/
#define SYSTIMER_TARGET1_HI_REG (DR_REG_SYSTIMER_BASE + 0x1c)
/* SYSTIMER_TIMER_TARGET1_HI : R/W; bitpos: [31:0]; default: 0;
* System timer target1 high 32-bit
*/
#define SYSTIMER_TIMER_TARGET1_HI 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET1_HI_M (SYSTIMER_TIMER_TARGET1_HI_V << SYSTIMER_TIMER_TARGET1_HI_S)
#define SYSTIMER_TIMER_TARGET1_HI_V 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET1_HI_S 0
/* SYSTIMER_TARGET1_LO_REG register
* System timer target1 low 32-bit
*/
#define SYSTIMER_TARGET1_LO_REG (DR_REG_SYSTIMER_BASE + 0x20)
/* SYSTIMER_TIMER_TARGET1_LO : R/W; bitpos: [31:0]; default: 0;
* System timer target1 low 32-bit
*/
#define SYSTIMER_TIMER_TARGET1_LO 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET1_LO_M (SYSTIMER_TIMER_TARGET1_LO_V << SYSTIMER_TIMER_TARGET1_LO_S)
#define SYSTIMER_TIMER_TARGET1_LO_V 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET1_LO_S 0
/* SYSTIMER_TARGET2_HI_REG register
* System timer target2 high 32-bit
*/
#define SYSTIMER_TARGET2_HI_REG (DR_REG_SYSTIMER_BASE + 0x24)
/* SYSTIMER_TIMER_TARGET2_HI : R/W; bitpos: [31:0]; default: 0;
* System timer target2 high 32-bit
*/
#define SYSTIMER_TIMER_TARGET2_HI 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET2_HI_M (SYSTIMER_TIMER_TARGET2_HI_V << SYSTIMER_TIMER_TARGET2_HI_S)
#define SYSTIMER_TIMER_TARGET2_HI_V 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET2_HI_S 0
/* SYSTIMER_TARGET2_LO_REG register
* System timer target2 low 32-bit
*/
#define SYSTIMER_TARGET2_LO_REG (DR_REG_SYSTIMER_BASE + 0x28)
/* SYSTIMER_TIMER_TARGET2_LO : R/W; bitpos: [31:0]; default: 0;
* System timer target2 low 32-bit
*/
#define SYSTIMER_TIMER_TARGET2_LO 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET2_LO_M (SYSTIMER_TIMER_TARGET2_LO_V << SYSTIMER_TIMER_TARGET2_LO_S)
#define SYSTIMER_TIMER_TARGET2_LO_V 0xFFFFFFFF
#define SYSTIMER_TIMER_TARGET2_LO_S 0
/* SYSTIMER_TARGET0_CONF_REG register
* Configure system timer target0 work mode
*/
#define SYSTIMER_TARGET0_CONF_REG (DR_REG_SYSTIMER_BASE + 0x2c)
/* SYSTIMER_TARGET0_WORK_EN : R/W; bitpos: [31]; default: 0;
* system timer target0 work enable
*/
#define SYSTIMER_TARGET0_WORK_EN (BIT(31))
#define SYSTIMER_TARGET0_WORK_EN_M (SYSTIMER_TARGET0_WORK_EN_V << SYSTIMER_TARGET0_WORK_EN_S)
#define SYSTIMER_TARGET0_WORK_EN_V 0x00000001
#define SYSTIMER_TARGET0_WORK_EN_S 31
/* SYSTIMER_TARGET0_PERIOD_MODE : R/W; bitpos: [30]; default: 0;
* Whether system timer target0 work in period mode
*/
#define SYSTIMER_TARGET0_PERIOD_MODE (BIT(30))
#define SYSTIMER_TARGET0_PERIOD_MODE_M (SYSTIMER_TARGET0_PERIOD_MODE_V << SYSTIMER_TARGET0_PERIOD_MODE_S)
#define SYSTIMER_TARGET0_PERIOD_MODE_V 0x00000001
#define SYSTIMER_TARGET0_PERIOD_MODE_S 30
/* SYSTIMER_TARGET0_PERIOD : R/W; bitpos: [29:0]; default: 0;
* System timer target0 alarm period
*/
#define SYSTIMER_TARGET0_PERIOD 0x3FFFFFFF
#define SYSTIMER_TARGET0_PERIOD_M (SYSTIMER_TARGET0_PERIOD_V << SYSTIMER_TARGET0_PERIOD_S)
#define SYSTIMER_TARGET0_PERIOD_V 0x3FFFFFFF
#define SYSTIMER_TARGET0_PERIOD_S 0
/* SYSTIMER_TARGET1_CONF_REG register
* Configure system timer target1 work mode
*/
#define SYSTIMER_TARGET1_CONF_REG (DR_REG_SYSTIMER_BASE + 0x30)
/* SYSTIMER_TARGET1_WORK_EN : R/W; bitpos: [31]; default: 0;
* system timer target1 work enable
*/
#define SYSTIMER_TARGET1_WORK_EN (BIT(31))
#define SYSTIMER_TARGET1_WORK_EN_M (SYSTIMER_TARGET1_WORK_EN_V << SYSTIMER_TARGET1_WORK_EN_S)
#define SYSTIMER_TARGET1_WORK_EN_V 0x00000001
#define SYSTIMER_TARGET1_WORK_EN_S 31
/* SYSTIMER_TARGET1_PERIOD_MODE : R/W; bitpos: [30]; default: 0;
* Whether system timer target1 work in period mode
*/
#define SYSTIMER_TARGET1_PERIOD_MODE (BIT(30))
#define SYSTIMER_TARGET1_PERIOD_MODE_M (SYSTIMER_TARGET1_PERIOD_MODE_V << SYSTIMER_TARGET1_PERIOD_MODE_S)
#define SYSTIMER_TARGET1_PERIOD_MODE_V 0x00000001
#define SYSTIMER_TARGET1_PERIOD_MODE_S 30
/* SYSTIMER_TARGET1_PERIOD : R/W; bitpos: [29:0]; default: 0;
* System timer target1 alarm period
*/
#define SYSTIMER_TARGET1_PERIOD 0x3FFFFFFF
#define SYSTIMER_TARGET1_PERIOD_M (SYSTIMER_TARGET1_PERIOD_V << SYSTIMER_TARGET1_PERIOD_S)
#define SYSTIMER_TARGET1_PERIOD_V 0x3FFFFFFF
#define SYSTIMER_TARGET1_PERIOD_S 0
/* SYSTIMER_TARGET2_CONF_REG register
* Configure system timer target2 work mode
*/
#define SYSTIMER_TARGET2_CONF_REG (DR_REG_SYSTIMER_BASE + 0x34)
/* SYSTIMER_TARGET2_WORK_EN : R/W; bitpos: [31]; default: 0;
* system timer target2 work enable
*/
#define SYSTIMER_TARGET2_WORK_EN (BIT(31))
#define SYSTIMER_TARGET2_WORK_EN_M (SYSTIMER_TARGET2_WORK_EN_V << SYSTIMER_TARGET2_WORK_EN_S)
#define SYSTIMER_TARGET2_WORK_EN_V 0x00000001
#define SYSTIMER_TARGET2_WORK_EN_S 31
/* SYSTIMER_TARGET2_PERIOD_MODE : R/W; bitpos: [30]; default: 0;
* Whether system timer target2 work in period mode
*/
#define SYSTIMER_TARGET2_PERIOD_MODE (BIT(30))
#define SYSTIMER_TARGET2_PERIOD_MODE_M (SYSTIMER_TARGET2_PERIOD_MODE_V << SYSTIMER_TARGET2_PERIOD_MODE_S)
#define SYSTIMER_TARGET2_PERIOD_MODE_V 0x00000001
#define SYSTIMER_TARGET2_PERIOD_MODE_S 30
/* SYSTIMER_TARGET2_PERIOD : R/W; bitpos: [29:0]; default: 0;
* System timer target2 alarm period
*/
#define SYSTIMER_TARGET2_PERIOD 0x3FFFFFFF
#define SYSTIMER_TARGET2_PERIOD_M (SYSTIMER_TARGET2_PERIOD_V << SYSTIMER_TARGET2_PERIOD_S)
#define SYSTIMER_TARGET2_PERIOD_V 0x3FFFFFFF
#define SYSTIMER_TARGET2_PERIOD_S 0
/* SYSTIMER_UPDATE_REG register
* Read out system timer value
*/
#define SYSTIMER_UPDATE_REG (DR_REG_SYSTIMER_BASE + 0x38)
/* SYSTIMER_TIMER_UPDATE : WO; bitpos: [31]; default: 0;
* Update system timer value to register
*/
#define SYSTIMER_TIMER_UPDATE (BIT(31))
#define SYSTIMER_TIMER_UPDATE_M (SYSTIMER_TIMER_UPDATE_V << SYSTIMER_TIMER_UPDATE_S)
#define SYSTIMER_TIMER_UPDATE_V 0x00000001
#define SYSTIMER_TIMER_UPDATE_S 31
/* SYSTIMER_TIMER_VALUE_VALID : RO; bitpos: [30]; default: 0;
* If it is valid to read out timer value from register
*/
#define SYSTIMER_TIMER_VALUE_VALID (BIT(30))
#define SYSTIMER_TIMER_VALUE_VALID_M (SYSTIMER_TIMER_VALUE_VALID_V << SYSTIMER_TIMER_VALUE_VALID_S)
#define SYSTIMER_TIMER_VALUE_VALID_V 0x00000001
#define SYSTIMER_TIMER_VALUE_VALID_S 30
/* SYSTIMER_VALUE_HI_REG register
* system timer high 32-bit
*/
#define SYSTIMER_VALUE_HI_REG (DR_REG_SYSTIMER_BASE + 0x3c)
/* SYSTIMER_TIMER_VALUE_HI : RO; bitpos: [31:0]; default: 0;
* system timer high 32-bit
*/
#define SYSTIMER_TIMER_VALUE_HI 0xFFFFFFFF
#define SYSTIMER_TIMER_VALUE_HI_M (SYSTIMER_TIMER_VALUE_HI_V << SYSTIMER_TIMER_VALUE_HI_S)
#define SYSTIMER_TIMER_VALUE_HI_V 0xFFFFFFFF
#define SYSTIMER_TIMER_VALUE_HI_S 0
/* SYSTIMER_VALUE_LO_REG register
* system timer low 32-bit
*/
#define SYSTIMER_VALUE_LO_REG (DR_REG_SYSTIMER_BASE + 0x40)
/* SYSTIMER_TIMER_VALUE_LO : RO; bitpos: [31:0]; default: 0;
* system timer low 32-bit
*/
#define SYSTIMER_TIMER_VALUE_LO 0xFFFFFFFF
#define SYSTIMER_TIMER_VALUE_LO_M (SYSTIMER_TIMER_VALUE_LO_V << SYSTIMER_TIMER_VALUE_LO_S)
#define SYSTIMER_TIMER_VALUE_LO_V 0xFFFFFFFF
#define SYSTIMER_TIMER_VALUE_LO_S 0
/* SYSTIMER_INT_ENA_REG register
* system timer interrupt enable
*/
#define SYSTIMER_INT_ENA_REG (DR_REG_SYSTIMER_BASE + 0x44)
/* SYSTIMER_SYSTIMER_INT2_ENA : R/W; bitpos: [2]; default: 0;
* system timer target2 interrupt enable
*/
#define SYSTIMER_SYSTIMER_INT2_ENA (BIT(2))
#define SYSTIMER_SYSTIMER_INT2_ENA_M (SYSTIMER_SYSTIMER_INT2_ENA_V << SYSTIMER_SYSTIMER_INT2_ENA_S)
#define SYSTIMER_SYSTIMER_INT2_ENA_V 0x00000001
#define SYSTIMER_SYSTIMER_INT2_ENA_S 2
/* SYSTIMER_SYSTIMER_INT1_ENA : R/W; bitpos: [1]; default: 0;
* system timer target1 interrupt enable
*/
#define SYSTIMER_SYSTIMER_INT1_ENA (BIT(1))
#define SYSTIMER_SYSTIMER_INT1_ENA_M (SYSTIMER_SYSTIMER_INT1_ENA_V << SYSTIMER_SYSTIMER_INT1_ENA_S)
#define SYSTIMER_SYSTIMER_INT1_ENA_V 0x00000001
#define SYSTIMER_SYSTIMER_INT1_ENA_S 1
/* SYSTIMER_SYSTIMER_INT0_ENA : R/W; bitpos: [0]; default: 0;
* system timer target0 interrupt enable
*/
#define SYSTIMER_SYSTIMER_INT0_ENA (BIT(0))
#define SYSTIMER_SYSTIMER_INT0_ENA_M (SYSTIMER_SYSTIMER_INT0_ENA_V << SYSTIMER_SYSTIMER_INT0_ENA_S)
#define SYSTIMER_SYSTIMER_INT0_ENA_V 0x00000001
#define SYSTIMER_SYSTIMER_INT0_ENA_S 0
/* SYSTIMER_INT_RAW_REG register
* system timer interrupt raw
*/
#define SYSTIMER_INT_RAW_REG (DR_REG_SYSTIMER_BASE + 0x48)
/* SYSTIMER_SYSTIMER_INT2_RAW : RO; bitpos: [2]; default: 0;
* system timer target2 interrupt raw
*/
#define SYSTIMER_SYSTIMER_INT2_RAW (BIT(2))
#define SYSTIMER_SYSTIMER_INT2_RAW_M (SYSTIMER_SYSTIMER_INT2_RAW_V << SYSTIMER_SYSTIMER_INT2_RAW_S)
#define SYSTIMER_SYSTIMER_INT2_RAW_V 0x00000001
#define SYSTIMER_SYSTIMER_INT2_RAW_S 2
/* SYSTIMER_SYSTIMER_INT1_RAW : RO; bitpos: [1]; default: 0;
* system timer target1 interrupt raw
*/
#define SYSTIMER_SYSTIMER_INT1_RAW (BIT(1))
#define SYSTIMER_SYSTIMER_INT1_RAW_M (SYSTIMER_SYSTIMER_INT1_RAW_V << SYSTIMER_SYSTIMER_INT1_RAW_S)
#define SYSTIMER_SYSTIMER_INT1_RAW_V 0x00000001
#define SYSTIMER_SYSTIMER_INT1_RAW_S 1
/* SYSTIMER_SYSTIMER_INT0_RAW : RO; bitpos: [0]; default: 0;
* system timer target0 interrupt raw
*/
#define SYSTIMER_SYSTIMER_INT0_RAW (BIT(0))
#define SYSTIMER_SYSTIMER_INT0_RAW_M (SYSTIMER_SYSTIMER_INT0_RAW_V << SYSTIMER_SYSTIMER_INT0_RAW_S)
#define SYSTIMER_SYSTIMER_INT0_RAW_V 0x00000001
#define SYSTIMER_SYSTIMER_INT0_RAW_S 0
/* SYSTIMER_INT_CLR_REG register
* system timer interrupt clear
*/
#define SYSTIMER_INT_CLR_REG (DR_REG_SYSTIMER_BASE + 0x4c)
/* SYSTIMER_SYSTIMER_INT2_CLR : WO; bitpos: [2]; default: 0;
* system timer target2 interrupt clear
*/
#define SYSTIMER_SYSTIMER_INT2_CLR (BIT(2))
#define SYSTIMER_SYSTIMER_INT2_CLR_M (SYSTIMER_SYSTIMER_INT2_CLR_V << SYSTIMER_SYSTIMER_INT2_CLR_S)
#define SYSTIMER_SYSTIMER_INT2_CLR_V 0x00000001
#define SYSTIMER_SYSTIMER_INT2_CLR_S 2
/* SYSTIMER_SYSTIMER_INT1_CLR : WO; bitpos: [1]; default: 0;
* system timer target1 interrupt clear
*/
#define SYSTIMER_SYSTIMER_INT1_CLR (BIT(1))
#define SYSTIMER_SYSTIMER_INT1_CLR_M (SYSTIMER_SYSTIMER_INT1_CLR_V << SYSTIMER_SYSTIMER_INT1_CLR_S)
#define SYSTIMER_SYSTIMER_INT1_CLR_V 0x00000001
#define SYSTIMER_SYSTIMER_INT1_CLR_S 1
/* SYSTIMER_SYSTIMER_INT0_CLR : WO; bitpos: [0]; default: 0;
* system timer target0 interrupt clear
*/
#define SYSTIMER_SYSTIMER_INT0_CLR (BIT(0))
#define SYSTIMER_SYSTIMER_INT0_CLR_M (SYSTIMER_SYSTIMER_INT0_CLR_V << SYSTIMER_SYSTIMER_INT0_CLR_S)
#define SYSTIMER_SYSTIMER_INT0_CLR_V 0x00000001
#define SYSTIMER_SYSTIMER_INT0_CLR_S 0
/* SYSTIMER_DATE_REG register
* system timer register version
*/
#define SYSTIMER_DATE_REG (DR_REG_SYSTIMER_BASE + 0xfc)
/* SYSTIMER_DATE : R/W; bitpos: [31:0]; default: 25194848;
* system timer register version
*/
#define SYSTIMER_DATE 0xFFFFFFFF
#define SYSTIMER_DATE_M (SYSTIMER_DATE_V << SYSTIMER_DATE_S)
#define SYSTIMER_DATE_V 0xFFFFFFFF
#define SYSTIMER_DATE_S 0
#endif /* __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_SYSTIMER_H */

View File

@ -50,6 +50,10 @@
# include "esp32s2_tim_lowerhalf.h" # include "esp32s2_tim_lowerhalf.h"
#endif #endif
#ifdef CONFIG_ESP32S2_RT_TIMER
# include "esp32s2_rt_timer.h"
#endif
#include "esp32s2-saola-1.h" #include "esp32s2-saola-1.h"
/**************************************************************************** /****************************************************************************
@ -154,6 +158,14 @@ int esp32s2_bringup(void)
#endif /* CONFIG_TIMER */ #endif /* CONFIG_TIMER */
#ifdef CONFIG_ESP32S2_RT_TIMER
ret = esp32s2_rt_timer_init();
if (ret < 0)
{
syslog(LOG_ERR, "Failed to initialize RT timer: %d\n", ret);
}
#endif
/* If we got here then perhaps not all initialization was successful, but /* If we got here then perhaps not all initialization was successful, but
* at least enough succeeded to bring-up NSH with perhaps reduced * at least enough succeeded to bring-up NSH with perhaps reduced
* capabilities. * capabilities.