diff --git a/arch/xtensa/src/esp32/esp32_tim.c b/arch/xtensa/src/esp32/esp32_tim.c index 0ce5205a2c..c788359619 100644 --- a/arch/xtensa/src/esp32/esp32_tim.c +++ b/arch/xtensa/src/esp32/esp32_tim.c @@ -23,13 +23,9 @@ ****************************************************************************/ #include - -#include - #include #include #include -#include #include #include "xtensa.h" @@ -46,11 +42,13 @@ struct esp32_tim_priv_s { FAR struct esp32_tim_ops_s *ops; - uint32_t base; /* Timer register base address */ - 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 */ + uint32_t base; /* Timer register base address */ + uint8_t periph; /* Peripheral ID */ + uint8_t irq; /* Interrupt ID */ + int cpuint; /* CPU interrupt assigned to this timer */ + int core; /* Core that is taking care of the timer ints */ + bool inuse; /* Flag indicating if the timer is in use */ + uint8_t priority; /* Interrupt priority */ }; /**************************************************************************** @@ -73,35 +71,28 @@ static void esp32_tim_modifyreg32(FAR struct esp32_tim_dev_s *dev, /* TIM operations ***********************************************************/ -static int esp32_tim_start(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_stop(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_clear(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_configure(FAR struct esp32_tim_dev_s *dev, uint16_t pre, - uint8_t mode, uint64_t counter_value, - uint64_t alarm_value, bool alarm, - bool autoreload); -static int esp32_tim_setmode(FAR struct esp32_tim_dev_s *dev, uint8_t mode); -static int esp32_tim_setpre(FAR struct esp32_tim_dev_s *dev, uint16_t pre); -static int esp32_tim_getconfig(FAR struct esp32_tim_dev_s *dev, - uint32_t *value); -static int esp32_tim_getcounter(FAR struct esp32_tim_dev_s *dev, - uint64_t *value); -static int esp32_tim_setcounter(FAR struct esp32_tim_dev_s *dev, - uint64_t value); -static int esp32_tim_reload_now(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_getalarmvalue(FAR struct esp32_tim_dev_s *dev, - uint64_t *value); -static int esp32_tim_setalarmvalue(FAR struct esp32_tim_dev_s *dev, - uint64_t value); -static int esp32_tim_setalarm(FAR struct esp32_tim_dev_s *dev, bool enable); -static int esp32_tim_setautoreload(FAR struct esp32_tim_dev_s *dev, - bool enable); -static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler, - FAR void * arg); -static int esp32_tim_enableint(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_disableint(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_checkint(FAR struct esp32_tim_dev_s *dev); -static int esp32_tim_ackint(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_start(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_stop(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_clear(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_setmode(FAR struct esp32_tim_dev_s *dev, uint8_t mode); +static void esp32_tim_setpre(FAR struct esp32_tim_dev_s *dev, uint16_t pre); +static void esp32_tim_getcounter(FAR struct esp32_tim_dev_s *dev, + uint64_t *value); +static void esp32_tim_setcounter(FAR struct esp32_tim_dev_s *dev, + uint64_t value); +static void esp32_tim_reload_now(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_getalarmvalue(FAR struct esp32_tim_dev_s *dev, + uint64_t *value); +static void esp32_tim_setalarmvalue(FAR struct esp32_tim_dev_s *dev, + uint64_t value); +static void esp32_tim_setalarm(FAR struct esp32_tim_dev_s *dev, bool enable); +static void esp32_tim_setautoreload(FAR struct esp32_tim_dev_s *dev, + bool enable); +static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler, + FAR void * arg); +static void esp32_tim_enableint(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_disableint(FAR struct esp32_tim_dev_s *dev); +static void esp32_tim_ackint(FAR struct esp32_tim_dev_s *dev); /**************************************************************************** * Private Data @@ -114,11 +105,9 @@ struct esp32_tim_ops_s esp32_tim_ops = .start = esp32_tim_start, .stop = esp32_tim_stop, .clear = esp32_tim_clear, - .configure = esp32_tim_configure, .setmode = esp32_tim_setmode, .getcounter = esp32_tim_getcounter, .setpre = esp32_tim_setpre, - .getconfig = esp32_tim_getconfig, .setcounter = esp32_tim_setcounter, .reloadnow = esp32_tim_reload_now, .getalarmvalue = esp32_tim_getalarmvalue, @@ -128,7 +117,6 @@ struct esp32_tim_ops_s esp32_tim_ops = .setisr = esp32_tim_setisr, .enableint = esp32_tim_enableint, .disableint = esp32_tim_disableint, - .checkint = esp32_tim_checkint, .ackint = esp32_tim_ackint }; @@ -142,7 +130,9 @@ struct esp32_tim_priv_s g_esp32_tim0_priv = .periph = ESP32_PERIPH_TG_T0_LEVEL, /* Peripheral ID */ .irq = ESP32_IRQ_TG_T0_LEVEL, /* Interrupt ID */ .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .core = -ENODEV, /* No core was assigned */ .inuse = false, + .priority = 1, }; #endif @@ -156,7 +146,9 @@ struct esp32_tim_priv_s g_esp32_tim1_priv = .periph = ESP32_PERIPH_TG_T1_LEVEL, /* Peripheral ID */ .irq = ESP32_IRQ_TG_T1_LEVEL, /* Interrupt ID */ .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .core = -ENODEV, /* No core was assigned */ .inuse = false, + .priority = 1, }; #endif @@ -170,7 +162,9 @@ struct esp32_tim_priv_s g_esp32_tim2_priv = .periph = ESP32_PERIPH_TG1_T0_LEVEL, /* Peripheral ID */ .irq = ESP32_IRQ_TG1_T0_LEVEL, /* Interrupt ID */ .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .core = -ENODEV, /* No core was assigned */ .inuse = false, + .priority = 1, }; #endif @@ -184,7 +178,9 @@ struct esp32_tim_priv_s g_esp32_tim3_priv = .periph = ESP32_PERIPH_TG1_T1_LEVEL, /* Peripheral ID */ .irq = ESP32_IRQ_TG1_T1_LEVEL, /* Interrupt ID */ .cpuint = -ENOMEM, /* CPU interrupt assigned to this timer */ + .core = -ENODEV, /* No core was assigned */ .inuse = false, + .priority = 1, }; #endif @@ -252,13 +248,10 @@ static void esp32_tim_modifyreg32(FAR struct esp32_tim_dev_s *dev, * ****************************************************************************/ -static int esp32_tim_start(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_start(FAR struct esp32_tim_dev_s *dev) { DEBUGASSERT(dev); - esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, 0, TIMG_T0_EN); - - return OK; } /**************************************************************************** @@ -269,13 +262,10 @@ static int esp32_tim_start(FAR struct esp32_tim_dev_s *dev) * ****************************************************************************/ -static int esp32_tim_stop(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_stop(FAR struct esp32_tim_dev_s *dev) { DEBUGASSERT(dev); - esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_EN, 0); - - return OK; } /**************************************************************************** @@ -286,98 +276,12 @@ static int esp32_tim_stop(FAR struct esp32_tim_dev_s *dev) * ****************************************************************************/ -static int esp32_tim_clear(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_clear(FAR struct esp32_tim_dev_s *dev) { uint64_t clear_value = 0; - DEBUGASSERT(dev); - esp32_tim_setcounter(dev, clear_value); - esp32_tim_reload_now(dev); - - return OK; -} - -/**************************************************************************** - * Name: esp32_tim_configure - * - * Description: - * Configure prescaler divider, counter mode (up/down), counter value, - * Reload Event - * and alarm trigger value. - * - ****************************************************************************/ - -static int esp32_tim_configure(FAR struct esp32_tim_dev_s *dev, uint16_t pre, - uint8_t mode, uint64_t counter_value, - uint64_t alarm_value, bool alarm, - bool autoreload) -{ - int ret = OK; - - DEBUGASSERT(dev); - - /* Change the prescaler divider with the timer enabled can lead to - * unpredictable results, so it is disabled before configuring - */ - - ret = esp32_tim_stop(dev); - if (ret != OK) - { - goto errout; - } - - /* Configure TIMER prescaler */ - - ret = esp32_tim_setpre(dev, pre); - if (ret != OK) - { - goto errout; - } - - /* Configure TIMER mode */ - - ret = esp32_tim_setmode(dev, mode); - if (ret != OK) - { - goto errout; - } - - /* Configure TIMER counter value */ - - ret = esp32_tim_setcounter(dev, counter_value); - if (ret != OK) - { - goto errout; - } - - /* Configure TIMER alarm value */ - - ret = esp32_tim_setalarmvalue(dev, counter_value); - if (ret != OK) - { - goto errout; - } - - /* Enable TIMER alarm */ - - ret = esp32_tim_setalarm(dev, alarm); - if (ret != OK) - { - goto errout; - } - - /* Configure TIMER auto-reload */ - - ret = esp32_tim_setautoreload(dev, autoreload); - if (ret != OK) - { - goto errout; - } - -errout: - return ret; } /**************************************************************************** @@ -388,36 +292,18 @@ errout: * ****************************************************************************/ -static int esp32_tim_setmode(FAR struct esp32_tim_dev_s *dev, uint8_t mode) +static void esp32_tim_setmode(FAR struct esp32_tim_dev_s *dev, uint8_t mode) { - int ret = OK; - DEBUGASSERT(dev); - switch (mode) + if (mode == ESP32_TIM_MODE_DOWN) { - case ESP32_TIM_MODE_DOWN: - { - esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_INCREASE, 0); - break; - } - - case ESP32_TIM_MODE_UP: - { - esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, 0, TIMG_T0_INCREASE); - break; - } - - default: - { - tmrerr("ERROR: unsupported TIMER mode %d\n", mode); - ret = -EINVAL; - goto errout; - } + esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_INCREASE, 0); + } + else if (ESP32_TIM_MODE_UP) + { + esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, 0, TIMG_T0_INCREASE); } - -errout: - return ret; } /**************************************************************************** @@ -430,35 +316,11 @@ errout: * ****************************************************************************/ -static int esp32_tim_setpre(FAR struct esp32_tim_dev_s *dev, uint16_t pre) +static void esp32_tim_setpre(FAR struct esp32_tim_dev_s *dev, uint16_t pre) { uint32_t mask = (uint32_t)pre << TIMG_T0_DIVIDER_S; - DEBUGASSERT(dev); - esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_DIVIDER_M, mask); - - return OK; -} - -/**************************************************************************** - * Name: esp32_tim_getconfig - * - * Description: - * Get the current configuration from config reg - * - ****************************************************************************/ - -static int esp32_tim_getconfig(FAR struct esp32_tim_dev_s *dev, - uint32_t *value) -{ - DEBUGASSERT(dev); - - /* Read value */ - - *value = esp32_tim_getreg(dev, TIM_CONFIG_OFFSET); /* High 32 bits */ - - return OK; } /**************************************************************************** @@ -469,7 +331,7 @@ static int esp32_tim_getconfig(FAR struct esp32_tim_dev_s *dev, * ****************************************************************************/ -static int esp32_tim_getcounter(FAR struct esp32_tim_dev_s *dev, +static void esp32_tim_getcounter(FAR struct esp32_tim_dev_s *dev, uint64_t *value) { uint32_t value_32; @@ -485,16 +347,10 @@ static int esp32_tim_getcounter(FAR struct esp32_tim_dev_s *dev, /* Read value */ value_32 = esp32_tim_getreg(dev, TIM_HI_OFFSET); /* High 32 bits */ - *value |= (uint64_t)value_32; - *value <<= SHIFT_32; - value_32 = esp32_tim_getreg(dev, TIM_LO_OFFSET); /* Low 32 bits */ - *value |= (uint64_t)value_32; - - return OK; } /**************************************************************************** @@ -509,7 +365,7 @@ static int esp32_tim_getcounter(FAR struct esp32_tim_dev_s *dev, * ****************************************************************************/ -static int esp32_tim_setcounter(FAR struct esp32_tim_dev_s *dev, +static void esp32_tim_setcounter(FAR struct esp32_tim_dev_s *dev, uint64_t value) { uint64_t low_64 = value & LOW_32_MASK; @@ -521,8 +377,6 @@ static int esp32_tim_setcounter(FAR struct esp32_tim_dev_s *dev, esp32_tim_putreg(dev, TIM_LOAD_LO_OFFSET, (uint32_t)low_64); esp32_tim_putreg(dev, TIM_LOAD_HI_OFFSET, (uint32_t)high_64); - - return OK; } /**************************************************************************** @@ -533,15 +387,13 @@ static int esp32_tim_setcounter(FAR struct esp32_tim_dev_s *dev, * ****************************************************************************/ -static int esp32_tim_reload_now(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_reload_now(FAR struct esp32_tim_dev_s *dev) { DEBUGASSERT(dev); /* Dummy value to trigger reloading */ esp32_tim_putreg(dev, TIM_LOAD_OFFSET, BIT(0)); - - return OK; } /**************************************************************************** @@ -552,7 +404,7 @@ static int esp32_tim_reload_now(FAR struct esp32_tim_dev_s *dev) * ****************************************************************************/ -static int esp32_tim_getalarmvalue(FAR struct esp32_tim_dev_s *dev, +static void esp32_tim_getalarmvalue(FAR struct esp32_tim_dev_s *dev, uint64_t *value) { uint32_t value_32; @@ -564,16 +416,10 @@ static int esp32_tim_getalarmvalue(FAR struct esp32_tim_dev_s *dev, /* Read value */ value_32 = esp32_tim_getreg(dev, TIMG_ALARM_HI_OFFSET); /* High 32 bits */ - *value |= (uint64_t)value_32; - *value <<= SHIFT_32; - value_32 = esp32_tim_getreg(dev, TIMG_ALARM_LO_OFFSET); /* Low 32 bits */ - *value |= (uint64_t)value_32; - - return OK; } /**************************************************************************** @@ -585,7 +431,7 @@ static int esp32_tim_getalarmvalue(FAR struct esp32_tim_dev_s *dev, * ****************************************************************************/ -static int esp32_tim_setalarmvalue(FAR struct esp32_tim_dev_s *dev, +static void esp32_tim_setalarmvalue(FAR struct esp32_tim_dev_s *dev, uint64_t value) { uint64_t low_64 = value & LOW_32_MASK; @@ -597,8 +443,6 @@ static int esp32_tim_setalarmvalue(FAR struct esp32_tim_dev_s *dev, esp32_tim_putreg(dev, TIMG_ALARM_LO_OFFSET, (uint32_t)low_64); esp32_tim_putreg(dev, TIMG_ALARM_HI_OFFSET, (uint32_t)high_64); - - return OK; } /**************************************************************************** @@ -609,7 +453,7 @@ static int esp32_tim_setalarmvalue(FAR struct esp32_tim_dev_s *dev, * ****************************************************************************/ -static int esp32_tim_setalarm(FAR struct esp32_tim_dev_s *dev, bool enable) +static void esp32_tim_setalarm(FAR struct esp32_tim_dev_s *dev, bool enable) { DEBUGASSERT(dev); @@ -621,8 +465,6 @@ static int esp32_tim_setalarm(FAR struct esp32_tim_dev_s *dev, bool enable) { esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_ALARM_EN, 0); } - - return OK; } /**************************************************************************** @@ -636,7 +478,7 @@ static int esp32_tim_setalarm(FAR struct esp32_tim_dev_s *dev, bool enable) * ****************************************************************************/ -static int esp32_tim_setautoreload(FAR struct esp32_tim_dev_s *dev, +static void esp32_tim_setautoreload(FAR struct esp32_tim_dev_s *dev, bool enable) { DEBUGASSERT(dev); @@ -649,15 +491,13 @@ static int esp32_tim_setautoreload(FAR struct esp32_tim_dev_s *dev, { esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_AUTORELOAD, 0); } - - return OK; } /**************************************************************************** * Name: esp32_tim_setisr * * Description: - * Allocates an Edge CPU Interrupt, connects the peripheral source to this + * Allocates a level CPU Interrupt, connects the peripheral source to this * Interrupt, register the callback and enables the Interruption. It does * opposite if the handler and arg are NULL. * @@ -668,7 +508,6 @@ static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler, { FAR struct esp32_tim_priv_s *tim = NULL; int ret = OK; - uint8_t cpu; DEBUGASSERT(dev); @@ -680,62 +519,72 @@ static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler, { /* If a CPU Interrupt was previously allocated, then deallocate it */ - if (tim->cpuint >= 0) + if (tim->cpuint != -ENOMEM) { /* Disable CPU Interrupt, free a previously allocated * CPU Interrupt */ up_disable_irq(tim->cpuint); - cpu = up_cpu_index(); - esp32_detach_peripheral(cpu, tim->periph, tim->cpuint); + esp32_detach_peripheral(tim->core, tim->periph, tim->cpuint); esp32_free_cpuint(tim->cpuint); irq_detach(tim->irq); + tim->cpuint = -ENOMEM; + tim->core = -ENODEV; } - - ret = OK; - goto errout; } /* Otherwise set callback and enable interrupt */ - /* Verify the available CPU Interrupt */ - - tim->cpuint = esp32_alloc_levelint(1); - if (tim->cpuint < 0) + else { - tmrerr("ERROR: No CPU Interrupt available"); - ret = tim->cpuint; - goto errout; + if (tim->cpuint != -ENOMEM) + { + /* Disable the previous CPU Interrupt */ + + up_disable_irq(tim->cpuint); + + /* Free cpu interrupt + * because we will get another from esp32_alloc_levelint + */ + + esp32_free_cpuint(tim->cpuint); + } + + /* Verify the available level CPU Interrupt */ + + tim->cpuint = esp32_alloc_levelint(tim->priority); + if (tim->cpuint < 0) + { + tmrerr("ERROR: No CPU Interrupt available"); + ret = tim->cpuint; + goto errout; + } + + /* Attach a peripheral interrupt to the available CPU interrupt in + * the current core + */ + + tim->core = up_cpu_index(); + esp32_attach_peripheral(tim->core, tim->periph, tim->cpuint); + + /* Associate an IRQ Number (from the timer) to an ISR */ + + ret = irq_attach(tim->irq, handler, arg); + + if (ret != OK) + { + esp32_detach_peripheral(tim->core, tim->periph, tim->cpuint); + esp32_free_cpuint(tim->cpuint); + tmrerr("ERROR: Failed to associate an IRQ Number"); + goto errout; + } + + /* Enable the CPU Interrupt that is linked to the timer */ + + up_enable_irq(tim->cpuint); } - /* Disable the provided CPU Interrupt to configure it */ - - up_disable_irq(tim->cpuint); - - /* Attach a peripheral interrupt to the available CPU interrupt in - * the current core - */ - - cpu = up_cpu_index(); - esp32_attach_peripheral(cpu, tim->periph, tim->cpuint); - - /* Associate an IRQ Number (from the timer) to an ISR */ - - ret = irq_attach(tim->irq, handler, arg); - - if (ret != OK) - { - esp32_detach_peripheral(cpu, tim->periph, tim->cpuint); - esp32_free_cpuint(tim->cpuint); - tmrerr("ERROR: Failed to associate an IRQ Number"); - goto errout; - } - - /* Enable the CPU Interrupt that is linked to the timer */ - - up_enable_irq(tim->cpuint); - errout: return ret; } @@ -748,7 +597,7 @@ errout: * ****************************************************************************/ -static int esp32_tim_enableint(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_enableint(FAR struct esp32_tim_dev_s *dev) { DEBUGASSERT(dev); @@ -771,8 +620,6 @@ static int esp32_tim_enableint(FAR struct esp32_tim_dev_s *dev) esp32_tim_modifyreg32(dev, TIM1_INT_ENA_OFFSET, 0, TIMG_T1_INT_ENA); } - - return OK; } /**************************************************************************** @@ -783,7 +630,7 @@ static int esp32_tim_enableint(FAR struct esp32_tim_dev_s *dev) * ****************************************************************************/ -static int esp32_tim_disableint(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_disableint(FAR struct esp32_tim_dev_s *dev) { DEBUGASSERT(dev); @@ -804,49 +651,6 @@ static int esp32_tim_disableint(FAR struct esp32_tim_dev_s *dev) esp32_tim_modifyreg32(dev, TIM1_INT_ENA_OFFSET, TIMG_T1_INT_ENA, 0); } - - return OK; -} - -/**************************************************************************** - * Name: esp32_tim_checkint - * - * Description: - * Check the interrupt status bit. - * - ****************************************************************************/ - -static int esp32_tim_checkint(FAR struct esp32_tim_dev_s *dev) -{ - int ret = 0; - uint32_t reg_value; - - DEBUGASSERT(dev); - - /* Timer 0 from group 0 or 1 */ - - if (((struct esp32_tim_priv_s *)dev)->base == TIMG_T0CONFIG_REG(0) || - ((struct esp32_tim_priv_s *)dev)->base == TIMG_T0CONFIG_REG(1)) - { - reg_value = esp32_tim_getreg(dev, TIM0_INT_ST_OFFSET); - if (reg_value & TIMG_T0_INT_ST) - { - ret = 1; - } - } - - /* Timer 1 from group 0 or 1 */ - - else - { - reg_value = esp32_tim_getreg(dev, TIM1_INT_ST_OFFSET); - if (reg_value & TIMG_T1_INT_ST) - { - ret = 1; - } - } - - return ret; } /**************************************************************************** @@ -857,7 +661,7 @@ static int esp32_tim_checkint(FAR struct esp32_tim_dev_s *dev) * ****************************************************************************/ -static int esp32_tim_ackint(FAR struct esp32_tim_dev_s *dev) +static void esp32_tim_ackint(FAR struct esp32_tim_dev_s *dev) { DEBUGASSERT(dev); @@ -875,8 +679,6 @@ static int esp32_tim_ackint(FAR struct esp32_tim_dev_s *dev) { esp32_tim_putreg(dev, TIM1_CLR_OFFSET, TIMG_T1_INT_CLR); } - - return OK; } /**************************************************************************** @@ -958,7 +760,7 @@ FAR struct esp32_tim_dev_s *esp32_tim_init(int timer) * ****************************************************************************/ -int esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev) +void esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev) { FAR struct esp32_tim_priv_s *tim = NULL; @@ -967,8 +769,6 @@ int esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev) tim = (FAR struct esp32_tim_priv_s *)dev; tim->inuse = false; - - return OK; } /**************************************************************************** diff --git a/arch/xtensa/src/esp32/esp32_tim.h b/arch/xtensa/src/esp32/esp32_tim.h index ffcf3b812e..586f4412cb 100644 --- a/arch/xtensa/src/esp32/esp32_tim.h +++ b/arch/xtensa/src/esp32/esp32_tim.h @@ -40,10 +40,8 @@ #define ESP32_TIM_START(d) ((d)->ops->start(d)) #define ESP32_TIM_STOP(d) ((d)->ops->stop(d)) #define ESP32_TIM_CLEAR(d) ((d)->ops->clear(d)) -#define ESP32_TIM_CONFIGURE(d, p, m, c, av, a, ar) ((d)->ops->configure(d, m, c, av, a, ar)) #define ESP32_TIM_SETMODE(d, m) ((d)->ops->setmode(d, m)) #define ESP32_TIM_SETPRE(d, p) ((d)->ops->setpre(d, p)) -#define ESP32_TIM_GETCONFIG(d, v) ((d)->ops->getconfig(d, v)) #define ESP32_TIM_GETCTR(d, v) ((d)->ops->getcounter(d, v)) #define ESP32_TIM_SETCTR(d, v) ((d)->ops->setcounter(d, v)) #define ESP32_TIM_RLD_NOW(d) ((d)->ops->reloadnow(d)) @@ -54,7 +52,6 @@ #define ESP32_TIM_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) #define ESP32_TIM_ENABLEINT(d) ((d)->ops->enableint(d)) #define ESP32_TIM_DISABLEINT(d) ((d)->ops->disableint(d)) -#define ESP32_TIM_CHECKINT(d) ((d)->ops->checkint(d)) #define ESP32_TIM_ACKINT(d) ((d)->ops->ackint(d)) /**************************************************************************** @@ -84,39 +81,31 @@ struct esp32_tim_ops_s { /* Timer tasks */ - CODE int (*start)(FAR struct esp32_tim_dev_s *dev); - CODE int (*stop)(FAR struct esp32_tim_dev_s *dev); - CODE int (*clear)(FAR struct esp32_tim_dev_s *dev); - - /* Timer configuration */ - - CODE int (*configure)(FAR struct esp32_tim_dev_s *dev, uint16_t pre, - uint8_t mode, uint64_t counter_value, - uint64_t alarm_value, bool alarm, - bool autoreload); + CODE void (*start)(FAR struct esp32_tim_dev_s *dev); + CODE void (*stop)(FAR struct esp32_tim_dev_s *dev); + CODE void (*clear)(FAR struct esp32_tim_dev_s *dev); /* Timer operations */ - CODE int (*setmode)(FAR struct esp32_tim_dev_s *dev, uint8_t mode); - CODE int (*setpre)(FAR struct esp32_tim_dev_s *dev, uint16_t pre); - CODE int (*getconfig)(FAR struct esp32_tim_dev_s *dev, uint32_t *value); - CODE int (*getcounter)(FAR struct esp32_tim_dev_s *dev, uint64_t *value); - CODE int (*setcounter)(FAR struct esp32_tim_dev_s *dev, uint64_t value); - CODE int (*reloadnow)(FAR struct esp32_tim_dev_s *dev); - CODE int (*getalarmvalue)(FAR struct esp32_tim_dev_s *dev, + CODE void (*setmode)(FAR struct esp32_tim_dev_s *dev, uint8_t mode); + CODE void (*setpre)(FAR struct esp32_tim_dev_s *dev, uint16_t pre); + CODE void (*getcounter)(FAR struct esp32_tim_dev_s *dev, uint64_t *value); + CODE void (*setcounter)(FAR struct esp32_tim_dev_s *dev, uint64_t value); + CODE void (*reloadnow)(FAR struct esp32_tim_dev_s *dev); + CODE void (*getalarmvalue)(FAR struct esp32_tim_dev_s *dev, uint64_t *value); - CODE int (*setalarmvalue)(FAR struct esp32_tim_dev_s *dev, uint64_t value); - CODE int (*setalarm)(FAR struct esp32_tim_dev_s *dev, bool enable); - CODE int (*setautoreload)(FAR struct esp32_tim_dev_s *dev, bool enable); + CODE void (*setalarmvalue)(FAR struct esp32_tim_dev_s *dev, + uint64_t value); + CODE void (*setalarm)(FAR struct esp32_tim_dev_s *dev, bool enable); + CODE void (*setautoreload)(FAR struct esp32_tim_dev_s *dev, bool enable); /* Timer interrupts */ CODE int (*setisr)(FAR struct esp32_tim_dev_s *dev, xcpt_t handler, FAR void * arg); - CODE int (*enableint)(FAR struct esp32_tim_dev_s *dev); - CODE int (*disableint)(FAR struct esp32_tim_dev_s *dev); - CODE int (*checkint)(FAR struct esp32_tim_dev_s *dev); - CODE int (*ackint)(FAR struct esp32_tim_dev_s *dev); + CODE void (*enableint)(FAR struct esp32_tim_dev_s *dev); + CODE void (*disableint)(FAR struct esp32_tim_dev_s *dev); + CODE void (*ackint)(FAR struct esp32_tim_dev_s *dev); }; /**************************************************************************** @@ -124,7 +113,7 @@ struct esp32_tim_ops_s ****************************************************************************/ FAR struct esp32_tim_dev_s *esp32_tim_init(int timer); -int esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev); +void esp32_tim_deinit(FAR struct esp32_tim_dev_s *dev); FAR struct esp32_tim_dev_s *esp32_tim0_init(void); #endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_TIM_H */ diff --git a/arch/xtensa/src/esp32/esp32_tim_lowerhalf.c b/arch/xtensa/src/esp32/esp32_tim_lowerhalf.c index 3b3074c908..0f4a59e5d1 100644 --- a/arch/xtensa/src/esp32/esp32_tim_lowerhalf.c +++ b/arch/xtensa/src/esp32/esp32_tim_lowerhalf.c @@ -23,19 +23,18 @@ ****************************************************************************/ #include - +#include +#include #include #include #include #include #include -#include - -#include -#include #include "xtensa.h" + #include "hardware/esp32_soc.h" + #include "esp32_tim.h" #include "esp32_clockconfig.h" @@ -45,13 +44,7 @@ /* TIMER configuration */ -/* Lowest divider, Highest Frequency Best Resolution */ -#define ESP32_TIMER_PRESCALER 2 -/* Number of cycles to complete 1 microsecond */ -#define ESP32_1USECOND ((esp_clk_apb_freq()/ESP32_TIMER_PRESCALER)/1000000) -#define ESP32_INIT_CNTR_VALUE 0 /* Initial counter value */ #define ESP32_TIMER_MAX_USECOND 0xffffffff -#define ESP32_TIMER_MAX (ESP32_1USECOND*ESP32_TIMER_MAX_USECOND) /**************************************************************************** * Private Types @@ -64,6 +57,7 @@ struct esp32_timer_lowerhalf_s 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 */ }; /**************************************************************************** @@ -160,15 +154,13 @@ static int esp32_timer_handler(int irq, void *context, void *arg) (FAR struct esp32_timer_lowerhalf_s *)arg; uint32_t next_interval_us = 0; - /* Clear Interrupt Bits */ - - if (priv->callback(&next_interval_us, priv->arg)) + if (priv->callback(&next_interval_us, priv->upper)) { if (next_interval_us > 0) { /* Set a value to the alarm */ - ESP32_TIM_SETALRVL(priv->tim, next_interval_us*ESP32_1USECOND); + ESP32_TIM_SETALRVL(priv->tim, next_interval_us); } } else @@ -177,7 +169,6 @@ static int esp32_timer_handler(int irq, void *context, void *arg) } ESP32_TIM_SETALRM(priv->tim, true); /* Re-enables the alarm */ - ESP32_TIM_CLEAR(priv->tim); /* Reset the counter */ ESP32_TIM_ACKINT(priv->tim); /* Clear the Interrupt */ return OK; } @@ -202,6 +193,7 @@ static int esp32_timer_start(FAR struct timer_lowerhalf_s *lower) FAR struct esp32_timer_lowerhalf_s *priv = (FAR struct esp32_timer_lowerhalf_s *)lower; int ret = OK; + uint16_t pre; irqstate_t flags; DEBUGASSERT(priv); @@ -218,43 +210,33 @@ static int esp32_timer_start(FAR struct timer_lowerhalf_s *lower) * unpredictable results, so it is disabled before configuring */ - ret = ESP32_TIM_STOP(priv->tim); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_STOP(priv->tim); + + /* 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 */ - ret = ESP32_TIM_SETPRE(priv->tim, ESP32_TIMER_PRESCALER); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_SETPRE(priv->tim, pre); /* Configure TIMER mode */ - ret = ESP32_TIM_SETMODE(priv->tim, ESP32_TIM_MODE_UP); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_SETMODE(priv->tim, ESP32_TIM_MODE_UP); /* Clear TIMER counter value */ - ret = ESP32_TIM_CLEAR(priv->tim); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_CLEAR(priv->tim); + + /* Enable autoreload */ + + ESP32_TIM_SETARLD(priv->tim, true); /* Enable TIMER alarm */ - ret = ESP32_TIM_SETALRM(priv->tim, true); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_SETALRM(priv->tim, true); /* Clear Interrupt Bits Status */ @@ -265,21 +247,19 @@ static int esp32_timer_start(FAR struct timer_lowerhalf_s *lower) if (priv->callback != NULL) { flags = enter_critical_section(); - - ESP32_TIM_SETISR(priv->tim, esp32_timer_handler, priv); - ESP32_TIM_ENABLEINT(priv->tim); - + ret = ESP32_TIM_SETISR(priv->tim, esp32_timer_handler, priv); leave_critical_section(flags); + if (ret != OK) + { + goto errout; + } + + ESP32_TIM_ENABLEINT(priv->tim); } /* Finally, start the TIMER */ - ret = ESP32_TIM_START(priv->tim); - if (ret != OK) - { - goto errout; - } - + ESP32_TIM_START(priv->tim); priv->started = true; errout: @@ -306,6 +286,7 @@ static int esp32_timer_stop(FAR struct timer_lowerhalf_s *lower) FAR struct esp32_timer_lowerhalf_s *priv = (FAR struct esp32_timer_lowerhalf_s *)lower; int ret = OK; + irqstate_t flags; DEBUGASSERT(priv); @@ -318,7 +299,9 @@ static int esp32_timer_stop(FAR struct timer_lowerhalf_s *lower) } ESP32_TIM_DISABLEINT(priv->tim); - ESP32_TIM_SETISR(priv->tim, NULL, NULL); + flags = enter_critical_section(); + ret = ESP32_TIM_SETISR(priv->tim, NULL, NULL); + leave_critical_section(flags); ESP32_TIM_STOP(priv->tim); priv->started = false; @@ -378,25 +361,15 @@ static int esp32_timer_getstatus(FAR struct timer_lowerhalf_s *lower, /* Get the current counter value */ - ret = ESP32_TIM_GETCTR(priv->tim, ¤t_counter_value); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_GETCTR(priv->tim, ¤t_counter_value); /* Get the current configured timeout */ - ret = ESP32_TIM_GETALRVL(priv->tim, &alarm_value); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_GETALRVL(priv->tim, &alarm_value); - status->timeout = (uint32_t)(alarm_value / ESP32_1USECOND); - status->timeleft = (uint32_t)((alarm_value - current_counter_value) - / ESP32_1USECOND); + status->timeout = (uint32_t)(alarm_value); + status->timeleft = (uint32_t)((alarm_value - current_counter_value)); -errout: return ret; } @@ -422,30 +395,13 @@ static int esp32_timer_settimeout(FAR struct timer_lowerhalf_s *lower, FAR struct esp32_timer_lowerhalf_s *priv = (FAR struct esp32_timer_lowerhalf_s *)lower; int ret = OK; - uint64_t timeout_64; DEBUGASSERT(priv); - /* Verify if it is already running (set timeout must be called - * before start) - */ - - if (priv->started == true) - { - ret = -EPERM; - goto errout; - } - /* Set the timeout */ - timeout_64 = timeout*ESP32_1USECOND; - ret = ESP32_TIM_SETALRVL(priv->tim, timeout_64); - if (ret != OK) - { - goto errout; - } + ESP32_TIM_SETALRVL(priv->tim, (uint64_t)timeout); -errout: return ret; } @@ -468,7 +424,7 @@ errout: static int esp32_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, uint32_t *max_timeout) { - DEBUGASSERT(priv); + DEBUGASSERT(max_timeout); *max_timeout = ESP32_TIMER_MAX_USECOND; @@ -501,30 +457,32 @@ static void esp32_timer_setcallback(FAR struct timer_lowerhalf_s *lower, FAR struct esp32_timer_lowerhalf_s *priv = (FAR struct esp32_timer_lowerhalf_s *)lower; irqstate_t flags; + int ret = OK; DEBUGASSERT(priv); - flags = enter_critical_section(); - /* 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) { - ESP32_TIM_SETISR(priv->tim, esp32_timer_handler, priv); + ret = ESP32_TIM_SETISR(priv->tim, esp32_timer_handler, priv); ESP32_TIM_ENABLEINT(priv->tim); } else { ESP32_TIM_DISABLEINT(priv->tim); - ESP32_TIM_SETISR(priv->tim, NULL, NULL); + ret = ESP32_TIM_SETISR(priv->tim, NULL, NULL); } leave_critical_section(flags); + assert(ret == OK); } /**************************************************************************** @@ -552,7 +510,6 @@ static void esp32_timer_setcallback(FAR struct timer_lowerhalf_s *lower, int esp32_timer_initialize(FAR const char *devpath, uint8_t timer) { struct esp32_timer_lowerhalf_s *lower = NULL; - FAR void *drvr = NULL; int ret = OK; DEBUGASSERT(devpath); @@ -623,8 +580,9 @@ int esp32_timer_initialize(FAR const char *devpath, uint8_t timer) * REVISIT: The returned handle is discarded here. */ - drvr = timer_register(devpath, (FAR struct timer_lowerhalf_s *)lower); - if (drvr == NULL) + 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