diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs index 824e10fac1f..218adbb04e1 100644 --- a/arch/xtensa/src/esp32s2/Make.defs +++ b/arch/xtensa/src/esp32s2/Make.defs @@ -75,3 +75,9 @@ ifeq ($(CONFIG_ESP32S2_UART),y) CMN_CSRCS += esp32s2_serial.c endif +ifeq ($(CONFIG_ESP32S2_TIMER),y) +CHIP_CSRCS += esp32s2_tim.c +ifeq ($(CONFIG_TIMER),y) +CHIP_CSRCS += esp32s2_tim_lowerhalf.c +endif +endif diff --git a/arch/xtensa/src/esp32s2/esp32s2_tim.c b/arch/xtensa/src/esp32s2/esp32s2_tim.c new file mode 100644 index 00000000000..2007a43751d --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_tim.c @@ -0,0 +1,988 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_tim.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "xtensa.h" + +#include "hardware/esp32s2_tim.h" + +#include "esp32s2_tim.h" +#include "esp32s2_cpuint.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GROUP0 0 +#define GROUP1 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct esp32s2_tim_priv_s +{ + FAR struct esp32s2_tim_ops_s *ops; + uint8_t gid; /* Group instance */ + uint8_t tid; /* Timer instance */ + uint8_t int_pri; + uint8_t periph; /* Peripheral ID */ + uint8_t irq; /* Interrupt ID */ + int cpuint; /* CPU interrupt assigned to this timer */ + bool inuse; /* Flag indicating if the timer is in use */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* TIM operations ***********************************************************/ + +static void esp32s2_tim_start(FAR struct esp32s2_tim_dev_s *dev); +static void esp32s2_tim_stop(FAR struct esp32s2_tim_dev_s *dev); +static void esp32s2_tim_clear(FAR struct esp32s2_tim_dev_s *dev); +static void esp32s2_tim_setmode(FAR struct esp32s2_tim_dev_s *dev, + enum esp32s2_tim_mode_e mode); +static void esp32s2_tim_setclksrc(FAR struct esp32s2_tim_dev_s *dev, + enum esp32s2_tim_clksrc_e src); +static void esp32s2_tim_setpre(FAR struct esp32s2_tim_dev_s *dev, + uint16_t pre); +static void esp32s2_tim_getcounter(FAR struct esp32s2_tim_dev_s *dev, + uint64_t *value); +static void esp32s2_tim_setcounter(FAR struct esp32s2_tim_dev_s *dev, + uint64_t value); +static void esp32s2_tim_reload_now(FAR struct esp32s2_tim_dev_s *dev); +static void esp32s2_tim_getalarmvalue(FAR struct esp32s2_tim_dev_s *dev, + uint64_t *value); +static void esp32s2_tim_setalarmvalue(FAR struct esp32s2_tim_dev_s *dev, + uint64_t value); +static void esp32s2_tim_setalarm(FAR struct esp32s2_tim_dev_s *dev, + bool enable); +static void esp32s2_tim_setautoreload(FAR struct esp32s2_tim_dev_s *dev, + bool enable); +static int esp32s2_tim_setisr(FAR struct esp32s2_tim_dev_s *dev, + xcpt_t handler, FAR void * arg); +static void esp32s2_tim_enableint(FAR struct esp32s2_tim_dev_s *dev); +static void esp32s2_tim_disableint(FAR struct esp32s2_tim_dev_s *dev); +static void esp32s2_tim_ackint(FAR struct esp32s2_tim_dev_s *dev); +static int esp32s2_tim_checkint(FAR struct esp32s2_tim_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ESP32-S2 TIM ops */ + +struct esp32s2_tim_ops_s esp32s2_tim_ops = +{ + .start = esp32s2_tim_start, + .stop = esp32s2_tim_stop, + .clear = esp32s2_tim_clear, + .setmode = esp32s2_tim_setmode, + .getcounter = esp32s2_tim_getcounter, + .setclksrc = esp32s2_tim_setclksrc, + .setpre = esp32s2_tim_setpre, + .setcounter = esp32s2_tim_setcounter, + .reloadnow = esp32s2_tim_reload_now, + .getalarmvalue = esp32s2_tim_getalarmvalue, + .setalarmvalue = esp32s2_tim_setalarmvalue, + .setalarm = esp32s2_tim_setalarm, + .setautoreload = esp32s2_tim_setautoreload, + .setisr = esp32s2_tim_setisr, + .enableint = esp32s2_tim_enableint, + .disableint = esp32s2_tim_disableint, + .ackint = esp32s2_tim_ackint, + .checkint = esp32s2_tim_checkint +}; + +#ifdef CONFIG_ESP32S2_TIMER0 + +/* TIMER0 */ + +struct esp32s2_tim_priv_s g_esp32s2_tim0_priv = +{ + .ops = &esp32s2_tim_ops, + .gid = GROUP0, + .tid = TIMER0, + .int_pri = ESP32S2_INT_PRIO_DEF, + .periph = ESP32S2_PERI_TG_T0_LEVEL, /* Peripheral ID */ + .irq = ESP32S2_IRQ_TG_T0_LEVEL, /* Interrupt ID */ + .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .inuse = false, +}; +#endif + +#ifdef CONFIG_ESP32S2_TIMER1 +/* TIMER1 */ + +struct esp32s2_tim_priv_s g_esp32s2_tim1_priv = +{ + .ops = &esp32s2_tim_ops, + .gid = GROUP0, + .tid = TIMER1, + .int_pri = ESP32S2_INT_PRIO_DEF, + .periph = ESP32S2_PERI_TG_T1_LEVEL, /* Peripheral ID */ + .irq = ESP32S2_IRQ_TG_T1_LEVEL, /* Interrupt ID */ + .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .inuse = false, +}; +#endif + +#ifdef CONFIG_ESP32S2_TIMER2 +/* TIMER2 */ + +struct esp32s2_tim_priv_s g_esp32s2_tim2_priv = +{ + .ops = &esp32s2_tim_ops, + .gid = GROUP1, + .tid = TIMER0, + .int_pri = ESP32S2_INT_PRIO_DEF, + .periph = ESP32S2_PERI_TG1_T0_LEVEL, /* Peripheral ID */ + .irq = ESP32S2_IRQ_TG1_T0_LEVEL, /* Interrupt ID */ + .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .inuse = false, +}; +#endif + +#ifdef CONFIG_ESP32S2_TIMER3 +/* TIMER3 */ + +struct esp32s2_tim_priv_s g_esp32s2_tim3_priv = +{ + .ops = &esp32s2_tim_ops, + .gid = GROUP1, + .tid = TIMER1, + .int_pri = ESP32S2_INT_PRIO_DEF, + .periph = ESP32S2_PERI_TG1_T1_LEVEL, /* Peripheral ID */ + .irq = ESP32S2_IRQ_TG1_T1_LEVEL, /* Interrupt ID */ + .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .inuse = false, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_tim_start + * + * Description: + * Release the counter. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_start(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0, TIMG_T0_EN_M); + } + else + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), 0, TIMG_T1_EN_M); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_stop + * + * Description: + * Halt the counter. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_stop(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_EN_M, 0); + } + else + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), TIMG_T1_EN_M, 0); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_clear + * + * Description: + * Set the counter to zero instantly. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_clear(FAR struct esp32s2_tim_dev_s *dev) +{ + uint64_t clear_value = 0; + + DEBUGASSERT(dev); + + esp32s2_tim_setcounter(dev, clear_value); + esp32s2_tim_reload_now(dev); +} + +/**************************************************************************** + * Name: esp32s2_tim_setmode + * + * Description: + * Set counter mode. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * mode - Variable indicating the counting direction (up/down). + * + ****************************************************************************/ + +static void esp32s2_tim_setmode(FAR struct esp32s2_tim_dev_s *dev, + enum esp32s2_tim_mode_e mode) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (mode == ESP32S2_TIM_MODE_DOWN) + { + if (priv->tid == TIMER0) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_INCREASE_M, 0); + } + else + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), TIMG_T1_INCREASE_M, 0); + } + } + else if (mode == ESP32S2_TIM_MODE_UP) + { + if (priv->tid == TIMER0) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0, TIMG_T0_INCREASE_M); + } + else + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), 0, TIMG_T1_INCREASE_M); + } + } +} + +/**************************************************************************** + * Name: esp32s2_tim_setclksrc + * + * Description: + * Set CLK source. + * NOTE: It's not necessary to configure each timer's register for clock, + * because it doesn't matter which timer is configured, the clock + * configuration will apply to the timer group. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * src - The source, it may be APB_CLK or XTAL_CLK. + * + ****************************************************************************/ + +static void esp32s2_tim_setclksrc(FAR struct esp32s2_tim_dev_s *dev, + enum esp32s2_tim_clksrc_e src) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (src == ESP32S2_TIM_APB_CLK) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_USE_XTAL_M, 0); + } + else if(src == ESP32S2_TIM_XTAL_CLK) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0, TIMG_T0_USE_XTAL_M); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_setpre + * + * Description: + * Set the prescaler. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * pre - This is the division factor. This variable accepts + * values from 0 to 65535. If pre = 0, the division factor + * is 65536, if pre = 1 or 2, the division factor is 2. + * + ****************************************************************************/ + +static void esp32s2_tim_setpre(FAR struct esp32s2_tim_dev_s *dev, + uint16_t pre) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + uint32_t mask = (uint32_t)pre << TIMG_T0_DIVIDER_S; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_DIVIDER_M, mask); + } + else + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), TIMG_T1_DIVIDER_M, mask); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_getcounter + * + * Description: + * Get the current counter value. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - A pointer to a variable to store the current read + * value from counter. + * + ****************************************************************************/ + +static void esp32s2_tim_getcounter(FAR struct esp32s2_tim_dev_s *dev, + uint64_t *value) +{ + uint32_t value_32; + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + *value = 0; + + if (priv->tid == TIMER0) + { + /* Dummy value (0 or 1) to latch the counter value to read it */ + + putreg32(BIT(0), TIMG_T0UPDATE_REG(priv->gid)); + + /* Read value */ + + value_32 = getreg32(TIMG_T0HI_REG(priv->gid)); /* High 32 bits */ + *value |= (uint64_t)value_32; + *value <<= SHIFT_32; + value_32 = getreg32(TIMG_T0LO_REG(priv->gid)); /* Low 32 bits */ + *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; + } +} + +/**************************************************************************** + * Name: esp32s2_tim_setcounter + * + * Description: + * Set the value to be loaded to the counter. + * If you want the counter to be loaded at an alarm, enable the alarm and + * the auto-reload before. + * If you want the counter to be loaded instantly, call + * esp32s2_tim_reload_now() after this function. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - The value to be loaded the counter. + * + ****************************************************************************/ + +static void esp32s2_tim_setcounter(FAR struct esp32s2_tim_dev_s *dev, + uint64_t value) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + uint64_t low_64 = value & UINT32_MAX; + uint64_t high_64 = (value >> SHIFT_32); + + DEBUGASSERT(dev); + + /* Set the counter value */ + + if (priv->tid == TIMER0) + { + 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)); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_reload_now + * + * Description: + * Reload the counter instantly. It may be called after + * esp32s2_tim_setcounter(). + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_reload_now(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + /* Dummy value to trigger reloading */ + + if (priv->tid == TIMER0) + { + putreg32(BIT(0), TIMG_T0LOAD_REG(priv->gid)); + } + else + { + putreg32(BIT(0), TIMG_T1LOAD_REG(priv->gid)); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_getalarmvalue + * + * Description: + * Get the alarm value. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - Pointer to retrieve the current configured alarm value. + * + ****************************************************************************/ + +static void esp32s2_tim_getalarmvalue(FAR struct esp32s2_tim_dev_s *dev, + uint64_t *value) +{ + uint32_t value_32; + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + *value = 0; + + /* Read value */ + + if (priv->tid == TIMER0) + { + value_32 = getreg32(TIMG_T0ALARMHI_REG(priv->gid)); /* High 32 bits */ + *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_setalarmvalue + * + * Description: + * Set the value that will trigger an alarm when the + * counter value matches this value. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - The alarm value. + * + ****************************************************************************/ + +static void esp32s2_tim_setalarmvalue(FAR struct esp32s2_tim_dev_s *dev, + uint64_t value) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + uint64_t low_64 = value & UINT32_MAX; + uint64_t high_64 = (value >> SHIFT_32); + + DEBUGASSERT(dev); + + /* Set an alarm value */ + + if (priv->tid == TIMER0) + { + 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_setalarm + * + * Description: + * Enable/Disable the alarm. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * enable - A variable to indicate the action. If true, enable + * the alarm, if false, disable it. + * + ****************************************************************************/ + +static void esp32s2_tim_setalarm(FAR struct esp32s2_tim_dev_s *dev, + bool enable) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + 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 + { + 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); + } + } +} + +/**************************************************************************** + * Name: esp32s2_tim_setautoreload + * + * Description: + * Enable or disable the auto reload. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * enable - A variable to indicate the action. If it is true, + * enable the auto reload, if false, + * disable auto reload. + * + ****************************************************************************/ + +static void esp32s2_tim_setautoreload(FAR struct esp32s2_tim_dev_s *dev, + bool enable) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + if (enable) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), 0, TIMG_T0_AUTORELOAD_M); + } + else + { + modifyreg32(TIMG_T0CONFIG_REG(priv->gid), TIMG_T0_AUTORELOAD_M, 0); + } + } + else + { + if (enable) + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), 0, TIMG_T1_AUTORELOAD_M); + } + else + { + modifyreg32(TIMG_T1CONFIG_REG(priv->gid), TIMG_T1_AUTORELOAD_M, 0); + } + } +} + +/**************************************************************************** + * Name: esp32s2_tim_setisr + * + * Description: + * Allocate a CPU Interrupt, connect the peripheral source to this + * Interrupt, register the callback and enable the CPU Interruption. + * In case a NULL handler is provided, deallocate the interrupt and + * unregister the previously provided handler. + * + * Parameters: + * dev - Pointer to the driver state structure. + * handler - Callback to be invoked on timer interrupt. + * arg - Argument to be passed to the handler callback. + * + * Returned Values: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +static int esp32s2_tim_setisr(FAR struct esp32s2_tim_dev_s *dev, + xcpt_t handler, FAR void *arg) +{ + FAR struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + int ret = OK; + + DEBUGASSERT(dev); + + /* Disable interrupt when callback is removed. */ + + if (handler == NULL) + { + if (priv->cpuint != -ENOMEM) + { + /* Disable cpu interrupt */ + + up_disable_irq(priv->cpuint); + + /* Dissociate the IRQ from the ISR */ + + irq_detach(priv->irq); + + /* Free cpu interrupt that is attached to this peripheral */ + + esp32s2_free_cpuint(priv->periph); + priv->cpuint = -ENOMEM; + } + } + + /* Otherwise set callback and enable interrupt */ + + else + { + if (priv->cpuint != -ENOMEM) + { + /* Disable the provided CPU interrupt to configure it. */ + + up_disable_irq(priv->cpuint); + + /* Free cpu interrupt that is attached to this peripheral + * because we will get another from esp32s2_request_irq() + */ + + esp32s2_free_cpuint(priv->periph); + } + + priv->cpuint = esp32s2_alloc_levelint(priv->int_pri); + + if (priv->cpuint < 0) + { + tmrerr("ERROR: Failed to get a CPU interrupt"); + ret = priv->cpuint; + goto errout; + } + + /* Attach a peripheral interrupt to a CPU interrupt */ + + esp32s2_attach_peripheral(priv->periph, priv->cpuint); + + /* Associate an IRQ Number (from the timer) to an ISR */ + + ret = irq_attach(priv->irq, handler, arg); + if (ret != OK) + { + tmrerr("ERROR: Failed to associate an IRQ Number to and ISR"); + esp32s2_free_cpuint(priv->periph); + goto errout; + } + + /* Enable the CPU Interrupt that is linked to the timer */ + + up_enable_irq(priv->cpuint); + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: esp32s2_tim_enableint + * + * Description: + * Enable a level Interrupt at the alarm if it is set. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_enableint(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + 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); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_disableint + * + * Description: + * Disable a level Interrupt at the alarm if it is set. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_disableint(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + 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); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_ackint + * + * Description: + * Acknowledge an interrupt, that means, clear the interrupt. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32s2_tim_ackint(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (FAR struct esp32s2_tim_priv_s *)dev; + + DEBUGASSERT(dev); + + 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); + } +} + +/**************************************************************************** + * Name: esp32s2_tim_checkint + * + * Description: + * Check the interrupt status bit. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + * Returned Values: + * Return 1 in case of an interrupt is triggered, otherwise 0. + * + ****************************************************************************/ + +static int esp32s2_tim_checkint(FAR struct esp32s2_tim_dev_s *dev) +{ + struct esp32s2_tim_priv_s *priv = (struct esp32s2_tim_priv_s *)dev; + uint32_t reg_value; + int ret; + + DEBUGASSERT(dev); + + if (priv->tid == TIMER0) + { + 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; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_tim_init + * + * Description: + * Initialize TIMER device. + * + * Parameters: + * timer - Timer instance to be initialized. + * Valid values: 0 or 1. + * + * Returned Values: + * If the initialization is successful, return a pointer to the timer + * driver struct associated to that timer instance. + * In case it fails, return NULL. + * + ****************************************************************************/ + +FAR struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer) +{ + FAR struct esp32s2_tim_priv_s *tim = NULL; + + /* First, take the data structure associated with the timer instance */ + + switch (timer) + { +#ifdef CONFIG_ESP32S2_TIMER0 + case 0: + { + tim = &g_esp32s2_tim0_priv; + break; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER1 + case 1: + { + tim = &g_esp32s2_tim1_priv; + break; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER2 + case 2: + { + tim = &g_esp32s2_tim2_priv; + break; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER3 + case 3: + { + tim = &g_esp32s2_tim3_priv; + break; + } +#endif + + default: + { + tmrerr("ERROR: unsupported TIMER %d\n", timer); + goto errout; + } + } + + /* Verify if it is in use */ + + if (tim->inuse == false) + { + tim->inuse = true; /* If it was not, now it is */ + } + else + { + tmrerr("ERROR: TIMER %d is already in use\n", timer); + tim = NULL; + } + +errout: + return (FAR struct esp32s2_tim_dev_s *)tim; +} + +/**************************************************************************** + * Name: esp32s2_tim_deinit + * + * Description: + * Deinit TIMER device. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +void esp32s2_tim_deinit(FAR struct esp32s2_tim_dev_s *dev) +{ + FAR struct esp32s2_tim_priv_s *tim = NULL; + + DEBUGASSERT(dev); + + tim = (FAR struct esp32s2_tim_priv_s *)dev; + tim->inuse = false; +} diff --git a/arch/xtensa/src/esp32s2/esp32s2_tim.h b/arch/xtensa/src/esp32s2/esp32s2_tim.h new file mode 100644 index 00000000000..770ff9575a6 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_tim.h @@ -0,0 +1,138 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_tim.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_TIM_H +#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define ESP32S2_TIM_START(d) ((d)->ops->start(d)) +#define ESP32S2_TIM_STOP(d) ((d)->ops->stop(d)) +#define ESP32S2_TIM_CLEAR(d) ((d)->ops->clear(d)) +#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_GETCTR(d, v) ((d)->ops->getcounter(d, v)) +#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_RLD_NOW(d) ((d)->ops->reloadnow(d)) +#define ESP32S2_TIM_GETALRVL(d, v) ((d)->ops->getalarmvalue(d, v)) +#define ESP32S2_TIM_SETALRVL(d, v) ((d)->ops->setalarmvalue(d, v)) +#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_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) +#define ESP32S2_TIM_ENABLEINT(d) ((d)->ops->enableint(d)) +#define ESP32S2_TIM_DISABLEINT(d) ((d)->ops->disableint(d)) +#define ESP32S2_TIM_ACKINT(d) ((d)->ops->ackint(d)) +#define ESP32S2_TIM_CHECKINT(d) ((d)->ops->checkint(d)) + +#define TIMER0 0 +#define TIMER1 1 +#define TIMER2 2 +#define TIMER3 3 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Timer mode */ + +enum esp32s2_tim_mode_e +{ + ESP32S2_TIM_MODE_DOWN, + ESP32S2_TIM_MODE_UP, +}; + +/* Timer mode */ + +enum esp32s2_tim_clksrc_e +{ + ESP32S2_TIM_APB_CLK, + ESP32S2_TIM_XTAL_CLK, +}; + +/* ESP32-S2 TIM device */ + +struct esp32s2_tim_dev_s +{ + struct esp32s2_tim_ops_s *ops; +}; + +/* ESP32-S2 TIM ops */ + +/* This is a struct containing the pointers to the timer operations */ + +struct esp32s2_tim_ops_s +{ + /* Timer tasks */ + + CODE void (*start)(FAR struct esp32s2_tim_dev_s *dev); + CODE void (*stop)(FAR struct esp32s2_tim_dev_s *dev); + CODE void (*clear)(FAR struct esp32s2_tim_dev_s *dev); + + /* Timer operations */ + + CODE void (*setmode)(FAR struct esp32s2_tim_dev_s *dev, + enum esp32s2_tim_mode_e mode); + CODE void (*setpre)(FAR struct esp32s2_tim_dev_s *dev, uint16_t pre); + CODE void (*getcounter)(FAR struct esp32s2_tim_dev_s *dev, + uint64_t *value); + CODE void (*setclksrc)(FAR struct esp32s2_tim_dev_s *dev, + enum esp32s2_tim_clksrc_e src); + CODE void (*setcounter)(FAR struct esp32s2_tim_dev_s *dev, uint64_t value); + CODE void (*reloadnow)(FAR struct esp32s2_tim_dev_s *dev); + CODE void (*getalarmvalue)(FAR struct esp32s2_tim_dev_s *dev, + uint64_t *value); + CODE void (*setalarmvalue)(FAR struct esp32s2_tim_dev_s *dev, + uint64_t value); + CODE void (*setalarm)(FAR struct esp32s2_tim_dev_s *dev, bool enable); + CODE void (*setautoreload)(FAR struct esp32s2_tim_dev_s *dev, bool enable); + + /* Timer interrupts */ + + CODE int (*setisr)(FAR struct esp32s2_tim_dev_s *dev, xcpt_t handler, + FAR void * arg); + CODE void (*enableint)(FAR struct esp32s2_tim_dev_s *dev); + CODE void (*disableint)(FAR struct esp32s2_tim_dev_s *dev); + CODE void (*ackint)(FAR struct esp32s2_tim_dev_s *dev); + CODE int (*checkint)(FAR struct esp32s2_tim_dev_s *dev); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +FAR struct esp32s2_tim_dev_s *esp32s2_tim_init(int timer); +void esp32s2_tim_deinit(FAR struct esp32s2_tim_dev_s *dev); + +#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_TIM_H */ diff --git a/arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.c b/arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.c new file mode 100644 index 00000000000..67f58c42241 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.c @@ -0,0 +1,595 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "hardware/esp32s2_soc.h" + +#include "esp32s2_tim.h" +#include "esp32s2_clockconfig.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct esp32s2_timer_lowerhalf_s +{ + FAR const struct timer_ops_s *ops; /* Lower half operations */ + FAR struct esp32s2_tim_dev_s *tim; /* esp32s2 timer driver */ + tccb_t callback; /* Interrupt callback */ + FAR void *arg; /* Argument passed to upper half callback */ + bool started; /* True: Timer has been started */ + FAR void *upper; /* Pointer to watchdog_upperhalf_s */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int esp32s2_timer_handler(int irq, FAR void *context, void *arg); + +/* "Lower half" driver methods **********************************************/ + +static int esp32s2_timer_start(FAR struct timer_lowerhalf_s *lower); +static int esp32s2_timer_stop(FAR struct timer_lowerhalf_s *lower); +static int esp32s2_timer_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status); +static int esp32s2_timer_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout); +static int esp32s2_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t *timeout); +static void esp32s2_timer_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_esp32s2_timer_ops = +{ + .start = esp32s2_timer_start, + .stop = esp32s2_timer_stop, + .getstatus = esp32s2_timer_getstatus, + .settimeout = esp32s2_timer_settimeout, + .setcallback = esp32s2_timer_setcallback, + .maxtimeout = esp32s2_timer_maxtimeout, + .ioctl = NULL, +}; + +#ifdef CONFIG_ESP32S2_TIMER0 + +/* TIMER0 lower-half */ + +static struct esp32s2_timer_lowerhalf_s g_esp32s2_timer0_lowerhalf = +{ + .ops = &g_esp32s2_timer_ops, +}; +#endif + +#ifdef CONFIG_ESP32S2_TIMER1 + +/* TIMER1 lower-half */ + +static struct esp32s2_timer_lowerhalf_s g_esp32s2_timer1_lowerhalf = +{ + .ops = &g_esp32s2_timer_ops, +}; +#endif + +#ifdef CONFIG_ESP32S2_TIMER2 + +/* TIMER2 lower-half */ + +static struct esp32s2_timer_lowerhalf_s g_esp32s2_timer2_lowerhalf = +{ + .ops = &g_esp32s2_timer_ops, +}; +#endif + +#ifdef CONFIG_ESP32S2_TIMER3 + +/* TIMER3 lower-half */ + +static struct esp32s2_timer_lowerhalf_s g_esp32s2_timer3_lowerhalf = +{ + .ops = &g_esp32s2_timer_ops, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_timer_handler + * + * Description: + * Timer interrupt handler + * + ****************************************************************************/ + +static int esp32s2_timer_handler(int irq, FAR void *context, void *arg) +{ + FAR struct esp32s2_timer_lowerhalf_s *priv = + (FAR struct esp32s2_timer_lowerhalf_s *)arg; + uint32_t next_interval_us = 0; + + if (priv->callback(&next_interval_us, priv->upper)) + { + if (next_interval_us > 0) + { + /* Set a value to the alarm */ + + ESP32S2_TIM_SETALRVL(priv->tim, next_interval_us); + } + } + else + { + esp32s2_timer_stop((struct timer_lowerhalf_s *)priv); + } + + ESP32S2_TIM_SETALRM(priv->tim, true); /* Re-enables the alarm */ + ESP32S2_TIM_ACKINT(priv->tim); /* Clear the Interrupt */ + return OK; +} + +/**************************************************************************** + * Name: esp32s2_timer_start + * + * Description: + * Start the timer, resetting the time to the current timeout + * + * Input Parameters: + * lower - A pointer to the representation of + * the "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int esp32s2_timer_start(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct esp32s2_timer_lowerhalf_s *priv = + (FAR struct esp32s2_timer_lowerhalf_s *)lower; + int ret = OK; + uint16_t pre; + irqstate_t flags; + + DEBUGASSERT(priv); + + if (priv->started == true) + { + /* Return EBUSY to indicate that the timer is already running */ + + ret = -EBUSY; + goto errout; + } + + /* Make sure the timer is stopped to avoid unpredictable behavior */ + + ESP32S2_TIM_STOP(priv->tim); + + /* Configure clock source */ + + ESP32S2_TIM_CLK_SRC(priv->tim, ESP32S2_TIM_APB_CLK); + + /* Calculate the suitable prescaler according to the current APB + * frequency to generate a period of 1 us. + */ + + pre = esp_clk_apb_freq() / 1000000; + + /* Configure TIMER prescaler */ + + ESP32S2_TIM_SETPRE(priv->tim, pre); + + /* Configure TIMER mode */ + + ESP32S2_TIM_SETMODE(priv->tim, ESP32S2_TIM_MODE_UP); + + /* Clear TIMER counter value */ + + ESP32S2_TIM_CLEAR(priv->tim); + + /* Enable autoreload */ + + ESP32S2_TIM_SETARLD(priv->tim, true); + + /* Enable TIMER alarm */ + + ESP32S2_TIM_SETALRM(priv->tim, true); + + /* Clear Interrupt Bits Status */ + + ESP32S2_TIM_ACKINT(priv->tim); + + /* Configure callback, in case a handler was provided before */ + + if (priv->callback != NULL) + { + flags = enter_critical_section(); + ret = ESP32S2_TIM_SETISR(priv->tim, esp32s2_timer_handler, priv); + leave_critical_section(flags); + if (ret != OK) + { + goto errout; + } + + ESP32S2_TIM_ENABLEINT(priv->tim); + } + + /* Finally, start the TIMER */ + + ESP32S2_TIM_START(priv->tim); + priv->started = true; + +errout: + return ret; +} + +/**************************************************************************** + * Name: esp32s2_timer_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int esp32s2_timer_stop(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct esp32s2_timer_lowerhalf_s *priv = + (FAR struct esp32s2_timer_lowerhalf_s *)lower; + int ret = OK; + irqstate_t flags; + + DEBUGASSERT(priv); + + if (priv->started == false) + { + /* Return ENODEV to indicate that the timer was not running */ + + ret = -ENODEV; + goto errout; + } + + if (priv->callback != NULL) + { + flags = enter_critical_section(); + ESP32S2_TIM_DISABLEINT(priv->tim); + ret = ESP32S2_TIM_SETISR(priv->tim, NULL, NULL); + leave_critical_section(flags); + priv->callback = NULL; + } + + ESP32S2_TIM_STOP(priv->tim); + priv->started = false; + +errout: + return ret; +} + +/**************************************************************************** + * Name: esp32s2_timer_getstatus + * + * Description: + * Get timer status. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int esp32s2_timer_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status) +{ + FAR struct esp32s2_timer_lowerhalf_s *priv = + (FAR struct esp32s2_timer_lowerhalf_s *)lower; + int ret = OK; + uint64_t current_counter_value; + uint64_t alarm_value; + + DEBUGASSERT(priv); + DEBUGASSERT(status); + + /* Return the status bit */ + + status->flags = 0; + + if (priv->started == true) + { + /* TIMER is running */ + + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback != NULL) + { + /* TIMER has a user callback function to be called when + * expiration happens + */ + + status->flags |= TCFLAGS_HANDLER; + } + + /* Get the current counter value */ + + ESP32S2_TIM_GETCTR(priv->tim, ¤t_counter_value); + + /* Get the current configured timeout */ + + ESP32S2_TIM_GETALRVL(priv->tim, &alarm_value); + + status->timeout = (uint32_t)(alarm_value); + status->timeleft = (uint32_t)(alarm_value - current_counter_value); + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_timer_settimeout + * + * Description: + * Set a new timeout value. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * timeout - The new timeout value in microseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int esp32s2_timer_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct esp32s2_timer_lowerhalf_s *priv = + (FAR struct esp32s2_timer_lowerhalf_s *)lower; + int ret = OK; + + DEBUGASSERT(priv); + + /* Set the timeout */ + + ESP32S2_TIM_SETALRVL(priv->tim, (uint64_t)timeout); + + return ret; +} + +/**************************************************************************** + * Name: esp32s2_timer_maxtimeout + * + * Description: + * Get the maximum timeout value + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * maxtimeout - A pointer to the variable that will store the max timeout. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int esp32s2_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t *max_timeout) +{ + DEBUGASSERT(max_timeout); + + *max_timeout = UINT32_MAX; + + return OK; +} + +/**************************************************************************** + * Name: esp32s2_setcallback + * + * Description: + * Set the provided callback to be called at timeout from withing the + * ISR. + * + * Input Parameters: + * lower - A pointer to the publicly visible representation of + * the "lower-half" driver state structure. + * callback - A pointer to the callback. If this function pointer + * is NULL, then the reset-on-expiration behavior is restored. + * arg - A pointer to the argument that will be provided to + * the callback + * + ****************************************************************************/ + +static void esp32s2_timer_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg) +{ + FAR struct esp32s2_timer_lowerhalf_s *priv = + (FAR struct esp32s2_timer_lowerhalf_s *)lower; + irqstate_t flags; + int ret = OK; + + DEBUGASSERT(priv); + + /* Save the new callback */ + + priv->callback = callback; + priv->arg = arg; + + flags = enter_critical_section(); + + /* There is a user callback and the timer has already been started */ + + if (callback != NULL && priv->started == true) + { + ret = ESP32S2_TIM_SETISR(priv->tim, esp32s2_timer_handler, priv); + ESP32S2_TIM_ENABLEINT(priv->tim); + } + else + { + ESP32S2_TIM_DISABLEINT(priv->tim); + ret = ESP32S2_TIM_SETISR(priv->tim, NULL, NULL); + } + + leave_critical_section(flags); + if (ret != OK) + { + tmrerr("Error to set ISR: %d", ret); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timerx. + * timer - the timer's number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int esp32s2_timer_initialize(FAR const char *devpath, uint8_t timer) +{ + struct esp32s2_timer_lowerhalf_s *lower = NULL; + int ret = OK; + + DEBUGASSERT(devpath); + + switch (timer) + { +#ifdef CONFIG_ESP32S2_TIMER0 + case TIMER0: + { + lower = &g_esp32s2_timer0_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER1 + case TIMER1: + { + lower = &g_esp32s2_timer1_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER2 + case TIMER2: + { + lower = &g_esp32s2_timer2_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER3 + case TIMER3: + { + lower = &g_esp32s2_timer3_lowerhalf; + break; + } +#endif + + default: + { + ret = -ENODEV; + goto errout; + } + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = esp32s2_tim_init(timer); + + if (lower->tim == NULL) + { + ret = -EINVAL; + goto errout; + } + + /* Register the timer driver as /dev/timerX. The returned value from + * timer_register is a handle that could be used with timer_unregister(). + * REVISIT: The returned handle is discarded here. + */ + + lower->upper = timer_register(devpath, + (FAR struct timer_lowerhalf_s *)lower); + if (lower->upper == NULL) + { + /* The actual cause of the failure may have been a failure to allocate + * perhaps a failure to register the timer driver (such as if the + * 'devpath' were not unique). We know here but we return EEXIST to + * indicate the failure (implying the non-unique devpath). + */ + + ret = -EEXIST; + goto errout; + } + +errout: + return ret; +} diff --git a/arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.h b/arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.h new file mode 100644 index 00000000000..77b7c381792 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_tim_lowerhalf.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_TIM_LOWERHALF_H +#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_TIM_LOWERHALF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s2_timer_initialize + ****************************************************************************/ + +int esp32s2_timer_initialize(FAR const char *devpath, uint8_t timer); + +#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_TIM_LOWERHALF_H */ diff --git a/arch/xtensa/src/esp32s2/hardware/esp32s2_tim.h b/arch/xtensa/src/esp32s2/hardware/esp32s2_tim.h index 52bfe4d6295..03479c4d712 100644 --- a/arch/xtensa/src/esp32s2/hardware/esp32s2_tim.h +++ b/arch/xtensa/src/esp32s2/hardware/esp32s2_tim.h @@ -31,11 +31,13 @@ * Pre-processor Definitions ****************************************************************************/ -/* TIMG_T0CONFIG_REG register +#define SHIFT_32 32 + +/* TIMG_T0CONFIG_REG(i) register * Timer 0 configuration register */ -#define TIMG_T0CONFIG_REG (DR_REG_TIMG_BASE + 0x0) +#define TIMG_T0CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0) /* TIMG_T0_EN : R/W; bitpos: [31]; default: 0; * When set, the timer 0 time-base counter is enabled. @@ -115,14 +117,14 @@ #define TIMG_T0_USE_XTAL_V 0x00000001 #define TIMG_T0_USE_XTAL_S 9 -/* TIMG_T0LO_REG register +/* TIMG_T0LO_REG(i) register * Timer 0 current value, low 32 bits */ -#define TIMG_T0LO_REG (DR_REG_TIMG_BASE + 0x4) +#define TIMG_T0LO_REG(i) (REG_TIMG_BASE(i) + 0x4) /* TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; - * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base + * After writing to TIMG_T0UPDATE_REG(i), the low 32 bits of the time-base * counter * * of timer 0 can be read here. @@ -133,14 +135,14 @@ #define TIMG_T0_LO_V 0xFFFFFFFF #define TIMG_T0_LO_S 0 -/* TIMG_T0HI_REG register +/* TIMG_T0HI_REG(i) register * Timer 0 current value, high 32 bits */ -#define TIMG_T0HI_REG (DR_REG_TIMG_BASE + 0x8) +#define TIMG_T0HI_REG(i) (REG_TIMG_BASE(i) + 0x8) /* TIMG_T0_HI : RO; bitpos: [31:0]; default: 0; - * After writing to TIMG_T0UPDATE_REG, the high 32 bits of the time-base + * After writing to TIMG_T0UPDATE_REG(i), the high 32 bits of the time-base * counter * * of timer 0 can be read here. @@ -151,14 +153,15 @@ #define TIMG_T0_HI_V 0xFFFFFFFF #define TIMG_T0_HI_S 0 -/* TIMG_T0UPDATE_REG register - * Write to copy current timer value to TIMGn_T0_(LO/HI)_REG +/* TIMG_T0UPDATE_REG(i) register + * Write to copy current timer value to TIMGn_T0_(LO/HI)_REG(i) */ -#define TIMG_T0UPDATE_REG (DR_REG_TIMG_BASE + 0xc) +#define TIMG_T0UPDATE_REG(i) (REG_TIMG_BASE(i) + 0xc) /* TIMG_T0_UPDATE : R/W; bitpos: [31]; default: 0; - * After writing 0 or 1 to TIMG_T0UPDATE_REG, the counter value is latched. + * After writing 0 or 1 to TIMG_T0UPDATE_REG(i), the counter value + * is latched. */ #define TIMG_T0_UPDATE (BIT(31)) @@ -166,11 +169,11 @@ #define TIMG_T0_UPDATE_V 0x00000001 #define TIMG_T0_UPDATE_S 31 -/* TIMG_T0ALARMLO_REG register +/* TIMG_T0ALARMLO_REG(i) register * Timer 0 alarm value, low 32 bits */ -#define TIMG_T0ALARMLO_REG (DR_REG_TIMG_BASE + 0x10) +#define TIMG_T0ALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x10) /* TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Timer 0 alarm trigger time-base counter value, low 32 bits. @@ -181,11 +184,11 @@ #define TIMG_T0_ALARM_LO_V 0xFFFFFFFF #define TIMG_T0_ALARM_LO_S 0 -/* TIMG_T0ALARMHI_REG register +/* TIMG_T0ALARMHI_REG(i) register * Timer 0 alarm value, high bits */ -#define TIMG_T0ALARMHI_REG (DR_REG_TIMG_BASE + 0x14) +#define TIMG_T0ALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x14) /* TIMG_T0_ALARM_HI : R/W; bitpos: [31:0]; default: 0; * @@ -198,11 +201,11 @@ #define TIMG_T0_ALARM_HI_V 0xFFFFFFFF #define TIMG_T0_ALARM_HI_S 0 -/* TIMG_T0LOADLO_REG register +/* TIMG_T0LOADLO_REG(i) register * Timer 0 reload value, low 32 bits */ -#define TIMG_T0LOADLO_REG (DR_REG_TIMG_BASE + 0x18) +#define TIMG_T0LOADLO_REG(i) (REG_TIMG_BASE(i) + 0x18) /* TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * @@ -217,11 +220,11 @@ #define TIMG_T0_LOAD_LO_V 0xFFFFFFFF #define TIMG_T0_LOAD_LO_S 0 -/* TIMG_T0LOADHI_REG register +/* TIMG_T0LOADHI_REG(i) register * Timer 0 reload value, high 32 bits */ -#define TIMG_T0LOADHI_REG (DR_REG_TIMG_BASE + 0x1c) +#define TIMG_T0LOADHI_REG(i) (REG_TIMG_BASE(i) + 0x1c) /* TIMG_T0_LOAD_HI : R/W; bitpos: [31:0]; default: 0; * @@ -236,11 +239,11 @@ #define TIMG_T0_LOAD_HI_V 0xFFFFFFFF #define TIMG_T0_LOAD_HI_S 0 -/* TIMG_T0LOAD_REG register - * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG +/* TIMG_T0LOAD_REG(i) register + * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG(i) */ -#define TIMG_T0LOAD_REG (DR_REG_TIMG_BASE + 0x20) +#define TIMG_T0LOAD_REG(i) (REG_TIMG_BASE(i) + 0x20) /* TIMG_T0_LOAD : WO; bitpos: [31:0]; default: 0; * @@ -253,11 +256,11 @@ #define TIMG_T0_LOAD_V 0xFFFFFFFF #define TIMG_T0_LOAD_S 0 -/* TIMG_T1CONFIG_REG register +/* TIMG_T1CONFIG_REG(i) register * Timer 1 configuration register */ -#define TIMG_T1CONFIG_REG (DR_REG_TIMG_BASE + 0x24) +#define TIMG_T1CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x24) /* TIMG_T1_EN : R/W; bitpos: [31]; default: 0; * When set, the timer 1 time-base counter is enabled. @@ -337,14 +340,14 @@ #define TIMG_T1_USE_XTAL_V 0x00000001 #define TIMG_T1_USE_XTAL_S 9 -/* TIMG_T1LO_REG register +/* TIMG_T1LO_REG(i) register * Timer 1 current value, low 32 bits */ -#define TIMG_T1LO_REG (DR_REG_TIMG_BASE + 0x28) +#define TIMG_T1LO_REG(i) (REG_TIMG_BASE(i) + 0x28) /* TIMG_T1_LO : RO; bitpos: [31:0]; default: 0; - * After writing to TIMG_T1UPDATE_REG, the low 32 bits of the time-base + * After writing to TIMG_T1UPDATE_REG(i), the low 32 bits of the time-base * counter * * of timer 1 can be read here. @@ -355,14 +358,14 @@ #define TIMG_T1_LO_V 0xFFFFFFFF #define TIMG_T1_LO_S 0 -/* TIMG_T1HI_REG register +/* TIMG_T1HI_REG(i) register * Timer 1 current value, high 32 bits */ -#define TIMG_T1HI_REG (DR_REG_TIMG_BASE + 0x2c) +#define TIMG_T1HI_REG(i) (REG_TIMG_BASE(i) + 0x2c) /* TIMG_T1_HI : RO; bitpos: [31:0]; default: 0; - * After writing to TIMG_T1UPDATE_REG, the high 32 bits of the time-base + * After writing to TIMG_T1UPDATE_REG(i), the high 32 bits of the time-base * counter * * of timer 1 can be read here. @@ -373,14 +376,15 @@ #define TIMG_T1_HI_V 0xFFFFFFFF #define TIMG_T1_HI_S 0 -/* TIMG_T1UPDATE_REG register - * Write to copy current timer value to TIMGn_T1_(LO/HI)_REG +/* TIMG_T1UPDATE_REG(i) register + * Write to copy current timer value to TIMGn_T1_(LO/HI)_REG(i) */ -#define TIMG_T1UPDATE_REG (DR_REG_TIMG_BASE + 0x30) +#define TIMG_T1UPDATE_REG(i) (REG_TIMG_BASE(i) + 0x30) /* TIMG_T1_UPDATE : R/W; bitpos: [31]; default: 0; - * After writing 0 or 1 to TIMG_T1UPDATE_REG, the counter value is latched. + * After writing 0 or 1 to TIMG_T1UPDATE_REG(i), the counter value + * is latched. */ #define TIMG_T1_UPDATE (BIT(31)) @@ -388,11 +392,11 @@ #define TIMG_T1_UPDATE_V 0x00000001 #define TIMG_T1_UPDATE_S 31 -/* TIMG_T1ALARMLO_REG register +/* TIMG_T1ALARMLO_REG(i) register * Timer 1 alarm value, low 32 bits */ -#define TIMG_T1ALARMLO_REG (DR_REG_TIMG_BASE + 0x34) +#define TIMG_T1ALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x34) /* TIMG_T1_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Timer 1 alarm trigger time-base counter value, low 32 bits. @@ -403,11 +407,11 @@ #define TIMG_T1_ALARM_LO_V 0xFFFFFFFF #define TIMG_T1_ALARM_LO_S 0 -/* TIMG_T1ALARMHI_REG register +/* TIMG_T1ALARMHI_REG(i) register * Timer 1 alarm value, high bits */ -#define TIMG_T1ALARMHI_REG (DR_REG_TIMG_BASE + 0x38) +#define TIMG_T1ALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x38) /* TIMG_T1_ALARM_HI : R/W; bitpos: [31:0]; default: 0; * @@ -420,11 +424,11 @@ #define TIMG_T1_ALARM_HI_V 0xFFFFFFFF #define TIMG_T1_ALARM_HI_S 0 -/* TIMG_T1LOADLO_REG register +/* TIMG_T1LOADLO_REG(i) register * Timer 1 reload value, low 32 bits */ -#define TIMG_T1LOADLO_REG (DR_REG_TIMG_BASE + 0x3c) +#define TIMG_T1LOADLO_REG(i) (REG_TIMG_BASE(i) + 0x3c) /* TIMG_T1_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * @@ -439,11 +443,11 @@ #define TIMG_T1_LOAD_LO_V 0xFFFFFFFF #define TIMG_T1_LOAD_LO_S 0 -/* TIMG_T1LOADHI_REG register +/* TIMG_T1LOADHI_REG(i) register * Timer 1 reload value, high 32 bits */ -#define TIMG_T1LOADHI_REG (DR_REG_TIMG_BASE + 0x40) +#define TIMG_T1LOADHI_REG(i) (REG_TIMG_BASE(i) + 0x40) /* TIMG_T1_LOAD_HI : R/W; bitpos: [31:0]; default: 0; * @@ -458,11 +462,11 @@ #define TIMG_T1_LOAD_HI_V 0xFFFFFFFF #define TIMG_T1_LOAD_HI_S 0 -/* TIMG_T1LOAD_REG register - * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG +/* TIMG_T1LOAD_REG(i) register + * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG(i) */ -#define TIMG_T1LOAD_REG (DR_REG_TIMG_BASE + 0x44) +#define TIMG_T1LOAD_REG(i) (REG_TIMG_BASE(i) + 0x44) /* TIMG_T1_LOAD : WO; bitpos: [31:0]; default: 0; * @@ -475,11 +479,11 @@ #define TIMG_T1_LOAD_V 0xFFFFFFFF #define TIMG_T1_LOAD_S 0 -/* TIMG_WDTCONFIG0_REG register +/* TIMG_WDTCONFIG0_REG(i) register * Watchdog timer configuration register */ -#define TIMG_WDTCONFIG0_REG (DR_REG_TIMG_BASE + 0x48) +#define TIMG_WDTCONFIG0_REG(i) (REG_TIMG_BASE(i) + 0x48) /* TIMG_WDT_EN : R/W; bitpos: [31]; default: 0; * When set, MWDT is enabled. @@ -605,11 +609,11 @@ #define TIMG_WDT_APPCPU_RESET_EN_V 0x00000001 #define TIMG_WDT_APPCPU_RESET_EN_S 12 -/* TIMG_WDTCONFIG1_REG register +/* TIMG_WDTCONFIG1_REG(i) register * Watchdog timer prescaler register */ -#define TIMG_WDTCONFIG1_REG (DR_REG_TIMG_BASE + 0x4c) +#define TIMG_WDTCONFIG1_REG(i) (REG_TIMG_BASE(i) + 0x4c) /* TIMG_WDT_CLK_PRESCALER : R/W; bitpos: [31:16]; default: 1; * MWDT clock prescaler value. MWDT clock period = 12.5 ns * @@ -622,11 +626,11 @@ #define TIMG_WDT_CLK_PRESCALER_V 0x0000FFFF #define TIMG_WDT_CLK_PRESCALER_S 16 -/* TIMG_WDTCONFIG2_REG register +/* TIMG_WDTCONFIG2_REG(i) register * Watchdog timer stage 0 timeout value */ -#define TIMG_WDTCONFIG2_REG (DR_REG_TIMG_BASE + 0x50) +#define TIMG_WDTCONFIG2_REG(i) (REG_TIMG_BASE(i) + 0x50) /* TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; * Stage 0 timeout value, in MWDT clock cycles. @@ -637,11 +641,11 @@ #define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFF #define TIMG_WDT_STG0_HOLD_S 0 -/* TIMG_WDTCONFIG3_REG register +/* TIMG_WDTCONFIG3_REG(i) register * Watchdog timer stage 1 timeout value */ -#define TIMG_WDTCONFIG3_REG (DR_REG_TIMG_BASE + 0x54) +#define TIMG_WDTCONFIG3_REG(i) (REG_TIMG_BASE(i) + 0x54) /* TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; * Stage 1 timeout value, in MWDT clock cycles. @@ -652,11 +656,11 @@ #define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFF #define TIMG_WDT_STG1_HOLD_S 0 -/* TIMG_WDTCONFIG4_REG register +/* TIMG_WDTCONFIG4_REG(i) register * Watchdog timer stage 2 timeout value */ -#define TIMG_WDTCONFIG4_REG (DR_REG_TIMG_BASE + 0x58) +#define TIMG_WDTCONFIG4_REG(i) (REG_TIMG_BASE(i) + 0x58) /* TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 2 timeout value, in MWDT clock cycles. @@ -667,11 +671,11 @@ #define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFF #define TIMG_WDT_STG2_HOLD_S 0 -/* TIMG_WDTCONFIG5_REG register +/* TIMG_WDTCONFIG5_REG(i) register * Watchdog timer stage 3 timeout value */ -#define TIMG_WDTCONFIG5_REG (DR_REG_TIMG_BASE + 0x5c) +#define TIMG_WDTCONFIG5_REG(i) (REG_TIMG_BASE(i) + 0x5c) /* TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; * Stage 3 timeout value, in MWDT clock cycles. @@ -682,11 +686,11 @@ #define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFF #define TIMG_WDT_STG3_HOLD_S 0 -/* TIMG_WDTFEED_REG register +/* TIMG_WDTFEED_REG(i) register * Write to feed the watchdog timer */ -#define TIMG_WDTFEED_REG (DR_REG_TIMG_BASE + 0x60) +#define TIMG_WDTFEED_REG(i) (REG_TIMG_BASE(i) + 0x60) /* TIMG_WDT_FEED : WO; bitpos: [31:0]; default: 0; * Write any value to feed the MWDT. (WO) @@ -697,11 +701,11 @@ #define TIMG_WDT_FEED_V 0xFFFFFFFF #define TIMG_WDT_FEED_S 0 -/* TIMG_WDTWPROTECT_REG register +/* TIMG_WDTWPROTECT_REG(i) register * Watchdog write protect register */ -#define TIMG_WDTWPROTECT_REG (DR_REG_TIMG_BASE + 0x64) +#define TIMG_WDTWPROTECT_REG(i) (REG_TIMG_BASE(i) + 0x64) /* TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; * If the register contains a different value than its reset value, write @@ -714,86 +718,11 @@ #define TIMG_WDT_WKEY_V 0xFFFFFFFF #define TIMG_WDT_WKEY_S 0 -/* TIMG_RTCCALICFG_REG register - * RTC calibration configuration register - */ - -#define TIMG_RTCCALICFG_REG (DR_REG_TIMG_BASE + 0x68) - -/* TIMG_RTC_CALI_START : R/W; bitpos: [31]; default: 0; - * Reserved - */ - -#define TIMG_RTC_CALI_START (BIT(31)) -#define TIMG_RTC_CALI_START_M (TIMG_RTC_CALI_START_V << TIMG_RTC_CALI_START_S) -#define TIMG_RTC_CALI_START_V 0x00000001 -#define TIMG_RTC_CALI_START_S 31 - -/* TIMG_RTC_CALI_MAX : R/W; bitpos: [30:16]; default: 1; - * Reserved - */ - -#define TIMG_RTC_CALI_MAX 0x00007FFF -#define TIMG_RTC_CALI_MAX_M (TIMG_RTC_CALI_MAX_V << TIMG_RTC_CALI_MAX_S) -#define TIMG_RTC_CALI_MAX_V 0x00007FFF -#define TIMG_RTC_CALI_MAX_S 16 - -/* TIMG_RTC_CALI_RDY : RO; bitpos: [15]; default: 0; - * Reserved - */ - -#define TIMG_RTC_CALI_RDY (BIT(15)) -#define TIMG_RTC_CALI_RDY_M (TIMG_RTC_CALI_RDY_V << TIMG_RTC_CALI_RDY_S) -#define TIMG_RTC_CALI_RDY_V 0x00000001 -#define TIMG_RTC_CALI_RDY_S 15 - -/* TIMG_RTC_CALI_CLK_SEL : R/W; bitpos: [14:13]; default: 1; - * 0:rtcslowclock. 1:clk_80m. 2:xtal_32k. - */ - -#define TIMG_RTC_CALI_CLK_SEL 0x00000003 -#define TIMG_RTC_CALI_CLK_SEL_M (TIMG_RTC_CALI_CLK_SEL_V << TIMG_RTC_CALI_CLK_SEL_S) -#define TIMG_RTC_CALI_CLK_SEL_V 0x00000003 -#define TIMG_RTC_CALI_CLK_SEL_S 13 - -/* TIMG_RTC_CALI_START_CYCLING : R/W; bitpos: [12]; default: 1; - * Reserved - */ - -#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_M (TIMG_RTC_CALI_START_CYCLING_V << TIMG_RTC_CALI_START_CYCLING_S) -#define TIMG_RTC_CALI_START_CYCLING_V 0x00000001 -#define TIMG_RTC_CALI_START_CYCLING_S 12 - -/* TIMG_RTCCALICFG1_REG register - * RTC calibration configuration1 register - */ - -#define TIMG_RTCCALICFG1_REG (DR_REG_TIMG_BASE + 0x6c) - -/* TIMG_RTC_CALI_VALUE : RO; bitpos: [31:7]; default: 0; - * Reserved - */ - -#define TIMG_RTC_CALI_VALUE 0x01FFFFFF -#define TIMG_RTC_CALI_VALUE_M (TIMG_RTC_CALI_VALUE_V << TIMG_RTC_CALI_VALUE_S) -#define TIMG_RTC_CALI_VALUE_V 0x01FFFFFF -#define TIMG_RTC_CALI_VALUE_S 7 - -/* TIMG_RTC_CALI_CYCLING_DATA_VLD : RO; bitpos: [0]; default: 0; - * Reserved - */ - -#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (TIMG_RTC_CALI_CYCLING_DATA_VLD_V << TIMG_RTC_CALI_CYCLING_DATA_VLD_S) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x00000001 -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_S 0 - -/* TIMG_LACTCONFIG_REG register +/* TIMG_LACTCONFIG_REG(i) register * LACT configuration register */ -#define TIMG_LACTCONFIG_REG (DR_REG_TIMG_BASE + 0x70) +#define TIMG_LACTCONFIG_REG(i) (REG_TIMG_BASE(i) + 0x70) /* TIMG_LACT_EN : R/W; bitpos: [31]; default: 0; * Reserved @@ -894,11 +823,11 @@ #define TIMG_LACT_USE_REFTICK_V 0x00000001 #define TIMG_LACT_USE_REFTICK_S 6 -/* TIMG_LACTRTC_REG register +/* TIMG_LACTRTC_REG(i) register * LACT RTC register */ -#define TIMG_LACTRTC_REG (DR_REG_TIMG_BASE + 0x74) +#define TIMG_LACTRTC_REG(i) (REG_TIMG_BASE(i) + 0x74) /* TIMG_LACT_RTC_STEP_LEN : R/W; bitpos: [31:6]; default: 0; * Reserved @@ -909,11 +838,11 @@ #define TIMG_LACT_RTC_STEP_LEN_V 0x03FFFFFF #define TIMG_LACT_RTC_STEP_LEN_S 6 -/* TIMG_LACTLO_REG register +/* TIMG_LACTLO_REG(i) register * LACT low register */ -#define TIMG_LACTLO_REG (DR_REG_TIMG_BASE + 0x78) +#define TIMG_LACTLO_REG(i) (REG_TIMG_BASE(i) + 0x78) /* TIMG_LACT_LO : RO; bitpos: [31:0]; default: 0; * Reserved @@ -924,11 +853,11 @@ #define TIMG_LACT_LO_V 0xFFFFFFFF #define TIMG_LACT_LO_S 0 -/* TIMG_LACTHI_REG register +/* TIMG_LACTHI_REG(i) register * LACT high register */ -#define TIMG_LACTHI_REG (DR_REG_TIMG_BASE + 0x7c) +#define TIMG_LACTHI_REG(i) (REG_TIMG_BASE(i) + 0x7c) /* TIMG_LACT_HI : RO; bitpos: [31:0]; default: 0; * Reserved @@ -939,11 +868,11 @@ #define TIMG_LACT_HI_V 0xFFFFFFFF #define TIMG_LACT_HI_S 0 -/* TIMG_LACTUPDATE_REG register +/* TIMG_LACTUPDATE_REG(i) register * LACT update register */ -#define TIMG_LACTUPDATE_REG (DR_REG_TIMG_BASE + 0x80) +#define TIMG_LACTUPDATE_REG(i) (REG_TIMG_BASE(i) + 0x80) /* TIMG_LACT_UPDATE : WO; bitpos: [31:0]; default: 0; * Reserved @@ -954,11 +883,11 @@ #define TIMG_LACT_UPDATE_V 0xFFFFFFFF #define TIMG_LACT_UPDATE_S 0 -/* TIMG_LACTALARMLO_REG register +/* TIMG_LACTALARMLO_REG(i) register * LACT alarm low register */ -#define TIMG_LACTALARMLO_REG (DR_REG_TIMG_BASE + 0x84) +#define TIMG_LACTALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x84) /* TIMG_LACT_ALARM_LO : R/W; bitpos: [31:0]; default: 0; * Reserved @@ -969,11 +898,11 @@ #define TIMG_LACT_ALARM_LO_V 0xFFFFFFFF #define TIMG_LACT_ALARM_LO_S 0 -/* TIMG_LACTALARMHI_REG register +/* TIMG_LACTALARMHI_REG(i) register * LACT alarm high register */ -#define TIMG_LACTALARMHI_REG (DR_REG_TIMG_BASE + 0x88) +#define TIMG_LACTALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x88) /* TIMG_LACT_ALARM_HI : R/W; bitpos: [31:0]; default: 0; * Reserved @@ -984,11 +913,11 @@ #define TIMG_LACT_ALARM_HI_V 0xFFFFFFFF #define TIMG_LACT_ALARM_HI_S 0 -/* TIMG_LACTLOADLO_REG register +/* TIMG_LACTLOADLO_REG(i) register * LACT load low register */ -#define TIMG_LACTLOADLO_REG (DR_REG_TIMG_BASE + 0x8c) +#define TIMG_LACTLOADLO_REG(i) (REG_TIMG_BASE(i) + 0x8c) /* TIMG_LACT_LOAD_LO : R/W; bitpos: [31:0]; default: 0; * Reserved @@ -999,11 +928,11 @@ #define TIMG_LACT_LOAD_LO_V 0xFFFFFFFF #define TIMG_LACT_LOAD_LO_S 0 -/* TIMG_LACTLOADHI_REG register +/* TIMG_LACTLOADHI_REG(i) register * Timer LACT load high register */ -#define TIMG_LACTLOADHI_REG (DR_REG_TIMG_BASE + 0x90) +#define TIMG_LACTLOADHI_REG(i) (REG_TIMG_BASE(i) + 0x90) /* TIMG_LACT_LOAD_HI : R/W; bitpos: [31:0]; default: 0; * Reserved @@ -1014,11 +943,11 @@ #define TIMG_LACT_LOAD_HI_V 0xFFFFFFFF #define TIMG_LACT_LOAD_HI_S 0 -/* TIMG_LACTLOAD_REG register +/* TIMG_LACTLOAD_REG(i) register * Timer LACT load register */ -#define TIMG_LACTLOAD_REG (DR_REG_TIMG_BASE + 0x94) +#define TIMG_LACTLOAD_REG(i) (REG_TIMG_BASE(i) + 0x94) /* TIMG_LACT_LOAD : WO; bitpos: [31:0]; default: 0; * Reserved @@ -1029,11 +958,11 @@ #define TIMG_LACT_LOAD_V 0xFFFFFFFF #define TIMG_LACT_LOAD_S 0 -/* TIMG_INT_ENA_TIMERS_REG register +/* TIMG_INT_ENA_TIMERS_REG(i) register * Interrupt enable bits */ -#define TIMG_INT_ENA_TIMERS_REG (DR_REG_TIMG_BASE + 0x98) +#define TIMG_INT_ENA_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x98) /* TIMG_LACT_INT_ENA : R/W; bitpos: [3]; default: 0; * The interrupt enable bit for the TIMG_LACT_INT interrupt. @@ -1071,11 +1000,11 @@ #define TIMG_T0_INT_ENA_V 0x00000001 #define TIMG_T0_INT_ENA_S 0 -/* TIMG_INT_RAW_TIMERS_REG register +/* TIMG_INT_RAW_TIMERS_REG(i) register * Raw interrupt status */ -#define TIMG_INT_RAW_TIMERS_REG (DR_REG_TIMG_BASE + 0x9c) +#define TIMG_INT_RAW_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x9c) /* TIMG_LACT_INT_RAW : RO; bitpos: [3]; default: 0; * The raw interrupt status bit for the TIMG_LACT_INT interrupt. @@ -1113,11 +1042,11 @@ #define TIMG_T0_INT_RAW_V 0x00000001 #define TIMG_T0_INT_RAW_S 0 -/* TIMG_INT_ST_TIMERS_REG register +/* TIMG_INT_ST_TIMERS_REG(i) register * Masked interrupt status */ -#define TIMG_INT_ST_TIMERS_REG (DR_REG_TIMG_BASE + 0xa0) +#define TIMG_INT_ST_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0xa0) /* TIMG_LACT_INT_ST : RO; bitpos: [3]; default: 0; * The masked interrupt status bit for the TIMG_LACT_INT interrupt. @@ -1155,11 +1084,11 @@ #define TIMG_T0_INT_ST_V 0x00000001 #define TIMG_T0_INT_ST_S 0 -/* TIMG_INT_CLR_TIMERS_REG register +/* TIMG_INT_CLR_TIMERS_REG(i) register * Interrupt clear bits */ -#define TIMG_INT_CLR_TIMERS_REG (DR_REG_TIMG_BASE + 0xa4) +#define TIMG_INT_CLR_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0xa4) /* TIMG_LACT_INT_CLR : WO; bitpos: [3]; default: 0; * Set this bit to clear the TIMG_LACT_INT interrupt. @@ -1197,11 +1126,11 @@ #define TIMG_T0_INT_CLR_V 0x00000001 #define TIMG_T0_INT_CLR_S 0 -/* TIMG_RTCCALICFG2_REG register +/* TIMG_RTCCALICFG2_REG(i) register * Timer group calibration register */ -#define TIMG_RTCCALICFG2_REG (DR_REG_TIMG_BASE + 0xa8) +#define TIMG_RTCCALICFG2_REG(i) (REG_TIMG_BASE(i) + 0xa8) /* TIMG_RTC_CALI_TIMEOUT_THRES : R/W; bitpos: [31:7]; default: 33554431; * Threshold value for the RTC calibration timer. If the calibration timer's @@ -1231,11 +1160,11 @@ #define TIMG_RTC_CALI_TIMEOUT_V 0x00000001 #define TIMG_RTC_CALI_TIMEOUT_S 0 -/* TIMG_TIMERS_DATE_REG register +/* TIMG_TIMERS_DATE_REG(i) register * Version control register */ -#define TIMG_TIMERS_DATE_REG (DR_REG_TIMG_BASE + 0xf8) +#define TIMG_TIMERS_DATE_REG(i) (REG_TIMG_BASE(i) + 0xf8) /* TIMG_TIMERS_DATE : R/W; bitpos: [27:0]; default: 26243681; * Version control register. @@ -1246,11 +1175,11 @@ #define TIMG_TIMERS_DATE_V 0x0FFFFFFF #define TIMG_TIMERS_DATE_S 0 -/* TIMG_REGCLK_REG register +/* TIMG_REG(i)CLK_REG(i) register * Timer group clock gate register */ -#define TIMG_REGCLK_REG (DR_REG_TIMG_BASE + 0xfc) +#define TIMG_REG(i)CLK_REG(i) (REG_TIMG_BASE(i) + 0xfc) /* TIMG_CLK_EN : R/W; bitpos: [31]; default: 0; * Register clock gate signal. 1: Registers can be read and written to by diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/configs/timer/defconfig b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/timer/defconfig new file mode 100644 index 00000000000..71a9668092c --- /dev/null +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/timer/defconfig @@ -0,0 +1,56 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s2-saola-1" +CONFIG_ARCH_BOARD_ESP32S2_SAOLA_1=y +CONFIG_ARCH_CHIP="esp32s2" +CONFIG_ARCH_CHIP_ESP32S2=y +CONFIG_ARCH_CHIP_ESP32S2WROVER=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEV_GPIO=y +CONFIG_ESP32S2_DATA_CACHE_0KB=y +CONFIG_ESP32S2_GPIO_IRQ=y +CONFIG_ESP32S2_TIMER0=y +CONFIG_ESP32S2_TIMER1=y +CONFIG_ESP32S2_TIMER2=y +CONFIG_ESP32S2_TIMER3=y +CONFIG_ESP32S2_UART0=y +CONFIG_EXAMPLES_TIMER=y +CONFIG_EXAMPLES_TIMER_GPOUT=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_TIMER=y +CONFIG_TIMER_ARCH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h index 740100db058..b014312c42e 100644 --- a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2-saola-1.h @@ -39,6 +39,13 @@ #define BUTTON_BOOT 0 +/* TIMERS */ + +#define TIMER0 0 +#define TIMER1 1 +#define TIMER2 2 +#define TIMER3 3 + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c index 92a7c657c12..42eab288f66 100644 --- a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c @@ -46,6 +46,10 @@ # include #endif +#ifdef CONFIG_TIMER +# include "esp32s2_tim_lowerhalf.h" +#endif + #include "esp32s2-saola-1.h" /**************************************************************************** @@ -100,6 +104,56 @@ int esp32s2_bringup(void) } #endif + /* Register the timer drivers */ + +#ifdef CONFIG_TIMER + +#ifdef CONFIG_ESP32S2_TIMER0 + ret = esp32s2_timer_initialize("/dev/timer0", TIMER0); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer driver: %d\n", + ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER1 + ret = esp32s2_timer_initialize("/dev/timer1", TIMER1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer driver: %d\n", + ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER2 + ret = esp32s2_timer_initialize("/dev/timer2", TIMER2); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer driver: %d\n", + ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP32S2_TIMER3 + ret = esp32s2_timer_initialize("/dev/timer3", TIMER3); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer driver: %d\n", + ret); + return ret; + } +#endif + +#endif /* CONFIG_TIMER */ + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities.