/**************************************************************************** * arch/arm/src/tiva/tiva_timer.h * * Copyright (C) 2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "up_arch.h" #include "chip/tiva_syscontrol.h" #include "chip/tiva_timer.h" #include "tiva_enableclks.h" #include "tiva_enablepwr.h" #include "tiva_periphrdy.h" #include "tiva_timer.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ /* This structure retains the fixed, well-known attributes of a GPTM module */ struct tiva_gptmattr_s { uintptr_t base; /* Register base address */ int irq[2]; /* Timer A/B interrupt numbers */ xcpt_t handler32; /* Handler for 32-bit timer interrupts */ xcpt_t handler16[2]; /* Handlers for 16-bit timer A/B interrupts */ }; /* This structure represents the state of a GPTM module */ struct tiva_gptmstate_s { /* Constant timer attributes and configuration */ const struct tiva_gptmattr_s *attr; const struct tiva_gptmconfig_s *config; /* Variable state values */ uint32_t frequency; /* Frequency of the input clock */ uint32_t imr; /* Interrupt mask value. Zero if no interrupts */ #ifdef CONFIG_TIVA_TIMER_REGDEBUG /* Register level debug */ bool wrlast; /* Last was a write */ uintptr_t addrlast; /* Last address */ uint32_t vallast; /* Last value */ int ntimes; /* Number of times */ #endif }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ /* Register Access */ #ifdef CONFIG_TIVA_TIMER_REGDEBUG static bool tiva_timer_checkreg(struct tiva_gptmstate_s *priv, bool wr, uint32_t regval, uintptr_t regaddr); #endif static uint32_t tiva_getreg(struct tiva_gptmstate_s *priv, unsigned int offset); static void tiva_putreg(struct tiva_gptmstate_s *priv, unsigned int offset, uint32_t regval); /* Interrupt handling */ static int tiva_timer32_interrupt(struct tiva_gptmstate_s *priv); #ifdef CONFIG_TIVA_TIMER0 static int tiva_gptm0_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER1 static int tiva_gptm1_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER2 static int tiva_gptm2_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER3 static int tiva_gptm3_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER4 static int tiva_gptm4_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER5 static int tiva_gptm5_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER6 static int tiva_gptm6_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER7 static int tiva_gptm7_interrupt(int irq, FAR void *context); #endif static int tiva_timer16_interrupt(struct tiva_gptmstate_s *priv, int tmndx); #ifdef CONFIG_TIVA_TIMER0 static int tiva_timer0a_interrupt(int irq, FAR void *context); static int tiva_timer0b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER1 static int tiva_timer1a_interrupt(int irq, FAR void *context); static int tiva_timer1b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER2 static int tiva_timer2a_interrupt(int irq, FAR void *context); static int tiva_timer2b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER3 static int tiva_timer3a_interrupt(int irq, FAR void *context); static int tiva_timer3b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER4 static int tiva_timer4a_interrupt(int irq, FAR void *context); static int tiva_timer4b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER5 static int tiva_timer5a_interrupt(int irq, FAR void *context); static int tiva_timer5b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER6 static int tiva_timer6a_interrupt(int irq, FAR void *context); static int tiva_timer6b_interrupt(int irq, FAR void *context); #endif #ifdef CONFIG_TIVA_TIMER7 static int tiva_timer7a_interrupt(int irq, FAR void *context); static int tiva_timer7b_interrupt(int irq, FAR void *context); #endif /* Timer initialization and configuration */ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv, const struct tiva_timer32config_s *timer); static int tiva_oneshot_periodic_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx); static int tiva_rtc_mode32(struct tiva_gptmstate_s *priv, const struct tiva_timer32config_s *timer); static int tiva_input_edgecount_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx); static int tiva_input_time_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx); static int tiva_pwm_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx); static int tiva_timer32_configure(struct tiva_gptmstate_s *priv, const struct tiva_timer32config_s *timer); static int tiva_timer16_configure(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx); /**************************************************************************** * Private Data ****************************************************************************/ #ifdef CONFIG_TIVA_TIMER0 static const struct tiva_gptmattr_s g_gptm0_attr = { .base = TIVA_TIMER0_BASE, .irq = { TIVA_IRQ_TIMER0A, TIVA_IRQ_TIMER0B }, .handler32 = tiva_gptm0_interrupt, .handler16 = { tiva_timer0a_interrupt, tiva_timer0b_interrupt }, }; static struct tiva_gptmstate_s g_gptm0_state; #endif #ifdef CONFIG_TIVA_TIMER1 static const struct tiva_gptmattr_s g_gptm1_attr = { .base = TIVA_TIMER1_BASE, .irq = { TIVA_IRQ_TIMER1A, TIVA_IRQ_TIMER1B }, .handler32 = tiva_gptm1_interrupt, .handler16 = { tiva_timer1a_interrupt, tiva_timer1b_interrupt }, }; static struct tiva_gptmstate_s g_gptm1_state; #endif #ifdef CONFIG_TIVA_TIMER2 static const struct tiva_gptmattr_s g_gptm2_attr = { .base = TIVA_TIMER2_BASE, .irq = { TIVA_IRQ_TIMER2A, TIVA_IRQ_TIMER2B }, .handler32 = tiva_gptm2_interrupt, .handler16 = { tiva_timer2a_interrupt, tiva_timer2b_interrupt }, }; static struct tiva_gptmstate_s g_gptm2_state; #endif #ifdef CONFIG_TIVA_TIMER3 static const struct tiva_gptmattr_s g_gptm3_attr = { .base = TIVA_TIMER3_BASE, .irq = { TIVA_IRQ_TIMER3A, TIVA_IRQ_TIMER3B }, .handler32 = tiva_gptm3_interrupt, .handler16 = { tiva_timer3a_interrupt, tiva_timer3b_interrupt }, }; static struct tiva_gptmstate_s g_gptm3_state; #endif #ifdef CONFIG_TIVA_TIMER4 static const struct tiva_gptmattr_s g_gptm4_attr = { .base = TIVA_TIMER4_BASE, .irq = { TIVA_IRQ_TIMER4A, TIVA_IRQ_TIMER4B }, .handler32 = tiva_gptm4_interrupt, .handler16 = { tiva_timer4a_interrupt, tiva_timer4b_interrupt }, }; static struct tiva_gptmstate_s g_gptm4_state; #endif #ifdef CONFIG_TIVA_TIMER5 static const struct tiva_gptmattr_s g_gptm5_attr = { .base = TIVA_TIMER5_BASE, .irq = { TIVA_IRQ_TIMER5A, TIVA_IRQ_TIMER5B }, .handler32 = tiva_gptm5_interrupt, .handler16 = { tiva_timer5a_interrupt, tiva_timer5b_interrupt }, }; static struct tiva_gptmstate_s g_gptm5_state; #endif #ifdef CONFIG_TIVA_TIMER6 static const struct tiva_gptmattr_s g_gptm6_attr = { .base = TIVA_TIMER6_BASE, .irq = { TIVA_IRQ_TIMER6A, TIVA_IRQ_TIMER6B }, .handler32 = tiva_gptm6_interrupt, .handler16 = { tiva_timer6a_interrupt, tiva_timer6b_interrupt }, }; static struct tiva_gptmstate_s g_gptm6_state; #endif #ifdef CONFIG_TIVA_TIMER7 static const struct tiva_gptmattr_s g_gptm7_attr = { .base = TIVA_TIMER7_BASE, .irq = { TIVA_IRQ_TIMER7A, TIVA_IRQ_TIMER7B }, .handler32 = tiva_gptm7_interrupt, .handler16 = { tiva_timer7a_interrupt, tiva_timer7b_interrupt }, }; static struct tiva_gptmstate_s g_gptm7_state; #endif /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: tiva_checkreg * * Description: * Check if the current register access is a duplicate of the preceding. * * Input Parameters: * regval - The value to be written * regaddr - The address of the register to write to * * Returned Value: * true: This is the first register access of this type. * flase: This is the same as the preceding register access. * ****************************************************************************/ #ifdef CONFIG_TIVA_TIMER_REGDEBUG static bool tiva_timer_checkreg(struct tiva_gptmstate_s *priv, bool wr, uint32_t regval, uintptr_t regaddr) { if (wr == priv->wrlast && /* Same kind of access? */ regval == priv->vallast && /* Same value? */ regaddr == priv->addrlast) /* Same address? */ { /* Yes, then just keep a count of the number of times we did this. */ priv->ntimes++; return false; } else { /* Did we do the previous operation more than once? */ if (priv->ntimes > 0) { /* Yes... show how many times we did it */ lldbg("...[Repeats %d times]...\n", priv->ntimes); } /* Save information about the new access */ priv->wrlast = wr; priv->vallast = regval; priv->addrlast = regaddr; priv->ntimes = 0; } /* Return true if this is the first time that we have done this operation */ return true; } #endif /**************************************************************************** * Name: tiva_getreg * * Description: * Read one 32-bit GPTM register * ****************************************************************************/ static uint32_t tiva_getreg(struct tiva_gptmstate_s *priv, unsigned int offset) { uintptr_t regaddr = priv->attr->base + offset; uint32_t regval = getreg32(regaddr); #ifdef CONFIG_TIVA_TIMER_REGDEBUG if (tiva_timer_checkreg(priv, false, regval, regaddr)) { lldbg("%08x->%08x\n", regaddr, regval); } #endif return regval; } /**************************************************************************** * Name: tiva_putreg * * Description: * Write one 32-bit GPTM register * ****************************************************************************/ static void tiva_putreg(struct tiva_gptmstate_s *priv, unsigned int offset, uint32_t regval) { uintptr_t regaddr = priv->attr->base + offset; #ifdef CONFIG_TIVA_TIMER_REGDEBUG if (tiva_timer_checkreg(priv, true, regval, regaddr)) { lldbg("%08x<-%08x\n", regaddr, regval); } #endif 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 * * Description: * Common interrupt handler for 32-bit timers * ****************************************************************************/ static int tiva_timer32_interrupt(struct tiva_gptmstate_s *priv) { const struct tiva_gptm32config_s *config32; const struct tiva_timer32config_s *timer32; uint32_t status; DEBUGASSERT(priv && priv->attr && priv->config); /* Status flags are cleared by writing to the corresponding bits in the * GPTMICR register. */ status = tiva_getreg(priv, TIVA_TIMER_MIS_OFFSET); DEBUGASSERT(status != 0); if (status != 0) { tiva_putreg(priv, TIVA_TIMER_ICR_OFFSET, status); /* Get the timer configuration from the private state structure */ config32 = (const struct tiva_gptm32config_s *)priv->config; timer32 = &config32->config; /* Forward the interrupt to the handler. There should always be a non- * NULL handler in this case. */ DEBUGASSERT(timer32->handler); if (timer32->handler) { timer32->handler((TIMER_HANDLE)priv, config32, status); } } return OK; } /**************************************************************************** * Name: tiva_gptmN_interrupt, N=0..7 * * Description: * Individual interrupt handlers for each 32-bit timer * ****************************************************************************/ #ifdef CONFIG_TIVA_TIMER0 static int tiva_gptm0_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm0_state); } #endif #ifdef CONFIG_TIVA_TIMER1 static int tiva_gptm1_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm1_state); } #endif #ifdef CONFIG_TIVA_TIMER2 static int tiva_gptm2_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm2_state); } #endif #ifdef CONFIG_TIVA_TIMER3 static int tiva_gptm3_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm3_state); } #endif #ifdef CONFIG_TIVA_TIMER4 static int tiva_gptm4_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm4_state); } #endif #ifdef CONFIG_TIVA_TIMER5 static int tiva_gptm5_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm5_state); } #endif #ifdef CONFIG_TIVA_TIMER6 static int tiva_gptm6_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm6_state); } #endif #ifdef CONFIG_TIVA_TIMER7 static int tiva_gptm7_interrupt(int irq, FAR void *context) { return tiva_timer32_interrupt(&g_gptm7_state); } #endif /**************************************************************************** * Name: tiva_timer16_interrupt * * Description: * Common interrupt handler for 16-bit timers * ****************************************************************************/ static int tiva_timer16_interrupt(struct tiva_gptmstate_s *priv, int tmndx) { const struct tiva_gptm16config_s *config16; const struct tiva_timer16config_s *timer16; uint32_t intmask; uint32_t status; DEBUGASSERT(priv && priv->attr && priv->config && (unsigned)tmndx < 2); /* Status flags are cleared by writing to the corresponding bits in the * GPTMICR register. */ intmask = tmndx ? TIMERB_INTS : TIMERA_INTS; status = tiva_getreg(priv, TIVA_TIMER_MIS_OFFSET) & intmask; DEBUGASSERT(status != 0); if (status != 0) { tiva_putreg(priv, TIVA_TIMER_ICR_OFFSET, status); /* Get the timer configuration from the private state structure */ config16 = (const struct tiva_gptm16config_s *)priv->config; timer16 = &config16->config[tmndx]; /* Forward the interrupt to the handler. There should always be a * non-NULL handler in this context. */ DEBUGASSERT(timer16->handler); if (timer16->handler) { timer16->handler((TIMER_HANDLE)priv, config16, status, tmndx); } } return OK; } /**************************************************************************** * Name: tiva_timerNa_interrupt, tiva_timerNb_interrupt, N=0..7 * * Description: * Individual interrupt handlers for each 16-bit timer * ****************************************************************************/ #ifdef CONFIG_TIVA_TIMER0 static int tiva_timer0a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm0_state, TIMER16A); } static int tiva_timer0b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm0_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER1 static int tiva_timer1a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm1_state, TIMER16A); } static int tiva_timer1b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm1_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER2 static int tiva_timer2a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm2_state, TIMER16A); } static int tiva_timer2b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm2_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER3 static int tiva_timer3a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm3_state, TIMER16A); } static int tiva_timer3b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm3_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER4 static int tiva_timer4a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm4_state, TIMER16A); } static int tiva_timer4b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm4_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER5 static int tiva_timer5a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm5_state, TIMER16A); } static int tiva_timer5b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm5_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER6 static int tiva_timer6a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm6_state, TIMER16A); } static int tiva_timer6b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm6_state, TIMER16B); } #endif #ifdef CONFIG_TIVA_TIMER7 static int tiva_timer7a_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm7_state, TIMER16A); } static int tiva_timer7b_interrupt(int irq, FAR void *context) { return tiva_timer16_interrupt(&g_gptm7_state, TIMER16B); } #endif /**************************************************************************** * Name: tiva_oneshot_periodic_mode32 * * Description: * Configure a 32-bit timer to operate in one-short or periodic mode * ****************************************************************************/ static int tiva_oneshot_periodic_mode32(struct tiva_gptmstate_s *priv, const struct tiva_timer32config_s *timer) { uint32_t regval; /* The GPTM is configured for One-Shot and Periodic modes by the following * sequence: * * 1. Ensure the timer is disabled (the TAEN bit in the GPTMCTL register * is cleared) before making any changes. * * NOTE: The TAEN bit was cleared when the timer was reset prior to * calling this function. * * 2. Write the GPTM Configuration Register (GPTMCFG) to select 32-bit * operation. */ tiva_putreg(priv, TIVA_TIMER_CFG_OFFSET, TIMER_CFG_CFG_32); /* 3. Configure the TAMR field in the GPTM Timer n Mode Register * (GPTMTAMR): * * a. Write a value of 0x1 for One-Shot mode. * b. Write a value of 0x2 for Periodic mode. * * When Timer A and TimerB are concatenated, the GPTMTBMR register is * ignored and GPTMTAMR controls the modes for both Timer A and Timer B */ regval = tiva_getreg(priv, TIVA_TIMER_TAMR_OFFSET); regval &= ~TIMER_TnMR_TnMR_MASK; if (priv->config->mode == TIMER32_MODE_ONESHOT) { regval |= TIMER_TnMR_TnMR_ONESHOT; } else /* if (priv->config->mode == TIMER32_MODE_PERIODIC) */ { regval |= TIMER_TnMR_TnMR_PERIODIC; } tiva_putreg(priv, TIVA_TIMER_TAMR_OFFSET, regval); /* 4. Optionally configure the TASNAPS, TAWOT, TAMINTD, and TACDIR bits in * the GPTMTAMR register to select whether to capture the value of the * free-running timer at time-out, use an external trigger to start * counting, configure an additional trigger or interrupt, and count up * or down. * * TASNAPS - GPTM Timer A Snap-Shot Mode * 0: Snap-shot mode is disabled (default) * 1: If the 32-bit timeris configured in the periodic mode, * the actual free-running, capture or snapshot value of * the timer is loaded at the time-out event/capture or * snapshot event into the concatenated GPTM Timer A * (GPTMTAR) register. * TAWOT - GPTM Timer A Wait-on-Trigger * 0: The 32-bit timer begins counting as soon as it is * enabled (default). * 1: If the 32-bit timer is enabled, it does not begin * counting until it receives a trigger from the timer * in the previous position in the daisy chain. * TAINTD - One-shot/Periodic Interrupt Disable * 0: Time-out interrupt functions as normal. * 1: Time-out interrupt are disabled (default). * TACDIR - GPTM Timer A Count Direction * 0: The timer counts down (default). * 1: The timer counts up. When counting up, the timer * starts from a value of 0. */ /* Setup defaults */ regval &= (TIMER_TnMR_TnCDIR | TIMER_TnMR_TnWOT | TIMER_TnMR_TnCDIR); regval |= TIMER_TnMR_TnCINTD; /* Enable snapshot mode? */ #warning Missing Logic /* Enable wait-on-trigger? */ #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? */ if (timer->countup) { regval |= TIMER_TnMR_TnCDIR_UP; } tiva_putreg(priv, TIVA_TIMER_TAMR_OFFSET, regval); /* In addition, if using CCP pins, the TCACT field can be programmed to * configure the compare action. */ #warning Missing Logic /* 5. Load the start value into the GPTM Timer n Interval Load Register * (GPTMTAILR). * * When a GPTM is configured to one of the 32-bit modes, GPTMTAILR * appears as a 32-bit register; the upper 16-bits correspond to bits * 15:0 of the GPTM Timer B Interval Load (GPTMTBILR) register. * Writes to GPTMTBILR are ignored. */ tiva_putreg(priv, TIVA_TIMER_TAILR_OFFSET, timer->u.periodic.interval); /* 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. */ 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. * 8. Poll the GPTMRIS register or wait for the interrupt to be generated * (if enabled). In both cases, the status flags are cleared by writing * a 1 to the appropriate bit of the GPTM Interrupt Clear Register * (GPTMICR). * * NOTE: This timer is started until tiva_gptm_enable() is called. */ return -ENOSYS; } /**************************************************************************** * Name: tiva_oneshot_periodic_mode16 * * Description: * Configure 16-bit timer A/B to operate in one-short or periodic mode * ****************************************************************************/ static int tiva_oneshot_periodic_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx) { unsigned int regoffset; uint32_t regval; /* The GPTM is configured for One-Shot and Periodic modes by the following * sequence: * * 1. Ensure the timer is disabled (the TnEN bit in the GPTMCTL register * is cleared) before making any changes. * * NOTE: The TnEN bit was cleared when the timer was reset prior to * calling this function. * * 2. Write the GPTM Configuration Register (GPTMCFG) to select 16-bit * operation. * * NOTE: 16-bit mode of operation was already selected in * tiva_gptm_configure() before this function was called. * * 3. Configure the TnMR field in the GPTM Timer n Mode Register * (GPTMTnMR): * a. Write a value of 0x1 for One-Shot mode. * b. Write a value of 0x2 for Periodic mode. */ regoffset = tmndx ? TIVA_TIMER_TBMR_OFFSET : TIVA_TIMER_TAMR_OFFSET; regval = tiva_getreg(priv, regoffset); regval &= ~TIMER_TnMR_TnMR_MASK; if (timer->mode == TIMER16_MODE_ONESHOT) { regval |= TIMER_TnMR_TnMR_ONESHOT; } else /* if (timer->mode == TIMER16_MODE_PERIODIC) */ { regval |= TIMER_TnMR_TnMR_PERIODIC; } tiva_putreg(priv, regoffset, regval); /* 4. Optionally configure the TnSNAPS, TnWOT, TnMINTD, and TnCDIR bits in * the GPTMTnMR register to select whether to capture the value of the * free-running timer at time-out, use an external trigger to start * counting, configure an additional trigger or interrupt, and count up * or down. In addition, if using CCP pins, the TCACT field can be * programmed to configure the compare action. * * TnSNAPS - GPTM Timer A/B Snap-Shot Mode * 0: Snap-shot mode is disabled (default) * 1: If the 16-bit timer is configured in the periodic mode, * the actual free-running, capture or snapshot value of * the timer is loaded at the time-out event/capture or * snapshot event into the GPTM Timer A/B (GPTMTnR) * register. If the timer prescaler is used, the prescaler * snapshot is loaded into the GPTM Timer A/B (GPTMTnPR). * TnWOT - GPTM Timer A/B Wait-on-Trigger * 0: The 16-bit begins counting as soon as it is enabled (default). * 1: If the 16-bit timer is enabled, it does not begin counting * until it receives a trigger from the timer in the * previous position in the daisy chain. * TnINTD - One-shot/Periodic Interrupt Disable * 0: Time-out interrupt functions as normal. * 1: Time-out interrupt are disabled (default). * TnCDIR - GPTM Timer A/B Count Direction * 0: The timer counts down (default). * 1: The timer counts up. When counting up, the timer * starts from a value of 0. */ /* Setup defaults */ regval &= (TIMER_TnMR_TnCDIR | TIMER_TnMR_TnWOT | TIMER_TnMR_TnCDIR); regval |= TIMER_TnMR_TnCINTD; /* Enable snapshot mode? */ #warning Missing Logic /* Enable wait-on-trigger? */ #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? */ if (timer->countup) { regval |= TIMER_TnMR_TnCDIR_UP; } tiva_putreg(priv, regoffset, regval); /* In addition, if using CCP pins, the TCACT field can be programmed to * configure the compare action. */ #warning Missing Logic /* 5. Load the start value into the GPTM Timer n Interval Load Register * (GPTMTnILR). */ regoffset = tmndx ? TIVA_TIMER_TBILR_OFFSET : TIVA_TIMER_TAILR_OFFSET; tiva_putreg(priv, regoffset, timer->u.periodic.interval); /* 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. */ 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. * 8. Poll the GPTMRIS register or wait for the interrupt to be generated * (if enabled). In both cases, the status flags are cleared by writing * a 1 to the appropriate bit of the GPTM Interrupt Clear Register * (GPTMICR). * * NOTE: This timer is started until tiva_gptm_enable() is called. */ return -ENOSYS; } /**************************************************************************** * Name: tiva_rtc_mode32 * * Description: * Configure a 32-bit timer to operate in RTC mode * ****************************************************************************/ static int tiva_rtc_mode32(struct tiva_gptmstate_s *priv, const struct tiva_timer32config_s *timer) { /* To use the RTC mode, the timer must have a 32.768-KHz input signal on * an even CCP input. To enable the RTC feature, follow these steps: * * 1. Ensure the timer is disabled (the TAEN bit is cleared) before making * any changes. * * NOTE: The TAEN bit was cleared when the timer was reset prior to * calling this function. * * 2. If the timer has been operating in a different mode prior to this, * clear any residual set bits in the GPTM Timer n Mode (GPTMTnMR) * register before reconfiguring. * * NOTE: The TAMR and TBMR registers were cleared when the timer * was reset prior to calling this function. * * 3. Write the GPTM Configuration Register (GPTMCFG) with a to select * the 32-bit RTC mode. */ tiva_putreg(priv, TIVA_TIMER_CFG_OFFSET, TIMER_CFG_CFG_RTC); /* 4. Write the match value to the GPTM Timer n Match Register * (GPTMTnMATCHR). */ /* 5. Set/clear the RTCEN and TnSTALL bit in the GPTM Control Register * (GPTMCTL) as needed. */ /* 6. If interrupts are required, set the RTCIM bit in the GPTM Interrupt * Mask Register (GPTMIMR). */ /* 7. Set the TAEN bit in the GPTMCTL register to enable the timer and * start counting. * * When the timer count equals the value in the GPTMTnMATCHR register, * the GPTM asserts the RTCRIS bit in the GPTMRIS register and continues * counting until Timer A is disabled or a hardware reset. The interrupt * is cleared by writing the RTCCINT bit in the GPTMICR register. Note * that if the GPTMTnILR register is loaded with a new value, the timer * begins counting at this new value and continues until it reaches * 0xFFFF.FFFF, at which point it rolls over. * * NOTE: The timer will not be enabled until tiva_gptm_enable() is called. */ #warning Missing Logic return -ENOSYS; } /**************************************************************************** * Name: tiva_input_edgecount_mode16 * * Description: * Configure 16-bit timer A/B to operate in Input Edge-Count mode * ****************************************************************************/ static int tiva_input_edgecount_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx) { /* A timer is configured to Input Edge-Count mode by the following sequence: * * 1. Ensure the timer is disabled (the TnEN bit is cleared) before making * any changes. * * NOTE: The TnEN bit was cleared when the timer was reset prior to * calling this function. * * 2. Write the GPTM Configuration Register (GPTMCFG) to select 16-bit * operation. * * NOTE: 16-bit mode of operation was already selected in * tiva_gptm_configure() before this function was called. * * 3. In the GPTM Timer Mode (GPTMTnMR) register, write the TnCMR field to * 0x0 and the TnMR field to 0x3. */ /* 4. Configure the type of event(s) that the timer captures by writing * the TnEVENT field of the GPTM Control (GPTMCTL) register. */ /* 5. Program registers according to count direction: * - In down-count mode, the GPTMTnMATCHR and GPTMTnPMR registers are * configured so that the difference between the value in the GPTMTnILR * and GPTMTnPR registers and the GPTMTnMATCHR and GPTMTnPMR registers * equals the number of edge events that must be counted. * - In up-count mode, the timer counts from 0x0 to the value in the * GPTMTnMATCHR and GPTMTnPMR registers. Note that when executing an * up-count, the value of the GPTMTnPR and GPTMTnILR must be greater * than the value of GPTMTnPMR and GPTMTnMATCHR. */ /* 6. If interrupts are required, set the CnMIM bit in the GPTM Interrupt * Mask (GPTMIMR) register. */ #warning Missing Logic /* 7. Set the TnEN bit in the GPTMCTL register to enable the timer and * begin waiting for edge events. * 8. Poll the CnMRIS bit in the GPTMRIS register or wait for the * interrupt to be generated (if enabled). In both cases, the status * flags are cleared by writing a 1 to the CnMCINT bit of the GPTM * Interrupt Clear (GPTMICR) register. * * When counting down in Input Edge-Count Mode, the timer stops after the * programmed number of edge events has been detected. To re-enable the * timer, ensure that the TnEN bit is cleared and repeat steps 4 through 8. * * NOTE: This timer is started until tiva_gptm_enable() is called. */ return -ENOSYS; } /**************************************************************************** * Name: tiva_input_time_mode16 * * Description: * Configure 16-bit timer A/B to operate in Input Time mode * ****************************************************************************/ static int tiva_input_time_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx) { /* A timer is configured to Input Edge Time mode by the following sequence: * * 1. Ensure the timer is disabled (the TnEN bit is cleared) before making * any changes. * * NOTE: The TnEN bit was cleared when the timer was reset prior to * calling this function. * * 2. Write the GPTM Configuration Register (GPTMCFG) to select 16-bit * operation. * * NOTE: 16-bit mode of operation was already selected in * tiva_gptm_configure() before this function was called. * * 3. In the GPTM Timer Mode (GPTMTnMR) register, write the TnCMR field to * 0x1 and the TnMR field to 0x3 and select a count direction by * programming the TnCDIR bit. */ /* 4. Configure the type of event that the timer captures by writing the * TnEVENT field of the GPTM Control (GPTMCTL) register. */ /* 5. If a prescaler is to be used, write the prescale value to the GPTM * Timer n Prescale Register (GPTMTnPR). */ /* 6. Load the timer start value into the GPTM Timer n Interval Load * (GPTMTnILR) register. */ /* 7. If interrupts are required, set the CnEIM bit in the GPTM Interrupt * Mask (GPTMIMR) register. */ #warning Missing Logic /* 8. Set the TnEN bit in the GPTM Control (GPTMCTL) register to enable the * timer and start counting. * 9. Poll the CnERIS bit in the GPTMRIS register or wait for the interrupt * to be generated (if enabled). In both cases, the status flags are * cleared by writing a 1 to the CnECINT bit of the GPTM Interrupt * Clear (GPTMICR) register. The time at which the event happened can * be obtained by reading the GPTM Timer n (GPTMTnR) register. * * In Input Edge Timing mode, the timer continues running after an edge * event has been detected, but the timer interval can be changed at any * time by writing the GPTMTnILR register and clearing the TnILD bit in * the GPTMTnMR register. The change takes effect at the next cycle after * the write. * * NOTE: This timer is started until tiva_gptm_enable() is called. */ return -ENOSYS; } /**************************************************************************** * Name: tiva_pwm_mode16 * * Description: * Configure 16-bit timer A/B to operate in PWM mode * ****************************************************************************/ static int tiva_pwm_mode16(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx) { /* A timer is configured to PWM mode using the following sequence: * * 1. Ensure the timer is disabled (the TnEN bit is cleared) before making * any changes. * * NOTE: The TnEN bit was cleared when the timer was reset prior to * calling this function. * * 2. Write the GPTM Configuration Register (GPTMCFG) to select 16-bit * operation. * * NOTE: 16-bit mode of operation was already selected in * tiva_gptm_configure() before this function was called. * * 3. In the GPTM Timer Mode (GPTMTnMR) register, set the TnAMS bit to * 0x1, the TnCMR bit to 0x0, and the TnMR field to 0x2. */ /* 4. Configure the output state of the PWM signal (whether or not it is * inverted) in the TnPWML field of the GPTM Control (GPTMCTL) register. */ /* 5. If a prescaler is to be used, write the prescale value to the GPTM * Timer n Prescale Register (GPTMTnPR). */ /* 6. If PWM interrupts are used, configure the interrupt condition in the * TnEVENT field in the GPTMCTL register and enable the interrupts by * setting the TnPWMIE bit in the GPTMTnMR register. Note that edge * detect interrupt behavior is reversed when the PWM output is * inverted. */ /* 7. Load the timer start value into the GPTM Timer n Interval Load * (GPTMTnILR) register. */ /* 8. Load the GPTM Timer n Match (GPTMTnMATCHR) register with the match * value. */ #warning Missing Logic /* 9. Set the TnEN bit in the GPTM Control (GPTMCTL) register to enable * the timer and begin generation of the output PWM signal. * * In PWM Time mode, the timer continues running after the PWM signal has * been generated. The PWM period can be adjusted at any time by writing * the GPTMTnILR register, and the change takes effect at the next cycle * after the write. * * NOTE: This timer is started until tiva_gptm_enable() is called. */ return -ENOSYS; } /**************************************************************************** * Name: tiva_timer16_configure * * Description: * Configure the 32-bit timer to operate in the provided mode. * ****************************************************************************/ static int tiva_timer32_configure(struct tiva_gptmstate_s *priv, const struct tiva_timer32config_s *timer) { switch (priv->config->mode) { case TIMER32_MODE_ONESHOT: /* 32-bit programmable one-shot timer */ case TIMER32_MODE_PERIODIC: /* 32-bit programmable periodic timer */ return tiva_oneshot_periodic_mode32(priv, timer); case TIMER32_MODE_RTC: /* 32-bit RTC with external 32.768-KHz * input */ return tiva_rtc_mode32(priv, timer); default: return -EINVAL; } } /**************************************************************************** * Name: tiva_timer16_configure * * Description: * Configure 16-bit timer A or B to operate in the provided mode. * ****************************************************************************/ static int tiva_timer16_configure(struct tiva_gptmstate_s *priv, const struct tiva_timer16config_s *timer, int tmndx) { /* Configure the timer per the selected mode */ switch (timer->mode) { case TIMER16_MODE_NONE: return OK; case TIMER16_MODE_ONESHOT: /* 16-bit programmable one-shot timer */ case TIMER16_MODE_PERIODIC: /* 16-bit programmable periodic timer */ return tiva_oneshot_periodic_mode16(priv, timer, tmndx); case TIMER16_MODE_COUNT_CAPTURE: /* 16-bit input-edge count-capture * mode w/8-bit prescaler */ return tiva_input_edgecount_mode16(priv, timer, tmndx); case TIMER16_MODE_TIME_CAPTURE: /* 16-bit input-edge time-capture * mode w/8-bit prescaler */ return tiva_input_time_mode16(priv, timer, tmndx); case TIMER16_MODE_PWM: /* 16-bit PWM output mode w/8-bit * prescaler */ return tiva_pwm_mode16(priv, timer, tmndx); default: return -EINVAL; } } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: tiva_gptm_configure * * Description: * Configure a general purpose timer module to operate in the provided * modes. * * Input Parameters: * gptm - Describes the configure of the GPTM timer resources * * Returned Value: * On success, a non-NULL handle is returned that can be used with the * other timer interfaces. NULL is returned on any failure to initialize * the timer. * ****************************************************************************/ TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *config) { static const struct tiva_gptmattr_s *attr; static struct tiva_gptmstate_s *priv; uint32_t regval; int ret; DEBUGASSERT(config); /* Select the GPTM module. */ switch (config->gptm) { #ifdef CONFIG_TIVA_TIMER0 case 0: /* Enable GPTM0 clocking and power */ attr = &g_gptm0_attr; priv = &g_gptm0_state; break; #endif #ifdef CONFIG_TIVA_TIMER1 case 1: attr = &g_gptm1_attr; priv = &g_gptm1_state; break; #endif #ifdef CONFIG_TIVA_TIMER2 case 2: attr = &g_gptm2_attr; priv = &g_gptm2_state; break; #endif #ifdef CONFIG_TIVA_TIMER3 case 3: attr = &g_gptm3_attr; priv = &g_gptm3_state; break; #endif #ifdef CONFIG_TIVA_TIMER4 case 4: attr = &g_gptm4_attr; priv = &g_gptm4_state; break; #endif #ifdef CONFIG_TIVA_TIMER5 case 5: attr = &g_gptm5_attr; priv = &g_gptm5_state; break; #endif #ifdef CONFIG_TIVA_TIMER6 case 6: attr = &g_gptm6_attr; priv = &g_gptm6_state; break; #endif #ifdef CONFIG_TIVA_TIMER7 case 7: attr = &g_gptm7_attr; priv = &g_gptm7_state; break; #endif default: return (TIMER_HANDLE)NULL; } /* Initialize the state structure */ memset(priv, 0, sizeof(struct tiva_gptmstate_s)); priv->attr = attr; priv->config = config; /* 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]); /* Enable power and clocking to the GPTM module * * - Enable Power (TM4C129 family only): Applies power (only) to the GPTM * module. This is not an essential step since enabling clocking * will also apply power. The only significance is that the GPTM state * will be retained if the GPTM clocking is subsequently disabled. * - Enable Clocking (All families): Applies both power and clocking to * the GPTM module, bringing it a fully functional state. */ tiva_gptm_enableclk(config->gptm); tiva_gptm_enablepwr(config->gptm); /* Wait for the gptm to become ready before modifying its registers */ while (!tiva_gpio_periphrdy(config->gptm)); /* 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); /* Select the alternate timer clock source is so requested. The general * purpose timer has the capability of being clocked by either the system * clock or an alternate clock source. By setting the ALTCLK bit in the * GPTM Clock Configuration (GPTMCC) register, software can selects an * alternate clock source as programmed in the Alternate Clock * Configuration (ALTCLKCFG) register in the System Control Module. The * alternate clock source options available are PIOSC, RTCOSC and LFIOSC. * * NOTE: The actual alternate clock source selection is a global property * and cannot be configure on a timer-by-timer basis here. That selection * must be done by common logic earlier in the initialization sequence. * * NOTE: Both the frequency of the SysClk (SYSCLK_FREQUENCY) and of the * alternate clock (ALTCLK_FREQUENCY) must be provided in the board.h * header file. */ if (config->alternate) { /* Enable the alternate clock source */ regval = tiva_getreg(priv, TIVA_TIMER_CC_OFFSET); regval |= TIMER_CC_ALTCLK; tiva_putreg(priv, TIVA_TIMER_CC_OFFSET, regval); /* Remember the frequency of the input clock */ priv->frequency = ALTCLK_FREQUENCY; } else { /* Remember the frequency of the input clock */ priv->frequency = SYSCLK_FREQUENCY; } /* Then [re-]configure the timer into the new configuration */ if (config->mode != TIMER16_MODE) { const struct tiva_gptm32config_s *config32 = (const struct tiva_gptm32config_s *)config; /* Attach the 32-bit timer interrupt handler (but do not yet enable * the interrupt). */ ret = irq_attach(attr->irq[TIMER32], attr->handler32); if (ret == OK) { /* Configure the 32-bit timer */ ret = tiva_timer32_configure(priv, &config32->config); } } else { const struct tiva_gptm16config_s *config16 = (const struct tiva_gptm16config_s *)config; /* Attach the 16-bit timer interrupt handlers (but do not yet enable * the interrupts). */ ret = irq_attach(attr->irq[TIMER16A], attr->handler16[TIMER16A]); if (ret == OK) { ret = irq_attach(attr->irq[TIMER16B], attr->handler16[TIMER16B]); } if (ret == OK) { /* Write the GPTM Configuration Register (GPTMCFG) to select 16- * bit operation. */ tiva_putreg(priv, TIVA_TIMER_CFG_OFFSET, TIMER_CFG_CFG_16); /* Configure 16-bit timer A */ ret = tiva_timer16_configure(priv, &config16->config[TIMER16A], TIMER16A); } /* Configure 16-bit timer B */ if (ret == OK) { ret = tiva_timer16_configure(priv, &config16->config[TIMER16B], TIMER16B); } } /* Return the timer handler if successfully configured */ return ret < 0 ? (TIMER_HANDLE)NULL : (TIMER_HANDLE)priv; } /**************************************************************************** * Name: tiva_gptm_putreg * * Description: * This function permits setting of any timer register by its offset into * the timer block. Its primary purpose is to support inline functions * defined in this header file. * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * offset - The offset to the timer register to be written * value - The value to write to the timer register * * Returned Value: * None. * ****************************************************************************/ void tiva_gptm_putreg(TIMER_HANDLE handle, unsigned int offset, uint32_t value) { DEBUGASSERT(handle); tiva_putreg((struct tiva_gptmstate_s *)handle, offset, value); } /**************************************************************************** * Name: tiva_gptm_getreg * * Description: * This function permits reading of any timer register by its offset into * the timer block. Its primary purpose is to support inline functions * defined in this header file. * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * offset - The offset to the timer register to be written * * Returned Value: * The 32-bit value read at the provided offset into the timer register base * address. * ****************************************************************************/ uint32_t tiva_gptm_getreg(TIMER_HANDLE handle, unsigned int offset) { DEBUGASSERT(handle); return tiva_getreg((struct tiva_gptmstate_s *)handle, offset); } /**************************************************************************** * Name: tiva_gptm_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. * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * offset - The offset to the timer register to be written * clrbits - The collection of bits to be cleared in the register * setbits - The collection of bits to be set in the register * * Returned Value: * None. * ****************************************************************************/ 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; DEBUGASSERT(priv && priv->attr); 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). * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * * Returned Value: * None. * ****************************************************************************/ 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. * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer * * Returned Value: * None. * ****************************************************************************/ 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. * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * * Returned Value: * None. * ****************************************************************************/ 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. * * Input Parameters: * handle - The handle value returned by tiva_gptm_configure() * tmndx - Either TIMER16A or TIMER16B to select the 16-bit timer * * Returned Value: * None. * ****************************************************************************/ 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); }