mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 08:36:24 +08:00
Tiva Timer: First cut at timer driver lower half (still incomplete)
This commit is contained in:
@@ -98,6 +98,9 @@ endif
|
||||
|
||||
ifeq ($(CONFIG_TIVA_TIMER),y)
|
||||
CHIP_CSRCS += tiva_timer.c
|
||||
ifeq ($(CONFIG_TIMER),y)
|
||||
CHIP_CSRCS += tiva_timerlow.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
|
||||
@@ -820,10 +820,11 @@ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv,
|
||||
#warning Missing Logic
|
||||
|
||||
/* Enable one-shot/periodic interrupts? Enable interrupts only if an
|
||||
* interrupt handler was provided.
|
||||
* non-NULL interrupt handler and non-zero timeout interval were
|
||||
* provided.
|
||||
*/
|
||||
|
||||
if (timer->handler)
|
||||
if (timer->handler && timer->u.periodic.interval > 0)
|
||||
{
|
||||
/* Select the interrupt mask that will enable the timer interrupt.
|
||||
* Any non-zero value of imr indicates that interrupts are expected.
|
||||
@@ -1527,8 +1528,8 @@ static int tiva_timer16_configure(struct tiva_gptmstate_s *priv,
|
||||
|
||||
TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *config)
|
||||
{
|
||||
static const struct tiva_gptmattr_s *attr;
|
||||
static struct tiva_gptmstate_s *priv;
|
||||
const struct tiva_gptmattr_s *attr;
|
||||
struct tiva_gptmstate_s *priv;
|
||||
uint32_t regval;
|
||||
int ret;
|
||||
|
||||
@@ -1542,7 +1543,7 @@ TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *config)
|
||||
case 0:
|
||||
/* Enable GPTM0 clocking and power */
|
||||
|
||||
|
||||
|
||||
attr = &g_gptm0_attr;
|
||||
priv = &g_gptm0_state;
|
||||
break;
|
||||
@@ -1632,7 +1633,7 @@ TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *config)
|
||||
|
||||
while (!tiva_gpio_periphrdy(config->gptm));
|
||||
|
||||
/* Reset the time to be certain that it is in the disabled state */
|
||||
/* Reset the timer to be certain that it is in the disabled state */
|
||||
|
||||
regval = tiva_getreg(priv, TIVA_SYSCON_SRTIMER);
|
||||
regval |= SYSCON_SRTIMER(config->gptm);
|
||||
@@ -1744,6 +1745,64 @@ TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *config)
|
||||
return ret < 0 ? (TIMER_HANDLE)NULL : (TIMER_HANDLE)priv;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_gptm_release
|
||||
*
|
||||
* Description:
|
||||
* Release resources held by the timer instance. After this function is
|
||||
* called, the timer handle is invalid and must not be used further.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tiva_gptm_release(TIMER_HANDLE handle)
|
||||
{
|
||||
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
|
||||
const struct tiva_gptmconfig_s *config;
|
||||
const struct tiva_gptmattr_s *attr;
|
||||
uint32_t regval;
|
||||
|
||||
DEBUGASSERT(priv && priv->attr && priv->config);
|
||||
config = priv->config;
|
||||
attr = priv->attr;
|
||||
|
||||
/* Disable and detach interrupt handlers */
|
||||
|
||||
up_disable_irq(attr->irq[TIMER16A]);
|
||||
up_disable_irq(attr->irq[TIMER16B]);
|
||||
|
||||
(void)irq_detach(attr->irq[TIMER16A]);
|
||||
(void)irq_detach(attr->irq[TIMER16B]);
|
||||
|
||||
/* Reset the time to be certain that it is in the disabled state */
|
||||
|
||||
regval = tiva_getreg(priv, TIVA_SYSCON_SRTIMER);
|
||||
regval |= SYSCON_SRTIMER(config->gptm);
|
||||
tiva_putreg(priv, TIVA_SYSCON_SRTIMER, regval);
|
||||
|
||||
regval &= ~SYSCON_SRTIMER(config->gptm);
|
||||
tiva_putreg(priv, TIVA_SYSCON_SRTIMER, regval);
|
||||
|
||||
/* Wait for the reset to complete */
|
||||
|
||||
while (!tiva_emac_periphrdy());
|
||||
up_udelay(250);
|
||||
|
||||
/* Disable power and clocking to the GPTM module */
|
||||
|
||||
tiva_gptm_disableclk(config->gptm);
|
||||
tiva_gptm_disablepwr(config->gptm);
|
||||
|
||||
/* Un-initialize the state structure */
|
||||
|
||||
memset(priv, 0, sizeof(struct tiva_gptmstate_s));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_gptm_putreg
|
||||
*
|
||||
@@ -2083,6 +2142,241 @@ uint32_t tiva_timer16_counter(TIMER_HANDLE handle, int tmndx)
|
||||
return counter;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_timer32_setinterval
|
||||
*
|
||||
* Description:
|
||||
* This function may be called at any time to change the timer interval
|
||||
* load value of a 32-bit timer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
* interval - The value to write to the timer interval load register
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tiva_timer32_setinterval(TIMER_HANDLE handle, uint32_t interval)
|
||||
{
|
||||
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
|
||||
const struct tiva_gptm32config_s *config;
|
||||
const struct tiva_timer32config_s *timer;
|
||||
irqstate_t flags;
|
||||
uintptr_t base;
|
||||
uintptr_t moder;
|
||||
uintptr_t loadr;
|
||||
uintptr_t icrr;
|
||||
uintptr_t imrr;
|
||||
uint32_t modev1;
|
||||
uint32_t modev2;
|
||||
bool toints;
|
||||
|
||||
DEBUGASSERT(priv && priv->attr && priv->config &&
|
||||
priv->config->mode != TIMER16_MODE);
|
||||
config = (const struct tiva_gptm32config_s *)priv->config;
|
||||
timer = &config->config;
|
||||
|
||||
/* Do we need to control timeout interrupts? */
|
||||
|
||||
base = priv->attr->base;
|
||||
if (timer->handler && interval > 0 &&
|
||||
(config->cmn.mode == TIMER32_MODE_ONESHOT ||
|
||||
config->cmn.mode == TIMER32_MODE_PERIODIC))
|
||||
{
|
||||
priv->imr |= TIMER_INT_TATO;
|
||||
toints = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->imr &= ~TIMER_INT_TATO;
|
||||
toints = false;
|
||||
}
|
||||
|
||||
loadr = base + TIVA_TIMER_TAILR_OFFSET;
|
||||
moder = base + TIVA_TIMER_TAMR_OFFSET;
|
||||
icrr = base + TIVA_TIMER_ICR_OFFSET;
|
||||
imrr = base + TIVA_TIMER_IMR_OFFSET;
|
||||
|
||||
/* Make the following atomic */
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* Set the new timeout interval */
|
||||
|
||||
putreg32(interval, loadr);
|
||||
|
||||
/* Enable/disable timeout interrupts */
|
||||
|
||||
if (toints)
|
||||
{
|
||||
/* Clearing the TACINTD bit allows the time-out interrupt to be
|
||||
* generated as normal
|
||||
*/
|
||||
|
||||
modev1 = tiva_getreg(priv, moder);
|
||||
modev2 = modev1 & ~TIMER_TnMR_TnCINTD;
|
||||
putreg32(modev2, moder);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setting the TACINTD bit prevents the time-out interrupt */
|
||||
|
||||
modev1 = tiva_getreg(priv, moder);
|
||||
modev2 = modev1 | TIMER_TnMR_TnCINTD;
|
||||
putreg32(modev2, moder);
|
||||
|
||||
/* Clear any pending timeout interrupts */
|
||||
|
||||
putreg32(TIMER_INT_TATO, icrr);
|
||||
}
|
||||
|
||||
/* Set the new interrupt mask */
|
||||
|
||||
putreg32(priv->imr, imrr);
|
||||
irqrestore(flags);
|
||||
|
||||
#ifdef CONFIG_TIVA_TIMER_REGDEBUG
|
||||
/* Generate low-level debug output outside of the critical section */
|
||||
|
||||
lldbg("%08x<-%08x\n", loadr, interval);
|
||||
lldbg("%08x->%08x\n", moder, modev1);
|
||||
lldbg("%08x<-%08x\n", moder, modev2);
|
||||
if (!toints)
|
||||
{
|
||||
lldbg("%08x->%08x\n", icrr, TIMER_INT_TATO);
|
||||
}
|
||||
|
||||
lldbg("%08x<-%08x\n", imrr, priv->imr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_timer16_setinterval
|
||||
*
|
||||
* Description:
|
||||
* This function may be called at any time to change the timer interval
|
||||
* load value of a 16-bit timer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
* interval - The value to write to the timer interval load register
|
||||
* tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tiva_timer16_setinterval(TIMER_HANDLE handle, uint16_t interval, int tmndx)
|
||||
{
|
||||
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
|
||||
const struct tiva_gptm16config_s *config;
|
||||
const struct tiva_timer16config_s *timer;
|
||||
irqstate_t flags;
|
||||
uintptr_t base;
|
||||
uintptr_t moder;
|
||||
uintptr_t loadr;
|
||||
uintptr_t icrr;
|
||||
uintptr_t imrr;
|
||||
uint32_t intbit;
|
||||
uint32_t modev1;
|
||||
uint32_t modev2;
|
||||
bool toints;
|
||||
|
||||
DEBUGASSERT(priv && priv->attr && priv->config &&
|
||||
priv->config->mode != TIMER16_MODE);
|
||||
config = (const struct tiva_gptm16config_s *)priv->config;
|
||||
timer = &config->config[tmndx];
|
||||
|
||||
/* Pre-calculate as much as possible outside of the critical section */
|
||||
|
||||
base = priv->attr->base;
|
||||
if (tmndx)
|
||||
{
|
||||
intbit = TIMER_INT_TBTO;
|
||||
loadr = base + TIVA_TIMER_TBILR_OFFSET;
|
||||
moder = base + TIVA_TIMER_TBMR_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
intbit = TIMER_INT_TATO;
|
||||
loadr = base + TIVA_TIMER_TAILR_OFFSET;
|
||||
moder = base + TIVA_TIMER_TAMR_OFFSET;
|
||||
}
|
||||
|
||||
icrr = base + TIVA_TIMER_ICR_OFFSET;
|
||||
imrr = base + TIVA_TIMER_IMR_OFFSET;
|
||||
|
||||
/* Do we need to control timeout interrupts? */
|
||||
|
||||
if (timer->handler && interval > 0 &&
|
||||
(config->cmn.mode == TIMER16_MODE_ONESHOT ||
|
||||
config->cmn.mode == TIMER16_MODE_PERIODIC))
|
||||
{
|
||||
priv->imr |= intbit;
|
||||
toints = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->imr &= ~intbit;
|
||||
toints = false;
|
||||
}
|
||||
|
||||
/* Make the following atomic */
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* Set the new timeout interval */
|
||||
|
||||
putreg32(interval, loadr);
|
||||
|
||||
/* Enable/disable timeout interrupts */
|
||||
|
||||
if (toints)
|
||||
{
|
||||
/* Clearing the TACINTD bit allows the time-out interrupt to be
|
||||
* generated as normal
|
||||
*/
|
||||
|
||||
modev1 = tiva_getreg(priv, moder);
|
||||
modev2 = modev1 & ~TIMER_TnMR_TnCINTD;
|
||||
putreg32(modev2, moder);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setting the TACINTD bit prevents the time-out interrupt */
|
||||
|
||||
modev1 = tiva_getreg(priv, moder);
|
||||
modev2 = modev1 | TIMER_TnMR_TnCINTD;
|
||||
putreg32(modev2, moder);
|
||||
|
||||
/* Clear any pending timeout interrupts */
|
||||
|
||||
putreg32(intbit, icrr);
|
||||
}
|
||||
|
||||
/* Set the new interrupt mask */
|
||||
|
||||
putreg32(priv->imr, imrr);
|
||||
irqrestore(flags);
|
||||
|
||||
#ifdef CONFIG_TIVA_TIMER_REGDEBUG
|
||||
/* Generate low-level debug output outside of the critical section */
|
||||
|
||||
lldbg("%08x<-%08x\n", loadr, interval);
|
||||
lldbg("%08x->%08x\n", moder, modev1);
|
||||
lldbg("%08x<-%08x\n", moder, modev2);
|
||||
if (!toints)
|
||||
{
|
||||
lldbg("%08x->%08x\n", icrr, intbit);
|
||||
}
|
||||
|
||||
lldbg("%08x<-%08x\n", imrr, priv->imr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_rtc_setalarm
|
||||
*
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
|
||||
#include <arch/tiva/chip.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "chip.h"
|
||||
#include "chip/tiva_timer.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -125,6 +127,20 @@
|
||||
#define TIMER_ISDMARTCM(c) ((((c)->flags) & TIMER_FLAG_DMARTCM) != 0)
|
||||
#define TIMER_ISDMAMATCH(c) ((((c)->flags) & TIMER_FLAG_DMAMATCH) != 0)
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
/* Non-standard debug that may be enabled just for testing the timer
|
||||
* driver. NOTE: that only lldbg types are used so that the output is
|
||||
* immediately available.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_TIMER
|
||||
# define timdbg lldbg
|
||||
# define timvdbg llvdbg
|
||||
#else
|
||||
# define timdbg(x...)
|
||||
# define timvdbg(x...)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@@ -320,6 +336,23 @@ struct tiva_gptm16config_s
|
||||
|
||||
TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *gptm);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_gptm_release
|
||||
*
|
||||
* Description:
|
||||
* Release resources held by the timer instance. After this function is
|
||||
* called, the timer handle is invalid and must not be used further.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tiva_gptm_release(TIMER_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_gptm_putreg
|
||||
*
|
||||
@@ -504,61 +537,44 @@ static inline uint32_t tiva_timer32_counter(TIMER_HANDLE handle)
|
||||
uint32_t tiva_timer16_counter(TIMER_HANDLE handle, int tmndx);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_timer32_setload
|
||||
* Name: tiva_timer32_setinterval
|
||||
*
|
||||
* Description:
|
||||
* This function may be called at any time to change the timer interval
|
||||
* load value of a 32-bit timer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
* load - The value to write to the timer interval load register
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
* interval - The value to write to the timer interval load register
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void tiva_timer32_setload(TIMER_HANDLE handle, uint32_t load)
|
||||
{
|
||||
tiva_gptm_putreg(handle, TIVA_TIMER_TAILR_OFFSET, load);
|
||||
}
|
||||
void tiva_timer32_setinterval(TIMER_HANDLE handle, uint32_t interval);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_timer16_setload
|
||||
* Name: tiva_timer16_setinterval
|
||||
*
|
||||
* Description:
|
||||
* This function may be called at any time to change the timer interval
|
||||
* load value of a 16-bit timer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
* load - The value to write to the timer interval load register
|
||||
* tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer
|
||||
* handle - The handle value returned by tiva_gptm_configure()
|
||||
* interval - The value to write to the timer interval load register
|
||||
* tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void tiva_timer16_setload(TIMER_HANDLE handle, uint16_t load,
|
||||
int tmndx)
|
||||
{
|
||||
unsigned int regoffset =
|
||||
tmndx ? TIVA_TIMER_TBILR_OFFSET : TIVA_TIMER_TAILR_OFFSET;
|
||||
void tiva_timer16_setinterval(TIMER_HANDLE handle, uint16_t interval, int tmndx);
|
||||
|
||||
tiva_gptm_putreg(handle, regoffset, load);
|
||||
}
|
||||
|
||||
static inline void tiva_timer16a_setload(TIMER_HANDLE handle, uint16_t load)
|
||||
{
|
||||
tiva_gptm_putreg(handle, TIVA_TIMER_TAILR_OFFSET, load);
|
||||
}
|
||||
|
||||
static inline void tiva_timer16b_setload(TIMER_HANDLE handle, uint16_t load)
|
||||
{
|
||||
tiva_gptm_putreg(handle, TIVA_TIMER_TBILR_OFFSET, load);
|
||||
}
|
||||
#define tiva_timer16a_setinterval(h,l) tiva_timer16_setinterval(h,l,TIMER16A)
|
||||
#define tiva_timer16b_setinterval(h,l) tiva_timer16_setinterval(h,l,TIMER16B)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_timer32_absmatch
|
||||
@@ -768,4 +784,32 @@ static inline void tiva_gptm0_synchronize(uint32_t sync)
|
||||
putreg32(sync, TIVA_TIMER0_SYNC);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tiva_timer_register
|
||||
*
|
||||
* Description:
|
||||
* Bind the configuration timer to a timer lower half instance and
|
||||
* register the timer drivers at 'devpath'
|
||||
*
|
||||
* NOTE: Only 32-bit periodic timers are supported.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the timer device. This should be of the form
|
||||
* /dev/timer0
|
||||
* gptm - General purpose timer number
|
||||
* timeout - Timeout interval in milliseconds. Set to a non-zero value
|
||||
* to enable timeout interrupts
|
||||
* altlck - True: Use alternate clock source.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
int tiva_timer_register(FAR const char *devpath, int gptm, uint32_t timeout,
|
||||
bool altclk);
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_TIVA_TIVA_TIMER_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user