Tiva Timer: Add more interrupt management logic

This commit is contained in:
Gregory Nutt 2015-01-09 13:29:03 -06:00
parent 59555646c5
commit 9531dd1a80
3 changed files with 239 additions and 176 deletions

View File

@ -665,124 +665,53 @@
# define TIMER_SYNC_SYNCWT5_TATB TIMER_SYNC_SYNCWT5(TIMER_SYNC_TATB)
#endif
/* GPTM Interrupt Mask (IMR) */
/* Common bit definitions used with:
*
* - GPTM Interrupt Mask (IMR)
* - GPTM Raw Interrupt Status (RIS)
* - GPTM Masked Interrupt Status (MIS)
* - GPTM Interrupt Clear (ICR)
*/
#define TIMER_IMR_TATOIM (1 << 0) /* Bit 0: Timer A Time-Out Interrupt Mask */
#define TIMER_INT_TATO (1 << 0) /* Bit 0: Timer A Time-Out Interrupt */
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_IMR_CAMIM (1 << 1) /* Bit 1: GPTM Timer A Capture Mode Match Interrupt Mask */
# define TIMER_IMR_CAEIM (1 << 2) /* Bit 2: GPTM Timer A Capture Mode Event Interrupt Mask */
# define TIMER_IMR_RTCIM (1 << 3) /* Bit 3: GPTM RTC Interrupt Mask */
# define TIMER_IMR_TAMIM (1 << 4) /* Bit 4: GPTM Timer A Match Interrupt Mask */
# define TIMER_INT_CAM (1 << 1) /* Bit 1: GPTM Timer A Capture Mode Match Interrupt */
# define TIMER_INT_CAE (1 << 2) /* Bit 2: GPTM Timer A Capture Mode Event Interrupt */
# define TIMER_INT_RTC (1 << 3) /* Bit 3: GPTM RTC Interrupt */
# define TIMER_INT_TAM (1 << 4) /* Bit 4: GPTM Timer A Match Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_IMR_DMAAIM (1 << 5) /* Bit 5: GPTM Timer A DMA Done Interrupt Mask */
# define TIMER_INT_DMAA (1 << 5) /* Bit 5: GPTM Timer A DMA Done Interrupt */
#endif
#define TIMER_INT_TBTO (1 << 8) /* Bit 8: GPTM Timer B Time-Out Interrupt */
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_IMR_TBTOIM (1 << 8) /* Bit 8: GPTM Timer B Time-Out Interrupt Mask */
# define TIMER_IMR_CBMIM (1 << 9) /* Bit 9: GPTM Timer B Capture Mode Match Interrupt Mask */
# define TIMER_IMR_CBEIM (1 << 10) /* Bit 10: GPTM Timer B Capture Mode Event Interrupt Mask */
# define TIMER_IMR_TBMIM (1 << 11) /* Bit 11: GPTM Timer B Match Interrupt Mask */
# define TIMER_INT_CBM (1 << 9) /* Bit 9: GPTM Timer B Capture Mode Match Interrupt */
# define TIMER_INT_CBE (1 << 10) /* Bit 10: GPTM Timer B Capture Mode Event Interrupt */
# define TIMER_INT_TBM (1 << 11) /* Bit 11: GPTM Timer B Match Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_IMR_DMABIM (1 << 13) /* Bit 13: GPTM Timer B DMA Done Interrupt Mask */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_IMR_WUEIM (1 << 16) /* Bit 16: 32/64-Bit Wide GPTM Write Update Error Interrupt Mask */
#endif
/* GPTM Raw Interrupt Status (RIS) */
#define TIMER_RIS_TATORIS (1 << 0) /* Bit 0: Timer A Time-Out Raw Interrupt */
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_RIS_CAMRIS (1 << 1) /* Bit 1: GPTM Timer A Capture Mode Match Raw Interrupt */
# define TIMER_RIS_CAERIS (1 << 2) /* Bit 2: GPTM Timer A Capture Mode Event Raw Interrupt */
# define TIMER_RIS_RTCRIS (1 << 3) /* Bit 3: GPTM RTC Raw Interrupt */
# define TIMER_RIS_TAMRIS (1 << 4) /* Bit 4: GPTM Timer A Match Raw Interrupt */
# define TIMER_INT_DMAB (1 << 13) /* Bit 13: GPTM Timer B DMA Done Interrupt */
#elif defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_INT_WUE (1 << 16) /* Bit 16: 32/64-Bit Wide GPTM Write Update Error Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_RIS_DMAARIS (1 << 5) /* Bit 5: GPTM Timer A DMA Done Raw Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_RIS_TBTORIS (1 << 8) /* Bit 8: GPTM Timer B Time-Out Raw Interrupt */
# define TIMER_RIS_CBMRIS (1 << 9) /* Bit 9: GPTM Timer B Capture Mode Match Raw Interrupt */
# define TIMER_RIS_CBERIS (1 << 10) /* Bit 10: GPTM Timer B Capture Mode Event Raw Interrupt */
# define TIMER_RIS_TBMRIS (1 << 11) /* Bit 11: GPTM Timer B Match Raw Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_RIS_DMABRIS (1 << 13) /* Bit 13: GPTM Timer B DMA Done Raw Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_RIS_WUERIS (1 << 16) /* Bit 16: 32/64-Bit Wide GPTM Write Update Error Raw Interrupt */
#endif
/* GPTM Masked Interrupt Status (MIS) */
#define TIMER_MIS_TATOMIS (1 << 0) /* Bit 0: Timer A Time-Out Masked Interrupt */
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_MIS_CAMMIS (1 << 1) /* Bit 1: GPTM Timer A Capture Mode Match Masked Interrupt */
# define TIMER_MIS_CAEMIS (1 << 2) /* Bit 2: GPTM Timer A Capture Mode Event Masked Interrupt */
# define TIMER_MIS_RTCMIS (1 << 3) /* Bit 3: GPTM RTC Masked Interrupt */
# define TIMER_MIS_TAMMIS (1 << 4) /* Bit 4: GPTM Timer A Match Masked Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_MIS_DMAAMIS (1 << 5) /* Bit 5: GPTM Timer A DMA Done Masked Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_MIS_TBTOMIS (1 << 8) /* Bit 8: GPTM Timer B Time-Out Masked Interrupt */
# define TIMER_MIS_CBMMIS (1 << 9) /* Bit 9: GPTM Timer B Capture Mode Match Masked Interrupt */
# define TIMER_MIS_CBEMIS (1 << 10) /* Bit 10: GPTM Timer B Capture Mode Event Masked Interrupt */
# define TIMER_MIS_TBMMIS (1 << 11) /* Bit 11: GPTM Timer B Match Masked Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_MIS_DMABMIS (1 << 13) /* Bit 13: GPTM Timer B DMA Done Masked Interrupt */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_MIS_WUEMIS (1 << 16) /* Bit 16: 32/64-Bit Wide GPTM Write Update Error Masked Interrupt */
#endif
/* GPTM Interrupt Clear (ICR) */
#define TIMER_ICR_TATOCINT (1 << 0) /* Bit 0: Timer A Time-Out Interrupt Clear */
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_ICR_CAMCINT (1 << 1) /* Bit 1: GPTM Timer A Capture Mode Match Interrupt Clear */
# define TIMER_ICR_CAECINT (1 << 2) /* Bit 2: GPTM Timer A Capture Mode Event Interrupt Clear */
# define TIMER_ICR_RTCCINT (1 << 3) /* Bit 3: GPTM RTC Interrupt Clear */
# define TIMER_ICR_TAMCINT (1 << 4) /* Bit 4: GPTM Timer A Match Interrupt Clear */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_ICR_DMAAINT (1 << 5) /* Bit 5: GPTM Timer A DMA Done Interrupt Clear */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_ICR_TBTOCINT (1 << 8) /* Bit 8: GPTM Timer B Time-Out Interrupt Clear */
# define TIMER_ICR_CBMCINT (1 << 9) /* Bit 9: GPTM Timer B Capture Mode Match Interrupt Clear */
# define TIMER_ICR_CBECINT (1 << 10) /* Bit 10: GPTM Timer B Capture Mode Event Interrupt Clear */
# define TIMER_ICR_TBMCINT (1 << 11) /* Bit 11: GPTM Timer B Match Interrupt Clear */
#endif
#if defined(CONFIG_ARCH_CHIP_TM4C129)
# define TIMER_ICR_DMABINT (1 << 13) /* Bit 13: GPTM Timer B DMA Done Interrupt Clear */
#endif
#if defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMER_ICR_WUECINT (1 << 16) /* Bit 16: 32/64-Bit Wide GPTM Write Update Error Interrupt Clear */
# define TIMERA_INTS 0x0000003f
# define TIMERB_INTS 0x00002f00
# define TIMER_ALLINTS 0x00002f3f
#elif defined(CONFIG_ARCH_CHIP_LM4F) || defined(CONFIG_ARCH_CHIP_TM4C)
# define TIMERA_INTS 0x0000001f
# define TIMERB_INTS 0x00000f00
# define TIMER_ALLINTS 0x00010f1f
#else
# define TIMERA_INTS 0x00000001
# define TIMERB_INTS 0x00000100
# define TIMER_ALLINTS 0x00000101
#endif
/* GPTM Timer A Interval Load (TAILR) (32-bit value) */

