diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig index 9d05fc56318..d44fe5f175b 100644 --- a/arch/risc-v/src/esp32c3/Kconfig +++ b/arch/risc-v/src/esp32c3/Kconfig @@ -157,6 +157,10 @@ config ESP32C3_UART bool default n +config ESP32C3_TIMER + bool + default n + config ESP32C3_WDT bool default n @@ -178,6 +182,20 @@ config ESP32C3_UART1 select ESP32C3_UART select UART1_SERIALDRIVER +config ESP32C3_TIMER0 + bool "54-bit Timer 0 (Group 0 Timer 0)" + default n + select ESP32C3_TIMER + ---help--- + Enables Timer 0 + +config ESP32C3_TIMER1 + bool "54-bit Timer 0 (Group 1 Timer 0)" + default n + select ESP32C3_TIMER + ---help--- + Enables Timer 1 + config ESP32C3_MWDT0 bool "Main System Watchdog Timer (Group 0)" default n diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs index e53635caabb..dc2db38e660 100644 --- a/arch/risc-v/src/esp32c3/Make.defs +++ b/arch/risc-v/src/esp32c3/Make.defs @@ -65,3 +65,10 @@ ifeq ($(CONFIG_WATCHDOG),y) CHIP_CSRCS += esp32c3_wdt_lowerhalf.c endif endif + +ifeq ($(CONFIG_ESP32C3_TIMER),y) +CHIP_CSRCS += esp32c3_tim.c +ifeq ($(CONFIG_TIMER),y) +CHIP_CSRCS += esp32c3_tim_lowerhalf.c +endif +endif \ No newline at end of file diff --git a/arch/risc-v/src/esp32c3/esp32c3_tim.c b/arch/risc-v/src/esp32c3/esp32c3_tim.c new file mode 100644 index 00000000000..f0ce44f3295 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_tim.c @@ -0,0 +1,740 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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 "riscv_arch.h" +#include "hardware/esp32c3_tim.h" + +#include "esp32c3_tim.h" +#include "esp32c3_irq.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct esp32c3_tim_priv_s +{ + FAR struct esp32c3_tim_ops_s *ops; + uint8_t id; /* Timer instance */ + 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 esp32c3_tim_start(FAR struct esp32c3_tim_dev_s *dev); +static void esp32c3_tim_stop(FAR struct esp32c3_tim_dev_s *dev); +static void esp32c3_tim_clear(FAR struct esp32c3_tim_dev_s *dev); +static void esp32c3_tim_setmode(FAR struct esp32c3_tim_dev_s *dev, + enum esp32c3_tim_mode_e mode); +static void esp32c3_tim_setclksrc(FAR struct esp32c3_tim_dev_s *dev, + enum esp32c3_tim_clksrc_e src); +static void esp32c3_tim_setpre(FAR struct esp32c3_tim_dev_s *dev, + uint16_t pre); +static void esp32c3_tim_getcounter(FAR struct esp32c3_tim_dev_s *dev, + uint64_t *value); +static void esp32c3_tim_setcounter(FAR struct esp32c3_tim_dev_s *dev, + uint64_t value); +static void esp32c3_tim_reload_now(FAR struct esp32c3_tim_dev_s *dev); +static void esp32c3_tim_getalarmvalue(FAR struct esp32c3_tim_dev_s *dev, + uint64_t *value); +static void esp32c3_tim_setalarmvalue(FAR struct esp32c3_tim_dev_s *dev, + uint64_t value); +static void esp32c3_tim_setalarm(FAR struct esp32c3_tim_dev_s *dev, + bool enable); +static void esp32c3_tim_setautoreload(FAR struct esp32c3_tim_dev_s *dev, + bool enable); +static int esp32c3_tim_setisr(FAR struct esp32c3_tim_dev_s *dev, + xcpt_t handler, FAR void * arg); +static void esp32c3_tim_enableint(FAR struct esp32c3_tim_dev_s *dev); +static void esp32c3_tim_disableint(FAR struct esp32c3_tim_dev_s *dev); +static void esp32c3_tim_ackint(FAR struct esp32c3_tim_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ESP32C3 TIM ops */ + +struct esp32c3_tim_ops_s esp32c3_tim_ops = +{ + .start = esp32c3_tim_start, + .stop = esp32c3_tim_stop, + .clear = esp32c3_tim_clear, + .setmode = esp32c3_tim_setmode, + .getcounter = esp32c3_tim_getcounter, + .setclksrc = esp32c3_tim_setclksrc, + .setpre = esp32c3_tim_setpre, + .setcounter = esp32c3_tim_setcounter, + .reloadnow = esp32c3_tim_reload_now, + .getalarmvalue = esp32c3_tim_getalarmvalue, + .setalarmvalue = esp32c3_tim_setalarmvalue, + .setalarm = esp32c3_tim_setalarm, + .setautoreload = esp32c3_tim_setautoreload, + .setisr = esp32c3_tim_setisr, + .enableint = esp32c3_tim_enableint, + .disableint = esp32c3_tim_disableint, + .ackint = esp32c3_tim_ackint +}; + +#ifdef CONFIG_ESP32C3_TIMER0 +/* TIMER0 */ + +struct esp32c3_tim_priv_s g_esp32c3_tim0_priv = +{ + .ops = &esp32c3_tim_ops, + .id = ESP32C3_TIMER0, + .periph = ESP32C3_PERIPH_TG0_T0, /* Peripheral ID */ + .irq = ESP32C3_IRQ_TG0_T0, /* Interrupt ID */ + .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .inuse = false, +}; +#endif + +#ifdef CONFIG_ESP32C3_TIMER1 +/* TIMER1 */ + +struct esp32c3_tim_priv_s g_esp32c3_tim1_priv = +{ + .ops = &esp32c3_tim_ops, + .id = ESP32C3_TIMER1, + .periph = ESP32C3_PERIPH_TG1_T0, /* Peripheral ID */ + .irq = ESP32C3_IRQ_TG1_T0, /* Interrupt ID */ + .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .inuse = false, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_tim_start + * + * Description: + * Release the counter. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_start(FAR struct esp32c3_tim_dev_s *dev) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_EN_M, TIMG_T0_EN_M); +} + +/**************************************************************************** + * Name: esp32c3_tim_stop + * + * Description: + * Halt the counter. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_stop(FAR struct esp32c3_tim_dev_s *dev) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_EN_M, 0); +} + +/**************************************************************************** + * Name: esp32c3_tim_clear + * + * Description: + * Set the counter to zero instantly. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_clear(FAR struct esp32c3_tim_dev_s *dev) +{ + uint64_t clear_value = 0; + DEBUGASSERT(dev); + esp32c3_tim_setcounter(dev, clear_value); + esp32c3_tim_reload_now(dev); +} + +/**************************************************************************** + * Name: esp32c3_tim_setmode + * + * Description: + * Set counter mode. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * mode - Variable indicating the counting direction (up/down). + * + ****************************************************************************/ + +static void esp32c3_tim_setmode(FAR struct esp32c3_tim_dev_s *dev, + enum esp32c3_tim_mode_e mode) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + if (mode == ESP32C3_TIM_MODE_DOWN) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_INCREASE_M, 0); + } + else if (mode == ESP32C3_TIM_MODE_UP) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), 0, TIMG_T0_INCREASE_M); + } +} + +/**************************************************************************** + * Name: esp32c3_tim_setclksrc + * + * Description: + * Set CLK source. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * src - The source, it may be APB_CLK or XTAL_CLK. + * + ****************************************************************************/ + +static void esp32c3_tim_setclksrc(FAR struct esp32c3_tim_dev_s *dev, + enum esp32c3_tim_clksrc_e src) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + if (src == ESP32C3_TIM_APB_CLK) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_USE_XTAL_M, 0); + } + else if(src == ESP32C3_TIM_XTAL_CLK) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), 0, TIMG_T0_USE_XTAL_M); + } +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_tim_setpre(FAR struct esp32c3_tim_dev_s *dev, + uint16_t pre) +{ + uint32_t mask = (uint32_t)pre << TIMG_T0_DIVIDER_S; + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_DIVIDER_M, mask); +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_tim_getcounter(FAR struct esp32c3_tim_dev_s *dev, + uint64_t *value) +{ + uint32_t value_32; + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + *value = 0; + + /* Dummy value (0 or 1) to latch the counter value to read it */ + + putreg32(BIT(0), TIMG_T0UPDATE_REG(priv->id)); + + /* Read value */ + + value_32 = getreg32(TIMG_T0HI_REG(priv->id)); /* High 32 bits */ + + /* Discard the top 10 bits */ + + value_32 &= LOW_22_MASK; + *value |= (uint64_t)value_32; + *value <<= SHIFT_32; + value_32 = getreg32(TIMG_T0LO_REG(priv->id)); /* Low 32 bits */ + *value |= (uint64_t)value_32; +} + +/**************************************************************************** + * Name: esp32c3_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 + * esp32c3_tim_reload_now() after this function. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - The value to be loaded the counter. + * + ****************************************************************************/ + +static void esp32c3_tim_setcounter(FAR struct esp32c3_tim_dev_s *dev, + uint64_t value) +{ + uint64_t low_64 = value & LOW_32_MASK; + + /* Get only the low 22 bits. */ + + uint64_t high_64 = (value >> SHIFT_32) & LOW_22_MASK; + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + + /* Set the counter value */ + + putreg32((uint32_t)low_64, TIMG_T0LOADLO_REG(priv->id)); + putreg32((uint32_t)high_64, TIMG_T0LOADHI_REG(priv->id)); +} + +/**************************************************************************** + * Name: esp32c3_tim_reload_now + * + * Description: + * Reload the counter instantly. It may be called after + * esp32c3_tim_setcounter(). + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_reload_now(FAR struct esp32c3_tim_dev_s *dev) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + + /* Dummy value to trigger reloading */ + + putreg32(BIT(0), TIMG_T0LOAD_REG(priv->id)); +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_tim_getalarmvalue(FAR struct esp32c3_tim_dev_s *dev, + uint64_t *value) +{ + uint32_t value_32; + struct esp32c3_tim_priv_s *priv; + + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + *value = 0; + + /* Read value */ + + value_32 = getreg32(TIMG_T0ALARMHI_REG(priv->id)); /* High 32 bits */ + + /* Get only the 22 low bits. */ + + value_32 &= LOW_22_MASK; + *value |= (uint64_t)value_32; + *value <<= SHIFT_32; + value_32 = getreg32(TIMG_T0ALARMLO_REG(priv->id)); /* Low 32 bits */ + *value |= (uint64_t)value_32; +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_tim_setalarmvalue(FAR struct esp32c3_tim_dev_s *dev, + uint64_t value) +{ + struct esp32c3_tim_priv_s *priv; + uint64_t low_64 = value & LOW_32_MASK; + uint64_t high_64 = (value >> SHIFT_32) & LOW_22_MASK; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + + /* Set an alarm value */ + + putreg32((uint32_t)low_64, TIMG_T0ALARMLO_REG(priv->id)); + putreg32((uint32_t)high_64, TIMG_T0ALARMHI_REG(priv->id)); +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_tim_setalarm(FAR struct esp32c3_tim_dev_s *dev, + bool enable) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + + if (enable) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), 0, TIMG_T0_ALARM_EN_M); + } + else + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_ALARM_EN_M, 0); + } +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_tim_setautoreload(FAR struct esp32c3_tim_dev_s *dev, + bool enable) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + + if (enable) + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), 0, TIMG_T0_AUTORELOAD_M); + } + else + { + modifyreg32(TIMG_T0CONFIG_REG(priv->id), TIMG_T0_AUTORELOAD_M, 0); + } +} + +/**************************************************************************** + * Name: esp32c3_tim_setisr + * + * Description: + * Allocate a CPU Interrupt, connect the peripheral source to this + * Interrupt, register the callback and enable CPU the 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 esp32c3_tim_setisr(FAR struct esp32c3_tim_dev_s *dev, + xcpt_t handler, FAR void *arg) +{ + FAR struct esp32c3_tim_priv_s *priv = NULL; + int ret = OK; + + DEBUGASSERT(dev); + + priv = (FAR struct esp32c3_tim_priv_s *)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 */ + + esp32c3_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 esp32c3_request_irq() + */ + + esp32c3_free_cpuint(priv->periph); + } + + priv->cpuint = esp32c3_request_irq(priv->periph, + ESP32C3_INT_PRIO_DEF, + ESP32C3_INT_LEVEL); + + if (priv->cpuint < 0) + { + tmrerr("ERROR: Failed to get a CPU interrupt"); + ret = priv->cpuint; + goto errout; + } + + /* 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"); + esp32c3_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: esp32c3_tim_enableint + * + * Description: + * Enable a level Interrupt at the alarm if it is set. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_enableint(FAR struct esp32c3_tim_dev_s *dev) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->id), 0, TIMG_T0_INT_ENA_M); +} + +/**************************************************************************** + * Name: esp32c3_tim_disableint + * + * Description: + * Disable a level Interrupt at the alarm if it is set. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_disableint(FAR struct esp32c3_tim_dev_s *dev) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + modifyreg32(TIMG_INT_ENA_TIMERS_REG(priv->id), TIMG_T0_INT_ENA_M, 0); +} + +/**************************************************************************** + * Name: esp32c3_tim_ackint + * + * Description: + * Acknowledge an interrupt, that means, clear the interrupt. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void esp32c3_tim_ackint(FAR struct esp32c3_tim_dev_s *dev) +{ + struct esp32c3_tim_priv_s *priv; + DEBUGASSERT(dev); + priv = (FAR struct esp32c3_tim_priv_s *)dev; + modifyreg32(TIMG_INT_CLR_TIMERS_REG(priv->id), 0, TIMG_T0_INT_CLR_M); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_tim_init + * + * Description: + * Initialize TIMER device, if software real-time timer + * (CONFIG_ESP32C3_RT_TIMER) is enabled, then timer0 can't + * be initialized by this function directly. + * + * 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 esp32c3_tim_dev_s *esp32c3_tim_init(int timer) +{ + FAR struct esp32c3_tim_priv_s *tim = NULL; + + /* Get timer instance */ + + switch (timer) + { +#if defined(CONFIG_ESP32C3_TIMER0) + case 0: + { + tim = &g_esp32c3_tim0_priv; + break; + } +#endif + +#ifdef CONFIG_ESP32C3_TIMER1 + case 1: + { + tim = &g_esp32c3_tim1_priv; + break; + } +#endif + + default: + { + tmrerr("ERROR: unsupported TIMER %d\n", timer); + goto errout; + } + } + + if (tim->inuse == true) + { + tmrerr("ERROR: TIMER %d is already in use\n", timer); + tim = NULL; + } + + errout: + return (FAR struct esp32c3_tim_dev_s *)tim; +} + +/**************************************************************************** + * Name: esp32c3_tim_deinit + * + * Description: + * Deinit TIMER device. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +void esp32c3_tim_deinit(FAR struct esp32c3_tim_dev_s *dev) +{ + FAR struct esp32c3_tim_priv_s *tim = NULL; + + DEBUGASSERT(dev); + + tim = (FAR struct esp32c3_tim_priv_s *)dev; + tim->inuse = false; +} diff --git a/arch/risc-v/src/esp32c3/esp32c3_tim.h b/arch/risc-v/src/esp32c3/esp32c3_tim.h new file mode 100644 index 00000000000..2d427435ae6 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_tim.h @@ -0,0 +1,138 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_TIM_H +#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define ESP32C3_TIM_START(d) ((d)->ops->start(d)) +#define ESP32C3_TIM_STOP(d) ((d)->ops->stop(d)) +#define ESP32C3_TIM_CLEAR(d) ((d)->ops->clear(d)) +#define ESP32C3_TIM_SETMODE(d, m) ((d)->ops->setmode(d, m)) +#define ESP32C3_TIM_CLK_SRC(d, s) ((d)->ops->setclksrc(d, s)) +#define ESP32C3_TIM_SETPRE(d, p) ((d)->ops->setpre(d, p)) +#define ESP32C3_TIM_GETCTR(d, v) ((d)->ops->getcounter(d, v)) +#define ESP32C3_TIM_SETCTR(d, v) ((d)->ops->setcounter(d, v)) +#define ESP32C3_TIM_RLD_NOW(d) ((d)->ops->reloadnow(d)) +#define ESP32C3_TIM_GETALRVL(d, v) ((d)->ops->getalarmvalue(d, v)) +#define ESP32C3_TIM_SETALRVL(d, v) ((d)->ops->setalarmvalue(d, v)) +#define ESP32C3_TIM_SETALRM(d, e) ((d)->ops->setalarm(d, e)) +#define ESP32C3_TIM_SETARLD(d, e) ((d)->ops->setautoreload(d, e)) +#define ESP32C3_TIM_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) +#define ESP32C3_TIM_ENABLEINT(d) ((d)->ops->enableint(d)) +#define ESP32C3_TIM_DISABLEINT(d) ((d)->ops->disableint(d)) +#define ESP32C3_TIM_ACKINT(d) ((d)->ops->ackint(d)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Instances of Timer */ + +enum esp32c3_tim_inst_e +{ + ESP32C3_TIMER0 = 0, /* Timer 0 from Timer Group 0 */ + ESP32C3_TIMER1, /* Timer 0 from Timer Group 1 */ +}; + +/* Timer mode */ + +enum esp32c3_tim_clksrc_e +{ + ESP32C3_TIM_APB_CLK, + ESP32C3_TIM_XTAL_CLK, +}; + +/* Timer mode */ + +enum esp32c3_tim_mode_e +{ + ESP32C3_TIM_MODE_DOWN, + ESP32C3_TIM_MODE_UP, +}; + +/* ESP32C3 TIM device */ + +struct esp32c3_tim_dev_s +{ + struct esp32c3_tim_ops_s *ops; +}; + +/* ESP32C3 TIM ops */ + +/* This is a struct containing the pointers to the timer operations */ + +struct esp32c3_tim_ops_s +{ + /* Timer tasks */ + + CODE void (*start)(FAR struct esp32c3_tim_dev_s *dev); + CODE void (*stop)(FAR struct esp32c3_tim_dev_s *dev); + CODE void (*clear)(FAR struct esp32c3_tim_dev_s *dev); + + /* Timer operations */ + + CODE void (*setmode)(FAR struct esp32c3_tim_dev_s *dev, + enum esp32c3_tim_mode_e mode); + CODE void (*setclksrc)(FAR struct esp32c3_tim_dev_s *dev, + enum esp32c3_tim_clksrc_e src); + CODE void (*setpre)(FAR struct esp32c3_tim_dev_s *dev, uint16_t pre); + CODE void (*getcounter)(FAR struct esp32c3_tim_dev_s *dev, + uint64_t *value); + CODE void (*setcounter)(FAR struct esp32c3_tim_dev_s *dev, uint64_t value); + CODE void (*reloadnow)(FAR struct esp32c3_tim_dev_s *dev); + CODE void (*getalarmvalue)(FAR struct esp32c3_tim_dev_s *dev, + uint64_t *value); + CODE void (*setalarmvalue)(FAR struct esp32c3_tim_dev_s *dev, + uint64_t value); + CODE void (*setalarm)(FAR struct esp32c3_tim_dev_s *dev, bool enable); + CODE void (*setautoreload)(FAR struct esp32c3_tim_dev_s *dev, bool enable); + + /* Timer interrupts */ + + CODE int (*setisr)(FAR struct esp32c3_tim_dev_s *dev, xcpt_t handler, + FAR void * arg); + CODE void (*enableint)(FAR struct esp32c3_tim_dev_s *dev); + CODE void (*disableint)(FAR struct esp32c3_tim_dev_s *dev); + CODE void (*ackint)(FAR struct esp32c3_tim_dev_s *dev); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +FAR struct esp32c3_tim_dev_s *esp32c3_tim_init(int timer); +void esp32c3_tim_deinit(FAR struct esp32c3_tim_dev_s *dev); + +#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TIM_H */ diff --git a/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c b/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c new file mode 100644 index 00000000000..8436936b3ea --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.c @@ -0,0 +1,559 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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 "hardware/esp32c3_soc.h" + +#include "esp32c3_tim.h" +#include "esp32c3_clockconfig.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TIMER configuration */ + +#define ESP32C3_TIMER_MAX_USECOND 0xffffffff + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct esp32c3_timer_lowerhalf_s +{ + FAR const struct timer_ops_s *ops; /* Lower half operations */ + FAR struct esp32c3_tim_dev_s *tim; /* esp32c3 timer driver */ + tccb_t callback; /* Current user interrupt callback */ + FAR void *arg; /* Argument passed to upper half callback */ + bool started; /* True: Timer has been started */ + void *upper; /* Pointer to watchdog_upperhalf_s */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int esp32c3_timer_handler(int irq, void *context, void *arg); + +/* "Lower half" driver methods **********************************************/ + +static int esp32c3_timer_start(FAR struct timer_lowerhalf_s *lower); +static int esp32c3_timer_stop(FAR struct timer_lowerhalf_s *lower); +static int esp32c3_timer_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status); +static int esp32c3_timer_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout); +static int esp32c3_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t *timeout); +static void esp32c3_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_esp32c3_timer_ops = +{ + .start = esp32c3_timer_start, + .stop = esp32c3_timer_stop, + .getstatus = esp32c3_timer_getstatus, + .settimeout = esp32c3_timer_settimeout, + .setcallback = esp32c3_timer_setcallback, + .maxtimeout = esp32c3_timer_maxtimeout, + .ioctl = NULL, +}; + +#ifdef CONFIG_ESP32C3_TIMER0 +/* TIMER0 lower-half */ + +static struct esp32c3_timer_lowerhalf_s g_esp32c3_timer0_lowerhalf = +{ + .ops = &g_esp32c3_timer_ops, +}; +#endif + +#ifdef CONFIG_ESP32C3_TIMER1 +/* TIMER1 lower-half */ + +static struct esp32c3_timer_lowerhalf_s g_esp32c3_timer1_lowerhalf = +{ + .ops = &g_esp32c3_timer_ops, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_timer_handler + * + * Description: + * Timer interrupt handler + * + ****************************************************************************/ + +static int esp32c3_timer_handler(int irq, void *context, void *arg) +{ + FAR struct esp32c3_timer_lowerhalf_s *priv = + (FAR struct esp32c3_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 */ + + ESP32C3_TIM_SETALRVL(priv->tim, next_interval_us); + } + } + else + { + esp32c3_timer_stop((struct timer_lowerhalf_s *)priv); + } + + ESP32C3_TIM_SETALRM(priv->tim, true); /* Re-enables the alarm */ + ESP32C3_TIM_ACKINT(priv->tim); /* Clear the Interrupt */ + return OK; +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_timer_start(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct esp32c3_timer_lowerhalf_s *priv = + (FAR struct esp32c3_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 */ + + ESP32C3_TIM_STOP(priv->tim); + + /* Configure clock source */ + + ESP32C3_TIM_CLK_SRC(priv->tim, ESP32C3_TIM_APB_CLK); + + /* Calculate the suitable prescaler according to the current APB + * frequency to generate a period of 1 us. + */ + + pre = esp32c3_clk_apb_freq() / 1000000; + + /* Configure TIMER prescaler */ + + ESP32C3_TIM_SETPRE(priv->tim, pre); + + /* Configure TIMER mode */ + + ESP32C3_TIM_SETMODE(priv->tim, ESP32C3_TIM_MODE_UP); + + /* Clear TIMER counter value */ + + ESP32C3_TIM_CLEAR(priv->tim); + + /* Enable autoreload */ + + ESP32C3_TIM_SETARLD(priv->tim, true); + + /* Enable TIMER alarm */ + + ESP32C3_TIM_SETALRM(priv->tim, true); + + /* Clear Interrupt Bits Status */ + + ESP32C3_TIM_ACKINT(priv->tim); + + /* Configure callback, in case a handler was provided before */ + + if (priv->callback != NULL) + { + flags = enter_critical_section(); + ret = ESP32C3_TIM_SETISR(priv->tim, esp32c3_timer_handler, priv); + leave_critical_section(flags); + if (ret != OK) + { + goto errout; + } + + ESP32C3_TIM_ENABLEINT(priv->tim); + } + + /* Finally, start the TIMER */ + + ESP32C3_TIM_START(priv->tim); + priv->started = true; + +errout: + return ret; +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_timer_stop(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct esp32c3_timer_lowerhalf_s *priv = + (FAR struct esp32c3_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; + } + + ESP32C3_TIM_DISABLEINT(priv->tim); + flags = enter_critical_section(); + ret = ESP32C3_TIM_SETISR(priv->tim, NULL, NULL); + leave_critical_section(flags); + ESP32C3_TIM_STOP(priv->tim); + + priv->started = false; + priv->callback = NULL; + +errout: + return ret; +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_timer_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status) +{ + FAR struct esp32c3_timer_lowerhalf_s *priv = + (FAR struct esp32c3_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 */ + + ESP32C3_TIM_GETCTR(priv->tim, ¤t_counter_value); + + /* Get the current configured timeout */ + + ESP32C3_TIM_GETALRVL(priv->tim, &alarm_value); + + status->timeout = (uint32_t)(alarm_value); + status->timeleft = (uint32_t)(alarm_value - current_counter_value); + + return ret; +} + +/**************************************************************************** + * Name: esp32c3_timer_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * 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 esp32c3_timer_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct esp32c3_timer_lowerhalf_s *priv = + (FAR struct esp32c3_timer_lowerhalf_s *)lower; + int ret = OK; + + DEBUGASSERT(priv); + + /* Set the timeout */ + + ESP32C3_TIM_SETALRVL(priv->tim, (uint64_t)timeout); + + return ret; +} + +/**************************************************************************** + * Name: esp32c3_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 esp32c3_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t *max_timeout) +{ + DEBUGASSERT(max_timeout); + + *max_timeout = ESP32C3_TIMER_MAX_USECOND; + + return OK; +} + +/**************************************************************************** + * Name: esp32c3_setcallback + * + * Description: + * Call this user provided timeout handler. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback + * + * Returned Value: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void esp32c3_timer_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg) +{ + FAR struct esp32c3_timer_lowerhalf_s *priv = + (FAR struct esp32c3_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 = ESP32C3_TIM_SETISR(priv->tim, esp32c3_timer_handler, priv); + ESP32C3_TIM_ENABLEINT(priv->tim); + } + else + { + ESP32C3_TIM_DISABLEINT(priv->tim); + ret = ESP32C3_TIM_SETISR(priv->tim, NULL, NULL); + } + + leave_critical_section(flags); + if (ret != OK) + { + tmrerr("Error to set ISR: %d", ret); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_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/timer0 + * 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 esp32c3_timer_initialize(FAR const char *devpath, uint8_t timer) +{ + struct esp32c3_timer_lowerhalf_s *lower = NULL; + int ret = OK; + + DEBUGASSERT(devpath); + + switch (timer) + { +#ifdef CONFIG_ESP32C3_TIMER0 + case 0: + { + lower = &g_esp32c3_timer0_lowerhalf; + break; + } +#endif + +#ifdef CONFIG_ESP32C3_TIMER1 + case 1: + { + lower = &g_esp32c3_timer1_lowerhalf; + break; + } +#endif + + default: + { + ret = -ENODEV; + goto errout; + } + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = esp32c3_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/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.h b/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.h new file mode 100644 index 00000000000..84beabaa2c5 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_tim_lowerhalf.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_TIM_LOWERHALF_H +#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TIM_LOWERHALF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32c3_timer_initialize + ****************************************************************************/ + +int esp32c3_timer_initialize(FAR const char *devpath, uint8_t timer); + +#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TIM_LOWERHALF_H */ diff --git a/arch/risc-v/src/esp32c3/hardware/esp32c3_tim.h b/arch/risc-v/src/esp32c3/hardware/esp32c3_tim.h index c050d0b80cd..b9846d816b9 100644 --- a/arch/risc-v/src/esp32c3/hardware/esp32c3_tim.h +++ b/arch/risc-v/src/esp32c3/hardware/esp32c3_tim.h @@ -69,6 +69,12 @@ #define TIMG_WDT_RESET_LENGTH_1600_NS 6 #define TIMG_WDT_RESET_LENGTH_3200_NS 7 +/* Maximum value in the high 22 bits from timer counters */ + +#define LOW_32_MASK 0xffffffff +#define LOW_22_MASK 0x3fffff +#define SHIFT_32 32 + #define TIMG_T0CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0000) /* TIMG_T0_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/timer/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/timer/defconfig new file mode 100644 index 00000000000..8f4759bee92 --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/timer/defconfig @@ -0,0 +1,48 @@ +# +# 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_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c3-devkit" +CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y +CONFIG_ARCH_CHIP="esp32c3" +CONFIG_ARCH_CHIP_ESP32C3=y +CONFIG_ARCH_CHIP_ESP32C3WROOM02=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESP32C3_TIMER0=y +CONFIG_ESP32C3_TIMER1=y +CONFIG_EXAMPLES_TIMER=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MAX_TASKS=8 +CONFIG_NFILE_DESCRIPTORS=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_NSH=y +CONFIG_TIMER=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile b/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile index ffb60d2a2cf..10004d1ffec 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/Makefile @@ -42,6 +42,10 @@ ifeq ($(CONFIG_WATCHDOG),y) CSRCS += esp32c3_wdt.c endif +ifeq ($(CONFIG_TIMER),y) +CSRCS += esp32c3_timer.c +endif + SCRIPTIN = $(SCRIPTDIR)$(DELIM)esp32c3.template.ld SCRIPTOUT = $(SCRIPTDIR)$(DELIM)esp32c3_out.ld diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h index 545312714cf..94011b86ae8 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h @@ -85,5 +85,21 @@ int esp32c3_gpio_init(void); int board_wdt_init(void); #endif +/**************************************************************************** + * Name: board_tim_init + * + * Description: + * Configure the timer driver. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_TIMER +int board_tim_init(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_SRC_ESP32C3_DEVKIT_H */ diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c index 513c712d29b..22115b0915e 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c @@ -107,6 +107,18 @@ int esp32c3_bringup(void) } #endif +#ifdef CONFIG_TIMER + /* Configure timer timer */ + + ret = board_tim_init(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer drivers: %d\n", + ret); + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities. diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c new file mode 100644 index 00000000000..b88b3d37a57 --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_timer.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 "esp32c3_tim_lowerhalf.h" +#include "esp32c3_tim.h" + +#include "esp32c3-devkit.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_tim_init + * + * Description: + * Configure the timer driver. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_tim_init(void) +{ + int ret = OK; + +#ifdef CONFIG_ESP32C3_TIMER0 + ret = esp32c3_timer_initialize("/dev/timer0", ESP32C3_TIMER0); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_ESP32C3_TIMER0 */ + +#ifdef CONFIG_ESP32C3_TIMER1 + ret = esp32c3_timer_initialize("/dev/timer1", ESP32C3_TIMER1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_ESP32C3_TIMER1 */ + + return ret; +} +