From d8ac2e146891a0d9e9d1cf6360cd1c9e584f4ed3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 8 Jan 2015 09:47:38 -0600 Subject: Tiva Timer: Add basic framework to configure timers. Incomplete on initial commit --- nuttx/arch/arm/src/tiva/Kconfig | 91 +++- nuttx/arch/arm/src/tiva/Make.defs | 4 + nuttx/arch/arm/src/tiva/tiva_enableclks.h | 40 +- nuttx/arch/arm/src/tiva/tiva_enablepwr.h | 42 +- nuttx/arch/arm/src/tiva/tiva_periphrdy.h | 20 +- nuttx/arch/arm/src/tiva/tiva_timer.c | 687 ++++++++++++++++++++++++++++++ nuttx/arch/arm/src/tiva/tiva_timer.h | 207 +++++++++ 7 files changed, 1036 insertions(+), 55 deletions(-) create mode 100644 nuttx/arch/arm/src/tiva/tiva_timer.c create mode 100644 nuttx/arch/arm/src/tiva/tiva_timer.h diff --git a/nuttx/arch/arm/src/tiva/Kconfig b/nuttx/arch/arm/src/tiva/Kconfig index f85548b77..3862c0b53 100644 --- a/nuttx/arch/arm/src/tiva/Kconfig +++ b/nuttx/arch/arm/src/tiva/Kconfig @@ -17,6 +17,7 @@ config ARCH_CHIP_LM3S6918 select ARCH_CHIP_LM3S select TIVA_HAVE_I2C1 select TIVA_HAVE_SSI1 + select TIVA_HAVE_TIMER3 select TIVA_HAVE_ETHERNET config ARCH_CHIP_LM3S9B96 @@ -27,6 +28,7 @@ config ARCH_CHIP_LM3S9B96 select TIVA_HAVE_UART3 select TIVA_HAVE_I2C1 select TIVA_HAVE_SSI1 + select TIVA_HAVE_TIMER3 select TIVA_HAVE_ETHERNET select TIVA_HAVE_GPIOH_IRQS @@ -44,6 +46,7 @@ config ARCH_CHIP_LM3S6965 select ARCH_CHIP_LM3S select TIVA_HAVE_UART3 select TIVA_HAVE_I2C1 + select TIVA_HAVE_TIMER3 select TIVA_HAVE_ETHERNET select TIVA_HAVE_GPIOH_IRQS @@ -54,6 +57,9 @@ config ARCH_CHIP_LM3S8962 select ARCH_CHIP_LM3S select TIVA_HAVE_UART3 select TIVA_HAVE_I2C1 + select TIVA_HAVE_TIMER3 + select TIVA_HAVE_TIMER4 + select TIVA_HAVE_TIMER5 select TIVA_HAVE_ETHERNET select TIVA_HAVE_GPIOH_IRQS @@ -136,6 +142,9 @@ config ARCH_CHIP_LM4F select TIVA_HAVE_SSI1 select TIVA_HAVE_SSI2 select TIVA_HAVE_SSI3 + select TIVA_HAVE_TIMER3 + select TIVA_HAVE_TIMER4 + select TIVA_HAVE_TIMER5 config ARCH_CHIP_TM4C123 bool @@ -149,6 +158,8 @@ config ARCH_CHIP_TM4C129 select TIVA_HAVE_I2C7 select TIVA_HAVE_I2C8 select TIVA_HAVE_I2C9 + select TIVA_HAVE_TIMER6 + select TIVA_HAVE_TIMER7 config ARCH_CHIP_TM4C bool @@ -167,6 +178,9 @@ config ARCH_CHIP_TM4C select TIVA_HAVE_SSI1 select TIVA_HAVE_SSI2 select TIVA_HAVE_SSI3 + select TIVA_HAVE_TIMER3 + select TIVA_HAVE_TIMER4 + select TIVA_HAVE_TIMER5 config LM_REVA2 bool "Rev A2" @@ -266,6 +280,30 @@ config TIVA_SSI bool default n +config TIVA_TIMER + bool + default n + +config TIVA_HAVE_TIMER3 + bool + default n + +config TIVA_HAVE_TIMER4 + bool + default n + +config TIVA_HAVE_TIMER5 + bool + default n + +config TIVA_HAVE_TIMER6 + bool + default n + +config TIVA_HAVE_TIMER7 + bool + default n + config TIVA_I2C0 bool "I2C0" default n @@ -371,28 +409,73 @@ config TIVA_UART7 config TIVA_SSI0 bool "SSI0" - default y + default n depends on TIVA_HAVE_SSI0 select TIVA_SSI config TIVA_SSI1 bool "SSI1" - default y + default n depends on TIVA_HAVE_SSI1 select TIVA_SSI config TIVA_SSI2 bool "SSI2" - default y + default n depends on TIVA_HAVE_SSI2 select TIVA_SSI config TIVA_SSI3 bool "SSI3" - default y + default n depends on TIVA_HAVE_SSI3 select TIVA_SSI +config TIVA_TIMER0 + bool "16-/32-bit Timer 0" + default n + select TIVA_TIMER + +config TIVA_TIMER1 + bool "16-/32-bit Timer 1" + default n + select TIVA_TIMER + +config TIVA_TIMER2 + bool "16-/32-bit Timer 2" + default n + select TIVA_TIMER + +config TIVA_TIMER3 + bool "16-/32-bit Timer 3" + default n + depends on TIVA_HAVE_TIMER3 + select TIVA_TIMER + +config TIVA_TIMER4 + bool "16-/32-bit Timer 4" + default n + depends on TIVA_HAVE_TIMER4 + select TIVA_TIMER + +config TIVA_TIMER5 + bool "16-/32-bit Timer 5" + default n + depends on TIVA_HAVE_TIMER5 + select TIVA_TIMER + +config TIVA_TIMER6 + bool "16-/32-bit Timer 6" + default n + depends on TIVA_HAVE_TIMER6 + select TIVA_TIMER + +config TIVA_TIMER7 + bool "16-/32-bit Timer 7" + default n + depends on TIVA_HAVE_TIMER7 + select TIVA_TIMER + config TIVA_ETHERNET bool "Ethernet" default n diff --git a/nuttx/arch/arm/src/tiva/Make.defs b/nuttx/arch/arm/src/tiva/Make.defs index 2f7a24be9..aa4d9269f 100644 --- a/nuttx/arch/arm/src/tiva/Make.defs +++ b/nuttx/arch/arm/src/tiva/Make.defs @@ -96,6 +96,10 @@ ifeq ($(CONFIG_TIVA_I2C),y) CHIP_CSRCS += tiva_i2c.c endif +ifeq ($(CONFIG_TIVA_TIMER),y) +CHIP_CSRCS += tiva_timer.c +endif + ifeq ($(CONFIG_NET),y) ifeq ($(CONFIG_ARCH_CHIP_LM3S),y) CHIP_CSRCS += lm3s_ethernet.c diff --git a/nuttx/arch/arm/src/tiva/tiva_enableclks.h b/nuttx/arch/arm/src/tiva/tiva_enableclks.h index caac203e3..5f876032b 100644 --- a/nuttx/arch/arm/src/tiva/tiva_enableclks.h +++ b/nuttx/arch/arm/src/tiva/tiva_enableclks.h @@ -73,26 +73,26 @@ /* 16/32-Bit Timer Run Mode Clock Gating Control */ #ifdef TIVA_SYSCON_RCGCTIMER -# define tiva_tm_enableclk(p) tiva_enableclk(TIVA_SYSCON_RCGCTIMER,SYSCON_RCGCTIMER(p)) -# define tiva_tm_disableclk(p) tiva_disableclk(TIVA_SYSCON_RCGCTIMER,SYSCON_RCGCTIMER(p)) - -# define tiva_tm0_enableclk() tiva_tm_enableclk(0) -# define tiva_tm1_enableclk() tiva_tm_enableclk(1) -# define tiva_tm2_enableclk() tiva_tm_enableclk(2) -# define tiva_tm3_enableclk() tiva_tm_enableclk(3) -# define tiva_tm4_enableclk() tiva_tm_enableclk(4) -# define tiva_tm5_enableclk() tiva_tm_enableclk(5) -# define tiva_tm6_enableclk() tiva_tm_enableclk(6) -# define tiva_tm7_enableclk() tiva_tm_enableclk(7) - -# define tiva_tm0_disableclk() tiva_tm_disableclk(0) -# define tiva_tm1_disableclk() tiva_tm_disableclk(1) -# define tiva_tm2_disableclk() tiva_tm_disableclk(2) -# define tiva_tm3_disableclk() tiva_tm_disableclk(3) -# define tiva_tm4_disableclk() tiva_tm_disableclk(4) -# define tiva_tm5_disableclk() tiva_tm_disableclk(5) -# define tiva_tm6_disableclk() tiva_tm_disableclk(6) -# define tiva_tm7_disableclk() tiva_tm_disableclk(7) +# define tiva_gptm_enableclk(p) tiva_enableclk(TIVA_SYSCON_RCGCTIMER,SYSCON_RCGCTIMER(p)) +# define tiva_gptm_disableclk(p) tiva_disableclk(TIVA_SYSCON_RCGCTIMER,SYSCON_RCGCTIMER(p)) + +# define tiva_gptm0_enableclk() tiva_gptm_enableclk(0) +# define tiva_gptm1_enableclk() tiva_gptm_enableclk(1) +# define tiva_gptm2_enableclk() tiva_gptm_enableclk(2) +# define tiva_gptm3_enableclk() tiva_gptm_enableclk(3) +# define tiva_gptm4_enableclk() tiva_gptm_enableclk(4) +# define tiva_gptm5_enableclk() tiva_gptm_enableclk(5) +# define tiva_gptm6_enableclk() tiva_gptm_enableclk(6) +# define tiva_gptm7_enableclk() tiva_gptm_enableclk(7) + +# define tiva_gptm0_disableclk() tiva_gptm_disableclk(0) +# define tiva_gptm1_disableclk() tiva_gptm_disableclk(1) +# define tiva_gptm2_disableclk() tiva_gptm_disableclk(2) +# define tiva_gptm3_disableclk() tiva_gptm_disableclk(3) +# define tiva_gptm4_disableclk() tiva_gptm_disableclk(4) +# define tiva_gptm5_disableclk() tiva_gptm_disableclk(5) +# define tiva_gptm6_disableclk() tiva_gptm_disableclk(6) +# define tiva_gptm7_disableclk() tiva_gptm_disableclk(7) #else #endif diff --git a/nuttx/arch/arm/src/tiva/tiva_enablepwr.h b/nuttx/arch/arm/src/tiva/tiva_enablepwr.h index f7e21be9a..28b91722e 100644 --- a/nuttx/arch/arm/src/tiva/tiva_enablepwr.h +++ b/nuttx/arch/arm/src/tiva/tiva_enablepwr.h @@ -75,30 +75,30 @@ /* 16/32-Bit Timer Power Control */ #ifdef TIVA_SYSCON_PCTIMER -# define tiva_tm_enablepwr(p) tiva_enablepwr(TIVA_SYSCON_PCTIMER,SYSCON_PCTIMER(p)) -# define tiva_tm_disablepwr(p) tiva_disablepwr(TIVA_SYSCON_PCTIMER,SYSCON_PCTIMER(p)) +# define tiva_gptm_enablepwr(p) tiva_enablepwr(TIVA_SYSCON_PCTIMER,SYSCON_PCTIMER(p)) +# define tiva_gptm_disablepwr(p) tiva_disablepwr(TIVA_SYSCON_PCTIMER,SYSCON_PCTIMER(p)) #else -# define tiva_tm_enablepwr(p) -# define tiva_tm_disablepwr(p) +# define tiva_gptm_enablepwr(p) +# define tiva_gptm_disablepwr(p) #endif -#define tiva_tm0_enablepwr() tiva_tm_enablepwr(0) -#define tiva_tm1_enablepwr() tiva_tm_enablepwr(1) -#define tiva_tm2_enablepwr() tiva_tm_enablepwr(2) -#define tiva_tm3_enablepwr() tiva_tm_enablepwr(3) -#define tiva_tm4_enablepwr() tiva_tm_enablepwr(4) -#define tiva_tm5_enablepwr() tiva_tm_enablepwr(5) -#define tiva_tm6_enablepwr() tiva_tm_enablepwr(6) -#define tiva_tm7_enablepwr() tiva_tm_enablepwr(7) - -#define tiva_tm0_disablepwr() tiva_tm_disablepwr(0) -#define tiva_tm1_disablepwr() tiva_tm_disablepwr(1) -#define tiva_tm2_disablepwr() tiva_tm_disablepwr(2) -#define tiva_tm3_disablepwr() tiva_tm_disablepwr(3) -#define tiva_tm4_disablepwr() tiva_tm_disablepwr(4) -#define tiva_tm5_disablepwr() tiva_tm_disablepwr(5) -#define tiva_tm6_disablepwr() tiva_tm_disablepwr(6) -#define tiva_tm7_disablepwr() tiva_tm_disablepwr(7) +#define tiva_gptm0_enablepwr() tiva_gptm_enablepwr(0) +#define tiva_gptm1_enablepwr() tiva_gptm_enablepwr(1) +#define tiva_gptm2_enablepwr() tiva_gptm_enablepwr(2) +#define tiva_gptm3_enablepwr() tiva_gptm_enablepwr(3) +#define tiva_gptm4_enablepwr() tiva_gptm_enablepwr(4) +#define tiva_gptm5_enablepwr() tiva_gptm_enablepwr(5) +#define tiva_gptm6_enablepwr() tiva_gptm_enablepwr(6) +#define tiva_gptm7_enablepwr() tiva_gptm_enablepwr(7) + +#define tiva_gptm0_disablepwr() tiva_gptm_disablepwr(0) +#define tiva_gptm1_disablepwr() tiva_gptm_disablepwr(1) +#define tiva_gptm2_disablepwr() tiva_gptm_disablepwr(2) +#define tiva_gptm3_disablepwr() tiva_gptm_disablepwr(3) +#define tiva_gptm4_disablepwr() tiva_gptm_disablepwr(4) +#define tiva_gptm5_disablepwr() tiva_gptm_disablepwr(5) +#define tiva_gptm6_disablepwr() tiva_gptm_disablepwr(6) +#define tiva_gptm7_disablepwr() tiva_gptm_disablepwr(7) /* GPIO Power Control */ diff --git a/nuttx/arch/arm/src/tiva/tiva_periphrdy.h b/nuttx/arch/arm/src/tiva/tiva_periphrdy.h index a0888d497..b7e86158d 100644 --- a/nuttx/arch/arm/src/tiva/tiva_periphrdy.h +++ b/nuttx/arch/arm/src/tiva/tiva_periphrdy.h @@ -69,19 +69,19 @@ /* 16/32-Bit Timer Power Control */ #ifdef TIVA_SYSCON_PRTIMER -# define tiva_tm_periphrdy(p) tiva_periphrdy(TIVA_SYSCON_PRTIMER,SYSCON_PRTIMER(p)) +# define tiva_gptm_periphrdy(p) tiva_periphrdy(TIVA_SYSCON_PRTIMER,SYSCON_PRTIMER(p)) #else -# define tiva_tm_periphrdy(p) (true) +# define tiva_gptm_periphrdy(p) (true) #endif -#define tiva_tm0_periphrdy() tiva_tm_periphrdy(0) -#define tiva_tm1_periphrdy() tiva_tm_periphrdy(1) -#define tiva_tm2_periphrdy() tiva_tm_periphrdy(2) -#define tiva_tm3_periphrdy() tiva_tm_periphrdy(3) -#define tiva_tm4_periphrdy() tiva_tm_periphrdy(4) -#define tiva_tm5_periphrdy() tiva_tm_periphrdy(5) -#define tiva_tm6_periphrdy() tiva_tm_periphrdy(6) -#define tiva_tm7_periphrdy() tiva_tm_periphrdy(7) +#define tiva_gptm0_periphrdy() tiva_gptm_periphrdy(0) +#define tiva_gptm1_periphrdy() tiva_gptm_periphrdy(1) +#define tiva_gptm2_periphrdy() tiva_gptm_periphrdy(2) +#define tiva_gptm3_periphrdy() tiva_gptm_periphrdy(3) +#define tiva_gptm4_periphrdy() tiva_gptm_periphrdy(4) +#define tiva_gptm5_periphrdy() tiva_gptm_periphrdy(5) +#define tiva_gptm6_periphrdy() tiva_gptm_periphrdy(6) +#define tiva_gptm7_periphrdy() tiva_gptm_periphrdy(7) /* GPIO Power Control */ diff --git a/nuttx/arch/arm/src/tiva/tiva_timer.c b/nuttx/arch/arm/src/tiva/tiva_timer.c new file mode 100644 index 000000000..4dfb65576 --- /dev/null +++ b/nuttx/arch/arm/src/tiva/tiva_timer.c @@ -0,0 +1,687 @@ +/**************************************************************************** + * 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 "up_arch.h" +#include "chip/tiva_syscontrol.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 attrutes of a GPTM module */ + +struct tiva_gptmattr_s +{ + uintptr_t base; /* Register base address */ + int irq[2]; /* Timer A/B interrupt numbers */ +}; + +/* This structure represents the state of a GPTM module */ + +struct tiva_gptmstate_s +{ + const struct tiva_gptmattr_s *attr; + const struct tiva_gptmconfig_s *config; +}; + +/**************************************************************************** + * 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 }, +}; + +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 }, +}; + +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 }, +}; + +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 }, +}; + +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 }, +}; + +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 }, +}; + +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 }, +}; + +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 }, +}; + +static struct tiva_gptmstate_s g_gptm7_state; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * 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; + return getreg32(regaddr); +} + +/**************************************************************************** + * 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; + putreg32(regval, regaddr); +} + +/**************************************************************************** + * 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) +{ + /* 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. + * 2. Write the GPTM Configuration Register (GPTMCFG) with a value of + * 0x0000.0000. + * 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. + * 4. Optionally configure the TnSNAPS, TnWOT, TnMTE, 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. + * 5. Load the start value into the GPTM Timer n Interval Load Register + * (GPTMTnILR). + * 6. If interrupts are required, set the appropriate bits in the GPTM + * Interrupt Mask Register (GPTMIMR). + * 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). + */ +#warning Missing Logic + 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) +{ + /* 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. + * 2. Write the GPTM Configuration Register (GPTMCFG) with a value of + * 0x0000.0000. + * 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. + * 4. Optionally configure the TnSNAPS, TnWOT, TnMTE, 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. + * 5. Load the start value into the GPTM Timer n Interval Load Register + * (GPTMTnILR). + * 6. If interrupts are required, set the appropriate bits in the GPTM + * Interrupt Mask Register (GPTMIMR). + * 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). + */ +#warning Missing Logic + 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. + * 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. + * 3. Write the GPTM Configuration Register (GPTMCFG) with a value of + * 0x0000.0001. + * 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. + */ +#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. + * 2. Write the GPTM Configuration (GPTMCFG) register with a value of + * 0x0000.0004. + * 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. + * 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. + */ +#warning Missing Logic + 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. + * 2. Write the GPTM Configuration (GPTMCFG) register with a value of + * 0x0000.0004. + * 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. + * 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. + */ +#warning Missing Logic + 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. + * 2. Write the GPTM Configuration (GPTMCFG) register with a value of + * 0x0000.0004. + * 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. + * 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. + */ +#warning Missing Logic + 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) +{ + 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. + * + ****************************************************************************/ + +TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *gptm) +{ + static const struct tiva_gptmattr_s *attr; + static struct tiva_gptmstate_s *priv; + uint32_t regval; + int ret; + + DEBUGASSERT(gptm); + + /* Select the GPTM module. */ + + switch (gptm->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 = gptm; + + /* 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(gptm->gptm); + tiva_gptm_enablepwr(gptm->gptm); + + /* Wait for the gptm to become ready before modifying its registers */ + + while (!tiva_gpio_periphrdy(gptm->gptm)); + + /* Reset the time to be certain that it is in the disabled state */ + + regval = tiva_getreg(priv, TIVA_SYSCON_SRTIMER); + regval |= SYSCON_SRTIMER(gptm->gptm); + tiva_putreg(priv, TIVA_SYSCON_SRTIMER, regval); + + regval &= ~SYSCON_SRTIMER(gptm->gptm); + tiva_putreg(priv, TIVA_SYSCON_SRTIMER, regval); + + /* Wait for the reset to complete */ + + while (!tiva_emac_periphrdy()); + up_udelay(250); + + /* Then [re-]configure the timer into the new configuration */ + + if (gptm->mode != TIMER16_MODE) + { + const struct tiva_gptm32config_s *gptm32 = + (const struct tiva_gptm32config_s *)gptm; + + /* Configure the 32-bit timer */ + + ret = tiva_timer32_configure(priv, &gptm32->config); + } + else + { + const struct tiva_gptm16config_s *gptm16 = + (const struct tiva_gptm16config_s *)gptm; + + /* Configure both 16-bit timers */ + + ret = tiva_timer16_configure(priv, &gptm16->config[TIMER_A], TIMER_A); + if (ret == OK) + { + ret = tiva_timer16_configure(priv, &gptm16->config[TIMER_B], + TIMER_B); + } + } + + /* Return the timer handler if successfully configured */ + + return ret < 0 ? (TIMER_HANDLE)NULL : (TIMER_HANDLE)priv; +} diff --git a/nuttx/arch/arm/src/tiva/tiva_timer.h b/nuttx/arch/arm/src/tiva/tiva_timer.h new file mode 100644 index 000000000..b645eddb7 --- /dev/null +++ b/nuttx/arch/arm/src/tiva/tiva_timer.h @@ -0,0 +1,207 @@ +/**************************************************************************** + * arch/arm/src/tiva/tiva_timer.h + * + * Copyright (C) 201r 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TIVA_TIVA_TIMER_H +#define __ARCH_ARM_SRC_TIVA_TIVA_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Make sure that no timers are enabled that are not supported by the + * architecture. + */ + +#if TIVA_NTIMERS < 8 +# undef CONFIG_TIVA_TIMER7 +# if TIVA_NTIMERS < 7 +# undef CONFIG_TIVA_TIMER6 +# if TIVA_NTIMERS < 6 +# undef CONFIG_TIVA_TIMER5 +# if TIVA_NTIMERS < 5 +# undef CONFIG_TIVA_TIMER4 +# if TIVA_NTIMERS < 4 +# undef CONFIG_TIVA_TIMER3 +# if TIVA_NTIMERS < 3 +# undef CONFIG_TIVA_TIMER2 +# if TIVA_NTIMERS < 2 +# undef CONFIG_TIVA_TIMER1 +# if TIVA_NTIMERS < 1 +# undef CONFIG_TIVA_TIMER0 +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif + +/* Used with the synca and syncb fields of struct tiva_timerconfig_s */ + +#define TIMER_SYNC(n) (1 << (n)) + +/* Identifies timer A and timer B */ + +#define TIMER_A 0 +#define TIMER_B 1 + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* This enumeration identifies all supported 32-bit timer modes of operation */ + +enum tiva_timer32mode_e +{ + TIMER16_MODE = 0, /* Use 16-bit timers, not 32-bit timer */ + TIMER32_MODE_ONESHOT, /* 32-bit programmable one-shot timer */ + TIMER32_MODE_PERIODIC, /* 32-bit programmable periodic timer */ + TIMER32_MODE_RTC /* 32-bit RTC with external 32.768-KHz input */ +}; + +/* This enumeration identifies all supported 16-bit timer A/Bmodes of + * operation. + */ + +enum tiva_timer16mode_e +{ + TIMER16_MODE_NONE = 0, /* 16-bit timer not used */ + TIMER16_MODE_ONESHOT, /* 16-bit programmable one-shot timer */ + TIMER16_MODE_PERIODIC, /* 16-bit programmable periodic timer */ + TIMER16_MODE_COUNT_CAPTURE, /* 16-bit input edge-count capture mode w/8-bit prescaler */ + TIMER16_MODE_TIME_CAPTURE, /* 16-bit input time capture mode w/8-bit prescaler */ + TIMER16_MODE_PWM /* 16-bit PWM output mode w/8-bit prescaler */ +}; + +/* This enumeration describes the timer clock source */ + +enum tiva_timersource_e +{ + TIMER_SOURCE_SYSCLK = 0, /* Timer clock source is SysClk */ + TIMER_SOURCE_PIOSC, /* Timer clock source is PIOSC */ + TIMER_SOURCE_RTCOSC, /* Source is Hibernation Module Real-time clock */ + TIMER_SOURCE_LFIOSC /* Timer clock source is LFI oscillator */ +}; + +/* This structure describes the configuration of one 32-bit timer */ + +struct tiva_timer32config_s +{ + bool down; /* False: Count up; True: Count down */ + /* TODO: Add fields to support ADC trigger events */ +}; + +/* This structure describes the configuration of one 16-bit timer A/B */ + +struct tiva_timer16config_s +{ + uint8_t mode; /* See enum tiva_timermode_e */ + bool down; /* False: Count up; True: Count down */ + /* TODO: Add fields to support ADC trigger events */ +}; + +/* This structure describes usage of both timers on a GPTIM module */ + +struct tiva_gptmconfig_s +{ + uint8_t gptm; /* GPTM number */ + uint8_t source; /* See enum tiva_timersource_e */ + uint8_t mode; /* See enum tiva_timer32mode_e */ +}; + +/* This structure is cast compatible with struct tiva_gptmconfig_s and + * describes usage of the single 32-bit timers on a GPTM module. + */ + +struct tiva_gptm32config_s +{ + struct tiva_gptmconfig_s cmn; + struct tiva_timer32config_s config; +}; + +/* This structure is cast compatible with struct tiva_gptmconfig_s and + * describes usage of both bit-bit timers A/B on a GPTM module. + */ + +struct tiva_gptm16config_s +{ + struct tiva_gptmconfig_s cmn; + struct tiva_timer16config_s config[2]; +}; + +/* This type represents the opaque handler returned by tiva_gptm_configure() */ + +typedef FAR void *TIMER_HANDLE; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tiva_gptm_configure + * + * Description: + * Configure a general purpose timer module to operate in the provided + * modes. + * + ****************************************************************************/ + +TIMER_HANDLE tiva_gptm_configure(const struct tiva_gptmconfig_s *gptm); + +/**************************************************************************** + * Name: tiva_gptm0_synchronize + * + * Description: + * Trigger timers from GPTM0 output. + * + ****************************************************************************/ + +int tiva_gptm0_synchronize(uint32_t sync); + +#endif /* __ARCH_ARM_SRC_TIVA_TIVA_TIMER_H */ -- cgit v1.2.3