xtensa/esp32: timer driver refactor

This commit is contained in:
Sara Souza 2021-03-03 16:32:45 -03:00 committed by Alan Carvalho de Assis
parent d889350822
commit 4ca0c6e3c8
3 changed files with 177 additions and 430 deletions

View File

@ -23,13 +23,9 @@
****************************************************************************/
#include <nuttx/config.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <stdbool.h>
#include <stdio.h>
#include <debug.h>
#include "xtensa.h"
@ -50,7 +46,9 @@ struct esp32_tim_priv_s
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,
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 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);
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_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 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);
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_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 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_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)
{
case ESP32_TIM_MODE_DOWN:
if (mode == ESP32_TIM_MODE_DOWN)
{
esp32_tim_modifyreg32(dev, TIM_CONFIG_OFFSET, TIMG_T0_INCREASE, 0);
break;
}
case ESP32_TIM_MODE_UP:
else if (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;
}
}
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,28 +519,41 @@ 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 */
else
{
if (tim->cpuint != -ENOMEM)
{
/* Disable the previous CPU Interrupt */
tim->cpuint = esp32_alloc_levelint(1);
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");
@ -709,16 +561,12 @@ static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler,
goto errout;
}
/* 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);
tim->core = up_cpu_index();
esp32_attach_peripheral(tim->core, tim->periph, tim->cpuint);
/* Associate an IRQ Number (from the timer) to an ISR */
@ -726,7 +574,7 @@ static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler,
if (ret != OK)
{
esp32_detach_peripheral(cpu, tim->periph, tim->cpuint);
esp32_detach_peripheral(tim->core, tim->periph, tim->cpuint);
esp32_free_cpuint(tim->cpuint);
tmrerr("ERROR: Failed to associate an IRQ Number");
goto errout;
@ -735,6 +583,7 @@ static int esp32_tim_setisr(FAR struct esp32_tim_dev_s *dev, xcpt_t handler,
/* 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;
}
/****************************************************************************

View File

@ -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 */

View File

@ -23,19 +23,18 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/timers/timer.h>
#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <stdio.h>
#include <nuttx/arch.h>
#include <nuttx/timers/timer.h>
#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);
}
/* Finally, start the TIMER */
ret = ESP32_TIM_START(priv->tim);
if (ret != OK)
{
goto errout;
}
ESP32_TIM_ENABLEINT(priv->tim);
}
/* Finally, start the TIMER */
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, &current_counter_value);
if (ret != OK)
{
goto errout;
}
ESP32_TIM_GETCTR(priv->tim, &current_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