From 487f9a3be98f0056059e59015c49362604e5638f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 12 Jan 2015 09:18:38 -0600 Subject: [PATCH] Tiva Timers: Add interfaces to read the current timer value --- arch/arm/src/tiva/tiva_timer.c | 134 +++++++++++++++++++++++++++++++-- arch/arm/src/tiva/tiva_timer.h | 49 +++++++++++- 2 files changed, 176 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/tiva/tiva_timer.c b/arch/arm/src/tiva/tiva_timer.c index c5266e80bb..5327c68479 100644 --- a/arch/arm/src/tiva/tiva_timer.c +++ b/arch/arm/src/tiva/tiva_timer.c @@ -1958,6 +1958,131 @@ void tiva_timer16_stop(TIMER_HANDLE handle, int tmndx) tiva_gptm_modifyreg(handle, TIVA_TIMER_CTL_OFFSET, clrbits, 0); } +/**************************************************************************** + * Name: tiva_timer16_counter + * + * Description: + * Return the current 24-bit counter value of the 16-bit timer. + * + * The timer 24-bit value is the 16-bit counter value AND the 8-bit + * prescaler value. From the caller's point of view the match value is + * the 24-bit timer at the timer input clock frequency. + * + * When counting down in periodic modes, the prescaler contains the + * least-significant bits of the count. When counting up, the prescaler + * holds the most-significant bits of the count. But the caller is + * protected from this complexity. + * + * Input Parameters: + * handle - The handle value returned by tiva_gptm_configure() + * tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer + * + * Returned Value: + * The current 24-bit counter value. + * + ****************************************************************************/ + +uint32_t tiva_timer16_counter(TIMER_HANDLE handle, int tmndx) +{ + struct tiva_gptmstate_s *priv = (struct tiva_gptmstate_s *)handle; + const struct tiva_gptm16config_s *gptm; + const struct tiva_timer16config_s *config; + irqstate_t flags; + uintptr_t base; + uintptr_t timerr; + uintptr_t prescr; + uint32_t timerv; + uint32_t prescv; + uint32_t checkv; + uint32_t counter; + + DEBUGASSERT(priv && priv->attr && priv->config && + priv->config->mode == TIMER16_MODE && (unsigned)tmndx < 2); + + /* Get settings common to both 16-bit timers */ + + gptm = (const struct tiva_gptm16config_s *)priv->config; + base = priv->attr->base; + + /* Get settings unique to one of the 16-bit timers */ + + if (tmndx) + { + /* Get the Timer B configuration */ + + config = &gptm->config[TIMER16B]; + + /* Get Timer B register addresses */ + + timerr = base + TIVA_TIMER_TBR_OFFSET; + prescr = base + TIVA_TIMER_TBPR_OFFSET; + } + else + { + /* Get the Timer A configuration */ + + config = &gptm->config[TIMER16A]; + + /* Get Timer A register addresses */ + + timerr = base + TIVA_TIMER_TAR_OFFSET; + prescr = base + TIVA_TIMER_TAPR_OFFSET; + } + + /* Are we counting up or down? */ + + if (TIMER_ISCOUNTUP(config)) + { + /* We are counting up. The prescaler holds the most-significant bits of + * the count. Sample these registers until we are assured that there + * is no roll-over from the counter to the prescaler register. + */ + + do + { + flags = irqsave(); + checkv = getreg32(prescr); + timerv = getreg32(timerr); + prescv = getreg32(prescr); + irqrestore(flags); + } + while (checkv != prescv); + + /* Then form the 32-bit counter value with the prescaler as the most + * significant 8-bits. + */ + + counter = (prescv & 0xff) << 16 | (timerv & 0xffff); + } + else + { + /* We are counting down. The prescaler contains the least-significant + * bits of the count. Sample these registers until we are assured that + * there is no roll-over from the counter to the counter register. + */ + + do + { + flags = irqsave(); + checkv = getreg32(timerr); + prescv = getreg32(prescr); + timerv = getreg32(timerr); + irqrestore(flags); + } + while (checkv != timerv); + + /* Then form the 32-bit counter value with the counter as the most + * significant 8-bits. + */ + + counter = (timerv & 0xffff) << 8 | (prescv & 0xff); + } + + /* Return the counter value */ + + return counter; +} + /**************************************************************************** * Name: tiva_rtc_setalarm * @@ -2161,8 +2286,8 @@ void tiva_timer32_relmatch(TIMER_HANDLE handle, uint32_t relmatch) * 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 - * callers point of view the match value is the 24-bit time to match + * match counter match value AND the 8-bit prescaler match value. From + * the caller's point of view the match value is the 24-bit time to match * driven at the timer input clock frequency. * * When counting down in periodic modes, the prescaler contains the @@ -2208,8 +2333,7 @@ void tiva_timer16_relmatch(TIMER_HANDLE handle, uint32_t relmatch, int tmndx) DEBUGASSERT(priv && priv->attr && priv->config && priv->config->mode == TIMER16_MODE && (unsigned)tmndx < 2); - - /* Precalculate as much as possible before entering the critical section */ + /* Pre-calculate as much as possible before entering the critical section */ gptm = (const struct tiva_gptm16config_s *)priv->config; base = priv->attr->base; @@ -2249,7 +2373,7 @@ void tiva_timer16_relmatch(TIMER_HANDLE handle, uint32_t relmatch, int tmndx) priv->imr |= TIMER_INT_TAM; } - /* Get Timer B register addresses */ + /* Get Timer A register addresses */ timerr = base + TIVA_TIMER_TAR_OFFSET; prescr = base + TIVA_TIMER_TAPR_OFFSET; diff --git a/arch/arm/src/tiva/tiva_timer.h b/arch/arm/src/tiva/tiva_timer.h index dc9e4b71d8..a7b809c32d 100644 --- a/arch/arm/src/tiva/tiva_timer.h +++ b/arch/arm/src/tiva/tiva_timer.h @@ -458,6 +458,51 @@ void tiva_timer16_stop(TIMER_HANDLE handle, int tmndx); #define tiva_timer16a_stop(h) tiva_timer16_stop(h, TIMER16A) #define tiva_timer16b_stop(h) tiva_timer16_stop(h, TIMER16B) +/**************************************************************************** + * Name: tiva_timer32_counter + * + * Description: + * Return the current 32-bit counter value of the 32-bit timer. + * + * Input Parameters: + * handle - The handle value returned by tiva_gptm_configure() + * + * Returned Value: + * The current 32-bit counter value. + * + ****************************************************************************/ + +static inline uint32_t tiva_timer32_counter(TIMER_HANDLE handle) +{ + return tiva_gptm_getreg(handle, TIVA_TIMER_TAR_OFFSET); +} + +/**************************************************************************** + * Name: tiva_timer16_counter + * + * Description: + * Return the current 24-bit counter value of the 16-bit timer. + * + * The timer 24-bit value is the 16-bit counter value AND the 8-bit + * prescaler value. From the caller's point of view the match value is + * the 24-bit timer at the timer input clock frequency. + * + * When counting down in periodic modes, the prescaler contains the + * least-significant bits of the count. When counting up, the prescaler + * holds the most-significant bits of the count. But the caller is + * protected from this complexity. + * + * Input Parameters: + * handle - The handle value returned by tiva_gptm_configure() + * tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer + * + * Returned Value: + * The current 24-bit counter value. + * + ****************************************************************************/ + +uint32_t tiva_timer16_counter(TIMER_HANDLE handle, int tmndx); + /**************************************************************************** * Name: tiva_timer32_setload * @@ -676,8 +721,8 @@ void tiva_timer32_relmatch(TIMER_HANDLE handle, uint32_t relmatch); * 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 - * callers point of view the match value is the 24-bit time to match + * match counter match value AND the 8-bit prescaler match value. From + * the caller's point of view the match value is the 24-bit time to match * driven at the timer input clock frequency. * * When counting down in periodic modes, the prescaler contains the