View File

@ -79,11 +79,15 @@ struct tiva_gptmattr_s
struct tiva_gptmstate_s
{
/* Constant time attributes and configuration */
/* Constant timer attributes and configuration */
const struct tiva_gptmattr_s *attr;
const struct tiva_gptmconfig_s *config;
/* Variable state values */
uint32_t imr; /* Interrupt mask value. Zero if no interrupts */
#ifdef CONFIG_TIVA_TIMER_REGDEBUG
/* Register level debug */
@ -394,6 +398,35 @@ static void tiva_putreg(struct tiva_gptmstate_s *priv, unsigned int offset,
putreg32(regval, regaddr);
}
/****************************************************************************
* Name: tiva_modifyreg
*
* Description:
* This function permits atomic of any timer register by its offset into
* the timer block. Its primary purpose is to support inline functions
* defined in this header file.
*
****************************************************************************/
static void tiva_modifyreg(struct tiva_gptmstate_s *priv, unsigned int offset,
uint32_t clrbits, uint32_t setbits)
{
#ifdef CONFIG_TIVA_TIMER_REGDEBUG
irqstate_t flags;
uint32_t regval;
flags = irqsave();
regval = tiva_getreg(priv, offset);
regval &= ~clrbits;
regval |= setbits;
tiva_putreg(priv, offset, regval);
irqrestore(flags);
#else
uintptr_t regaddr = priv->attr->base + offset;
modifyreg32(regaddr, clrbits, setbits);
#endif
}
/****************************************************************************
* Name: tiva_timer32_interrupt
*
@ -717,8 +750,25 @@ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv,
/* Enable wait-on-trigger? */
#warning Missing Logic
/* Enable one-shot/periodic interrupts? */
#warning Missing Logic
/* Enable one-shot/periodic interrupts? Enable interrupts only if an
* interrupt handler was provided.
*/
if (timer->handler)
{
/* Select the interrupt mask that will enable the timer interrupt.
* Any non-zero value of imr indicates that interrupts are expected.
*/
priv->imr = TIMER_INT_TATO;
/* Clearing the TACINTD bit allows the time-out interrupt to be
* generated as normal
*/
/* REVISIT: When will interrupts be enabled? */
regval &= ~TIMER_TnMR_TnCINTD;
}
/* Enable count down? */
@ -747,8 +797,12 @@ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv,
/* 6. If interrupts are required, set the appropriate bits in the GPTM
* Interrupt Mask Register (GPTMIMR).
*
* NOTE: Interrupts are still disabled at the NVIC. Interrupts will
* be enabled at the NVIC after ther timer is started.
*/
#warning Missing Logic
tiva_putreg(priv, TIVA_TIMER_IMR_OFFSET, priv->imr);
/* 7. Set the TAEN bit in the GPTMCTL register to enable the timer and
* start counting.
@ -854,8 +908,25 @@ static int tiva_oneshot_periodic_mode16(struct tiva_gptmstate_s *priv,
/* Enable wait-on-trigger? */
#warning Missing Logic
/* Enable one-shot/periodic interrupts? */
#warning Missing Logic
/* Enable one-shot/periodic interrupts? Enable interrupts only if an
* interrupt handler was provided.
*/
if (timer->handler)
{
/* Select the interrupt mask that will enable the timer interrupt.
* Any non-zero value of imr indicates that interrupts are expected.
*/
priv->imr |= tmndx ? TIMER_INT_TBTO : TIMER_INT_TATO;
/* Clearing the TnCINTD bit allows the time-out interrupt to be
* generated as normal
*/
/* REVISIT: When will interrupts be enabled? */
regval &= ~TIMER_TnMR_TnCINTD;
}
/* Enable count down? */
@ -880,8 +951,12 @@ static int tiva_oneshot_periodic_mode16(struct tiva_gptmstate_s *priv,
/* 6. If interrupts are required, set the appropriate bits in the GPTM
* Interrupt Mask Register (GPTMIMR).
*
* NOTE: Interrupts are still disabled at the NVIC. Interrupts will
* be enabled at the NVIC after ther timer is started.
*/
#warning Missing Logic
tiva_putreg(priv, TIVA_TIMER_IMR_OFFSET, priv->imr);
/* 7. Set the TnEN bit in the GPTMCTL register to enable the timer and
* start counting.
@ -1322,7 +1397,10 @@ TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *config)
priv->attr = attr;
priv->config = config;
/* Detach all interrupt handlers */
/* Disable and detach all 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]);
@ -1491,9 +1569,119 @@ void tiva_gptm_modifyreg(TIMER_HANDLE handle, unsigned int offset,
uint32_t clrbits, uint32_t setbits)
{
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
uintptr_t regaddr;
DEBUGASSERT(priv && priv->attr);
regaddr = priv->attr->base + offset;
modifyreg32(regaddr, clrbits, setbits);
tiva_modifyreg(priv, offset, clrbits, setbits);
}
/****************************************************************************
* Name: tiva_timer32_start
*
* Description:
* After tiva_gptm_configure() has been called to configure a 32-bit timer,
* this function must be called to start the timer(s).
*
****************************************************************************/
void tiva_timer32_start(TIMER_HANDLE handle)
{
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
DEBUGASSERT(priv && priv->attr);
/* Set the TAEN bit in the GPTMCTL register to enable the 32-bit timer and
* start counting
*/
tiva_modifyreg(priv, TIVA_TIMER_CTL_OFFSET, 0, TIMER_CTL_TAEN);
/* Enable interrupts at the NVIC if interrupts are expected */
if (priv->imr)
{
up_enable_irq(priv->attr->irq[TIMER32]);
}
}
/****************************************************************************
* Name: tiva_timer16_start
*
* Description:
* After tiva_gptm_configure() has been called to configure 16-bit timer(s),
* this function must be called to start one 16-bit timer.
*
****************************************************************************/
void tiva_timer16_start(TIMER_HANDLE handle, int tmndx)
{
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
uint32_t setbits;
uint32_t intmask;
DEBUGASSERT(priv && priv->attr && (unsigned)tmndx < 2);
/* Set the TnEN bit in the GPTMCTL register to enable the 16-bit timer and
* start counting
*/
setbits = tmndx ? TIMER_CTL_TBEN : TIMER_CTL_TAEN;
tiva_modifyreg(priv, TIVA_TIMER_CTL_OFFSET, 0, setbits);
/* Enable interrupts at the NVIC if interrupts are expected */
intmask = tmndx ? TIMERB_INTS : TIMERA_INTS;
if ((priv->imr & intmask) != 0)
{
up_enable_irq(priv->attr->irq[tmndx]);
}
}
/****************************************************************************
* Name: tiva_timer32_stop
*
* Description:
* After tiva_timer32_start() has been called to start a 32-bit timer,
* this function may be called to stop the timer.
*
****************************************************************************/
void tiva_timer32_stop(TIMER_HANDLE handle)
{
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
DEBUGASSERT(priv && priv->attr);
/* Disable interrupts at the NVIC */
up_disable_irq(priv->attr->irq[TIMER32]);
/* Clear the TAEN bit in the GPTMCTL register to disable the 16-bit timer */
tiva_modifyreg(priv, TIVA_TIMER_CTL_OFFSET, TIMER_CTL_TAEN, 0);
}
/****************************************************************************
* Name: tiva_timer16_stop
*
* Description:
* After tiva_timer32_start() has been called to start a 16-bit timer,
* this function may be called to stop the timer.
*
****************************************************************************/
void tiva_timer16_stop(TIMER_HANDLE handle, int tmndx)
{
struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle;
uint32_t clrbits;
DEBUGASSERT(priv && priv->attr && (unsigned)tmndx < 2);
/* Disable interrupts at the NVIC */
up_disable_irq(priv->attr->irq[tmndx]);
/* Clear the TnEN bit in the GPTMCTL register to disable the 16-bit timer */
clrbits = tmndx ? TIMER_CTL_TBEN : TIMER_CTL_TAEN;
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, clrbits, 0);
}

View File

@ -301,14 +301,7 @@ void tiva_gptm_modifyreg(TIMER_HANDLE handle, unsigned int offset,
*
****************************************************************************/
static inline void tiva_timer32_start(TIMER_HANDLE handle)
{
/* Set the TAEN bit in the GPTMCTL register to enable the timer and start
* counting
*/
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, 0, TIMER_CTL_TAEN);
}
void tiva_timer32_start(TIMER_HANDLE handle);
/****************************************************************************
* Name: tiva_timer16_start
@ -319,34 +312,10 @@ static inline void tiva_timer32_start(TIMER_HANDLE handle)
*
****************************************************************************/
static inline void tiva_timer16_start(TIMER_HANDLE handle, int tmndx)
{
uint32_t setbits = tmndx ? TIMER_CTL_TBEN : TIMER_CTL_TAEN;
void tiva_timer16_start(TIMER_HANDLE handle, int tmndx);
/* Set the TnEN bit in the GPTMCTL register to enable the 16-bit timer and
* start counting
*/
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, 0, setbits);
}
static inline void tiva_timer16a_start(TIMER_HANDLE handle)
{
/* Set the TAEN bit in the GPTMCTL register to enable 16-bit timer A and
* start counting
*/
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, 0, TIMER_CTL_TAEN);
}
static inline void tiva_timer16b_start(TIMER_HANDLE handle)
{
/* Set the TBEN bit in the GPTMCTL register to enable 16-bit timer B and
* start counting
*/
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, 0, TIMER_CTL_TBEN);
}
#define tiva_timer16a_start(h) tiva_timer16_start(h, TIMER16A)
#define tiva_timer16b_start(h) tiva_timer16_start(h, TIMER16B)
/****************************************************************************
* Name: tiva_timer32_stop
@ -357,12 +326,7 @@ static inline void tiva_timer16b_start(TIMER_HANDLE handle)
*
****************************************************************************/
static inline void tiva_timer32_stop(TIMER_HANDLE handle)
{
/* Clear the TAEN bit in the GPTMCTL register to disable the 16-bit timer */
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, TIMER_CTL_TAEN, 0);
}
void tiva_timer32_stop(TIMER_HANDLE handle);
/****************************************************************************
* Name: tiva_timer16_stop
@ -373,28 +337,10 @@ static inline void tiva_timer32_stop(TIMER_HANDLE handle)
*
****************************************************************************/
static inline void tiva_timer16_stop(TIMER_HANDLE handle, int tmndx)
{
uint32_t clrbits = tmndx ? TIMER_CTL_TBEN : TIMER_CTL_TAEN;
void tiva_timer16_stop(TIMER_HANDLE handle, int tmndx);
/* Clear the TnEN bit in the GPTMCTL register to disable the 16-bit timer */
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, clrbits, 0);
}
static inline void tiva_timer16a_stop(TIMER_HANDLE handle)
{
/* Clear the TAEN bit in the GPTMCTL register to disable the 16-bit timer A */
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, TIMER_CTL_TAEN, 0);
}
static inline void tiva_timer16b_stop(TIMER_HANDLE handle)
{
/* Clear the TBEN bit in the GPTMCTL register to disable the 16-bit timer B */
tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, TIMER_CTL_TBEN, 0);
}
#define tiva_timer16a_stop(h) tiva_timer16_stop(h, TIMER16A)
#define tiva_timer16b_stop(h) tiva_timer16_stop(h, TIMER16B)
/****************************************************************************
* Name: tiva_timer32_setload