From fa8521ee2c6e3ade23e07308fe917c111b4c3e95 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 10 Jan 2015 12:22:37 -0600 Subject: Tiva Timer: Add support for RTC match interrupts --- nuttx/arch/arm/src/tiva/tiva_timer.c | 105 +++++++++++++++++++++++++++++++++-- nuttx/arch/arm/src/tiva/tiva_timer.h | 73 ++++++++++++++++++++---- 2 files changed, 163 insertions(+), 15 deletions(-) diff --git a/nuttx/arch/arm/src/tiva/tiva_timer.c b/nuttx/arch/arm/src/tiva/tiva_timer.c index 1a375f89a..cee1d5564 100644 --- a/nuttx/arch/arm/src/tiva/tiva_timer.c +++ b/nuttx/arch/arm/src/tiva/tiva_timer.c @@ -457,13 +457,13 @@ static int tiva_timer32_interrupt(struct tiva_gptmstate_s *priv) { tiva_putreg(priv, TIVA_TIMER_ICR_OFFSET, status); - /* If this was a match interrupt, then disable further match - * interrupts. + /* If this was a match (or RTC match) interrupt, then disable further + * match interrupts. */ - if ((status & TIMER_INT_TAM) != 0) + if ((status & (TIMER_INT_TAM | TIMER_INT_RTC)) != 0) { - priv->imr &= ~TIMER_INT_TAM; + status &= ~(TIMER_INT_TAM | TIMER_INT_RTC); tiva_putreg(priv, TIVA_TIMER_IMR_OFFSET, priv->imr); } @@ -839,7 +839,6 @@ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv, regval &= ~TIMER_TnMR_TnCINTD; } - /* Enable count down? */ if (TIMER_ISCOUNTUP(timer)) @@ -876,6 +875,8 @@ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv, */ #warning Missing Logic + /* TODO: Enable and configure uDMA trigger outputs */ + /* 5. Load the start value into the GPTM Timer n Interval Load Register * (GPTMTAILR). * @@ -1087,6 +1088,8 @@ static int tiva_oneshot_periodic_mode16(struct tiva_gptmstate_s *priv, } } + /* TODO: Enable and configure uDMA trigger outputs */ + /* In addition, if using CCP pins, the TCACT field can be programmed to * configure the compare action. */ @@ -1152,6 +1155,10 @@ static int tiva_oneshot_periodic_mode16(struct tiva_gptmstate_s *priv, * Description: * Configure a 32-bit timer to operate in RTC mode * + * The input clock on a CCP0 input is required to be 32.768 KHz in RTC + * mode. The clock signal is then divided down to a 1-Hz rate and is + * passed along to the input of the counter. + * ****************************************************************************/ static int tiva_rtc_mode32(struct tiva_gptmstate_s *priv, @@ -1931,6 +1938,94 @@ void tiva_timer16_stop(TIMER_HANDLE handle, int tmndx) tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, clrbits, 0); } +/**************************************************************************** + * Name: tiva_rtc_alarm + * + * Description: + * Setup to receive an interrupt when the RTC counter equals a match time + * value. This function sets the match register to the current timer + * counter register value PLUS the relative value provided. The relative + * value then is an offset in seconds from the current time. + * + * NOTE: Use of this function is only meaningful for a a 32-bit RTC time. + * + * Input Parameters: + * handle - The handle value returned by tiva_gptm_configure() + * delay - A relative time in the future (seconds) + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void tiva_rtc_alarm(TIMER_HANDLE handle, uint32_t delay) +{ + struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle; + const struct tiva_timer32config_s *config; + irqstate_t flags; + uintptr_t base; + uint32_t counter; + uint32_t match; + uint32_t adcev; + uint32_t adcbits; + + DEBUGASSERT(priv && priv->attr && priv->config && + priv->config->mode == TIMER32_MODE_RTC); + + /* Update the saved IMR if an interrupt will be needed */ + + config = (const struct tiva_timer32config_s *)priv->config; + if (config->handler) + { + /* Update the saved IMR to enable the RTC match interrupt */ + + priv->imr |= TIMER_INT_RTC; + } + + /* This must be done without interrupt or context switches to minimize + * race conditions with the free-running timer. Note that we also + * by-pass the normal register accesses to keep the latency to a + * minimum. + */ + + base = priv->attr->base; + adcbits = TIMER_ISADCRTCM(config) ? TIMER_ADCEV_RTCADCEN : 0; + + flags = irqsave(); + + /* Set the match register to the current value of the timer counter plus + * the provided relative delay value. + */ + + counter = getreg32(base + TIVA_TIMER_TAR_OFFSET); + match = counter + delay; + putreg32(match, base + TIVA_TIMER_TAMATCHR_OFFSET); + + /* Enable ADC trigger (if selected). NOTE the TAOTE bit was already + * selected in the GPTMCTL register when the timer was configured. + */ + + adcev = getreg32(base + TIVA_TIMER_ADCEV_OFFSET); + putreg32(adcev | adcbits, base + TIVA_TIMER_ADCEV_OFFSET); + + /* TODO: Set uDMA trigger in the same manner */ + + /* Enable interrupts as necessary */ + + putreg32(priv->imr, base + TIVA_TIMER_IMR_OFFSET); + irqrestore(flags); + +#ifdef CONFIG_TIVA_TIMER_REGDEBUG + /* Generate low-level debug output outside of the critical section */ + + lldbg("%08x->%08x\n", base + TIVA_TIMER_TAR_OFFSET, counter); + lldbg("%08x<-%08x\n", base + TIVA_TIMER_TAMATCHR_OFFSET, match); + lldbg("%08x->%08x\n", base + TIVA_TIMER_ADCEV_OFFSET, adcev); + lldbg("%08x<-%08x\n", base + TIVA_TIMER_ADCEV_OFFSET, adcev | adcbits); + lldbg("%08x<-%08x\n", base + TIVA_TIMER_IMR_OFFSET, priv->imr); +#endif +} + /**************************************************************************** * Name: tiva_timer32_relmatch * diff --git a/nuttx/arch/arm/src/tiva/tiva_timer.h b/nuttx/arch/arm/src/tiva/tiva_timer.h index 89e8fa740..a0b9fab30 100644 --- a/nuttx/arch/arm/src/tiva/tiva_timer.h +++ b/nuttx/arch/arm/src/tiva/tiva_timer.h @@ -94,21 +94,47 @@ #define TIMER16B 1 /* Flags bit definitions in configuration structures. NOTE: not all flags - * apply in all timer modes. + * apply in all timer modes. Applicable modes noted with: + * + * a. 32-bit one shot timer + * b. 32-bit periodic timer + * c. 32-bit one shot timer + * d. 32-bit periodic timer + * e. 32-bit RTC timer */ -#define TIMER_FLAG_COUNTUP (1 << 0) /* Bit 0: Count up */ -#define TIMER_FLAG_ADCTIMEOUT (1 << 1) /* Bit 1: Generate ADC trigger on timeout */ -#define TIMER_FLAG_ADCMATCH (1 << 2) /* Bit 2: Generate ADC trigger on match */ +#define TIMER_FLAG_COUNTUP (1 << 0) /* Bit 0: Count up (abcd) */ +#define TIMER_FLAG_ADCTIMEOUT (1 << 1) /* Bit 1: Generate ADC trigger on + * timeout (abcd) */ +#define TIMER_FLAG_ADCRTCM (1 << 2) /* Bit 2: Generate ADC trigger on + * RTC match (e) */ +#define TIMER_FLAG_ADCMATCH (1 << 3) /* Bit 3: Generate ADC trigger on + * match (abcd) */ +#define TIMER_FLAG_DMATIMEOUT (1 << 4) /* Bit 4: Generate uDMA trigger on + * timeout (abcd) */ +#define TIMER_FLAG_DMARTCM (1 << 5) /* Bit 5: Generate uDMA trigger on + * RTC match (e) */ +#define TIMER_FLAG_DMAMATCH (1 << 6) /* Bit 6: Generate uDMA trigger on + * match (abcd) */ #define TIMER_ISCOUNTUP(c) ((((c)->flags) & TIMER_FLAG_COUNTUP) != 0) #define TIMER_ISADCTIMEOUT(c) ((((c)->flags) & TIMER_FLAG_ADCTIMEOUT) != 0) +#define TIMER_ISADCRTCM(c) ((((c)->flags) & TIMER_FLAG_ADCRTCM) != 0) #define TIMER_ISADCMATCH(c) ((((c)->flags) & TIMER_FLAG_ADCMATCH) != 0) +#define TIMER_ISDMATIMEOUT(c) ((((c)->flags) & TIMER_FLAG_DMATIMEOUT) != 0) +#define TIMER_ISDMARTCM(c) ((((c)->flags) & TIMER_FLAG_DMARTCM) != 0) +#define TIMER_ISDMAMATCH(c) ((((c)->flags) & TIMER_FLAG_DMAMATCH) != 0) /**************************************************************************** * Public Types ****************************************************************************/ -/* This enumeration identifies all supported 32-bit timer modes of operation */ +/* This enumeration identifies all supported 32-bit timer modes of operation + * + * NOTES: + * - TIMER32_MODE_RTC: The input clock on a CCP0 input is required to be + * 32.768 KHz in RTC mode. The clock signal is then divided down to a 1-Hz + * rate and is passed along to the input of the counter. + */ enum tiva_timer32mode_e { @@ -118,7 +144,7 @@ enum tiva_timer32mode_e TIMER32_MODE_RTC /* 32-bit RTC with external 32.768-KHz input */ }; -/* This enumeration identifies all supported 16-bit timer A/Bmodes of +/* This enumeration identifies all supported 16-bit timer A/B modes of * operation. */ @@ -545,6 +571,33 @@ static inline void tiva_timer16b_absmatch(TIMER_HANDLE handle, uint16_t absmatch tiva_gptm_putreg(handle, TIVA_TIMER_TBMATCHR_OFFSET, absmatch); } +/**************************************************************************** + * Name: tiva_rtc_alarm + * + * Description: + * Setup to receive an interrupt when the RTC counter equals a match time + * value. This function sets the match register to the current timer + * counter register value PLUS the relative value provided. The relative + * value then is an offset in seconds from the current time. + * + * If an interrupt handler is provided, then the RTC match interrupt will + * be enabled. A single RTC match interrupt will be generated; further + * RTC match interrupts will be disabled. + * + * NOTE: Use of this function is only meaningful for a a 32-bit RTC time. + * NOTE: An interrupt handler address must provided in the configuration. + * + * Input Parameters: + * handle - The handle value returned by tiva_gptm_configure() + * delay - A relative time in the future (seconds) + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void tiva_rtc_alarm(TIMER_HANDLE handle, uint32_t delay); + /**************************************************************************** * Name: tiva_timer32_relmatch * @@ -559,8 +612,8 @@ static inline void tiva_timer16b_absmatch(TIMER_HANDLE handle, uint16_t absmatch * be enabled. A single match interrupt will be generated; further match * interrupts will be disabled. * - * NOTE: Use of this function is only meaningful for a free-runnning, - * periodic timer. + * NOTE: Use of this function is only meaningful for a 32-bit free- + * runnning, periodic timer. * * WARNING: For free-running timers, the relative match value should be * sufficiently far in the future to avoid race conditions. @@ -590,8 +643,8 @@ void tiva_timer32_relmatch(TIMER_HANDLE handle, uint32_t relmatch); * be enabled. A single match interrupt will be generated; further match * interrupts will be disabled. * - * NOTE: Use of this function is only meaningful for a free-runnning, - * periodic timer. + * NOTE: Use of this function is only meaningful for a 16-bit free- + * runnning, periodic timer. * * NOTE: The relmatch input is a really a 24-bit value; it is the 16-bit * match counter match value AND the 8-bit prescaler value. From the -- cgit v1.2.3