From a76f2b853a63763a0643e1c203f2e3b1ba4e2a50 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 23 Dec 2015 13:41:36 -0600 Subject: [PATCH] TMS570: Add system timer logic --- arch/arm/src/tms570/chip/tms570_rti.h | 81 ++++++------ arch/arm/src/tms570/tms570_clockconfig.c | 48 +++++++- arch/arm/src/tms570/tms570_irq.c | 25 +--- arch/arm/src/tms570/tms570_irq.h | 17 --- arch/arm/src/tms570/tms570_timerisr.c | 150 +++++++++++++++++++++++ 5 files changed, 236 insertions(+), 85 deletions(-) diff --git a/arch/arm/src/tms570/chip/tms570_rti.h b/arch/arm/src/tms570/chip/tms570_rti.h index 6be1958bf2..69fc30739d 100644 --- a/arch/arm/src/tms570/chip/tms570_rti.h +++ b/arch/arm/src/tms570/chip/tms570_rti.h @@ -137,53 +137,44 @@ /* Register Bit-Field Definitions *******************************************************************/ /* RTI Global Control Register */ -#define RTI_GCTRL_ + +#define RTI_GCTRL_CNT0EN (1 << 0) /* Bit 0: Counter 0 enable */ +#define RTI_GCTRL_CNT1EN (1 << 1) /* Bit 1: Counter 1 enable */ +#define RTI_GCTRL_COS (1 << 15) /* Bit 15: Continue on suspend */ + /* RTI Capture Control Register */ -#define RTI_CAPCTRL_ + +#define RTI_CAPCTRL_CAPCNTR0 (1 << 0) /* Bit 0: Capture counter 0 */ +#define RTI_CAPCTRL_CAPCNTR1 (1 << 1) /* Bit 1: Capture counter 1 */ + /* RTI Compare Control Register */ -#define RTI_COMPCTRL_ -/* RTI Free Running Counter 0 Register */ -#define RTI_FRC0_ -/* RTI Up Counter 0 Register */ -#define RTI_UC0_ -/* RTI Compare Up Counter 0 Register */ -#define RTI_CPUC0_ -/* RTI Capture Free Running Counter 0 Register */ -#define RTI_CAFRC0_ -/* RTI Capture Up Counter 0 Register */ -#define RTI_CAUC0_ -/* RTI Free Running Counter 1 Register */ -#define RTI_FRC1_ -/* RTI Up Counter 1 Register */ -#define RTI_UC1_ -/* RTI Compare Up Counter 1 Register */ -#define RTI_CPUC1_ -/* RTI Capture Free Running Counter 1 Register */ -#define RTI_CAFRC1_ -/* RTI Capture Up Counter 1 Register */ -#define RTI_CAUC1_ -/* RTI Compare 0 Register Section */ -#define RTI_COMP0_ -/* RTI Update Compare 0 Register */ -#define RTI_UDCP0_ -/* RTI Compare 1 Register */ -#define RTI_COMP1_ -/* RTI Update Compare 1 Register */ -#define RTI_UDCP1_ -/* RTI Compare 2 Register */ -#define RTI_COMP2_ -/* RTI Update Compare 2 Register */ -#define RTI_UDCP2_ -/* RTI Compare 3 Register */ -#define RTI_COMP3_ -/* RTI Update Compare 3 Register */ -#define RTI_UDCP3_ -/* RTI Set Interrupt Enable Register */ -#define RTI_SETINTENA_ -/* RTI Clear Interrupt Enable Register */ -#define RTI_CLEARINTENA_ -/* RTI Interrupt Flag Register */ -#define RTI_INTFLAG_ + +#define RTI_COMPCTRL_COMPSEL0 (1 << 0) /* Bit 0: Compare select 0 */ +#define RTI_COMPCTRL_COMPSEL1 (1 << 4) /* Bit 4: Compare select 1 */ +#define RTI_COMPCTRL_COMPSEL2 (1 << 8) /* Bit 8: Compare select 2 */ +#define RTI_COMPCTRL_COMPSEL3 (1 << 12) /* Bit 12: Compare select 3 */ + +/* RTI Free Running Counter 0/1 Register (32-bit counter value) */ +/* RTI Up Counter 0/1 Register (32-bit counter value) */ +/* RTI Compare Up Counter 0/1 Register (32-bit counter value) */ +/* RTI Capture Free Running Counter 0/1 Register (32-bit counter value) */ +/* RTI Capture Up Counter 0/1 Register (32-bit counter value) */ +/* RTI Compare 0/1/2/3 Register Section (32-bit counter value) */ +/* RTI Update Compare 0/1/2/3 Register (32-bit counter value) */ + +/* RTI Set Interrupt Enable Register, RTI Clear Interrupt Enable Register, and + * RTI Interrupt Flag Register + */ + +#define RTI_INT0 (1 << 0) /* Bit 0: Compare interrupt 0 */ +#define RTI_INT1 (1 << 1) /* Bit 1: Compare interrupt 1 */ +#define RTI_INT2 (1 << 2) /* Bit 2: Compare interrupt 2 */ +#define RTI_INT3 (1 << 3) /* Bit 3: Compare interrupt 3 */ +#define RTI_TBINT (1 << 16) /* Bit 16: Timebase interrupt */ +#define RTI_OVL0INT (1 << 17) /* Bit 17: Free running counter 0 overflow interrupt */ +#define RTI_OVL1INT (1 << 18) /* Bit 18: Free running counter 1 overflow interrupt */ +#define RTI_ALLINTS 0x0007000f + /* Digital Watchdog Control Register */ #define RTI_DWDCTRL_ /* Digital Watchdog Preload Register */ diff --git a/arch/arm/src/tms570/tms570_clockconfig.c b/arch/arm/src/tms570/tms570_clockconfig.c index 8408f08579..a92b2b60b8 100644 --- a/arch/arm/src/tms570/tms570_clockconfig.c +++ b/arch/arm/src/tms570/tms570_clockconfig.c @@ -61,6 +61,50 @@ #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef BOARD_VCLK_DIVIDER +# error BOARD_VCLK_DIVIDER is not defined +#endif + +#if BOARD_VCLK_DIVIDER == 1 +# define SYS_CLKCNTL_VCLKR SYS_CLKCNTL_VCLKR_DIV1 +#elif BOARD_VCLK_DIVIDER == 2 +# define SYS_CLKCNTL_VCLKR SYS_CLKCNTL_VCLKR_DIV2 +#else +# error Invalid value for BOARD_VCLK_DIVIDER +#endif + +#ifndef BOARD_VCLK2_DIVIDER +# error BOARD_VCLK2_DIVIDER is not defined +#endif + +#if BOARD_VCLK2_DIVIDER == 1 +# define SYS_CLKCNTL_VCLKR2 SYS_CLKCNTL_VCLKR2_DIV1 +#elif BOARD_VCLK2_DIVIDER == 2 +# define SYS_CLKCNTL_VCLKR2 SYS_CLKCNTL_VCLKR_DIV2 +#else +# error Invalid value for SYS_CLKCNTL_VCLKR2_DIV2 +#endif + +#ifndef BOARD_RTICLK_DIVIDER +# error BOARD_RTICLK_DIVIDER is not defined +#endif + +#if BOARD_RTICLK_DIVIDER == 1 +# define SYS_RCLKSRC_RTI1DIV SYS_RCLKSRC_RTI1DIV_DIV1 +#elif BOARD_RTICLK_DIVIDER == 2 +# define SYS_RCLKSRC_RTI1DIV SYS_RCLKSRC_RTI1DIV_DIV2 +#elif BOARD_RTICLK_DIVIDER == 4 +# define SYS_RCLKSRC_RTI1DIV SYS_RCLKSRC_RTI1DIV_DIV4 +#elif BOARD_RTICLK_DIVIDER == 78 +# define SYS_RCLKSRC_RTI1DIV SYS_RCLKSRC_RTI1DIV_DIV8 +#else +# error Invalid value for SYS_CLKCNTL_VCLKR2_DIV2 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -434,12 +478,12 @@ static void tms570_clocksrc_configure(void) regval = getreg32(TMS570_SYS_CLKCNTL); regval &= ~(SYS_CLKCNTL_VCLKR2_MASK | SYS_CLKCNTL_VCLKR_MASK); - regval |= SYS_CLKCNTL_VCLKR2_DIV1 | SYS_CLKCNTL_VCLKR_DIV1; + regval |= SYS_CLKCNTL_VCLKR2 | SYS_CLKCNTL_VCLKR; putreg32(regval, TMS570_SYS_CLKCNTL); /* Setup RTICLK1 and RTICLK2 clocks */ - regval = SYS_RCLKSRC_RTI1SRC_VCLK | SYS_RCLKSRC_RTI1DIV_DIV2; + regval = SYS_RCLKSRC_RTI1SRC_VCLK | SYS_RCLKSRC_RTI1DIV; putreg32(regval, TMS570_SYS_RCLKSRC); /* Setup asynchronous peripheral clock sources for AVCLK1 */ diff --git a/arch/arm/src/tms570/tms570_irq.c b/arch/arm/src/tms570/tms570_irq.c index 24af3895c6..38906ddf52 100644 --- a/arch/arm/src/tms570/tms570_irq.c +++ b/arch/arm/src/tms570/tms570_irq.c @@ -137,6 +137,10 @@ void up_irqinitialize(void) putreg32((uint32_t)tms570_error_handler, TMS570_VIM_FBPARERR); + /* Assign all interrupt requests to the VIM channel of the same value. + * NOTE: Nothing need be done. That is the power-on default mapping. + */ + /* Assign all channels to IRQs */ putreg32(0, TMS570_VIM_FIRQPR0); @@ -184,27 +188,6 @@ void up_irqinitialize(void) #endif } -/**************************************************************************** - * Name: tms570_vim_channel - * - * Description: - * Allocate a VIM channel and assign it to the 'request'. - * - * Input Parameters: - * request - The interrupt request to be mapped to a channel - * - * Returned Value: - * One sucess, the allocated channel number is returned. A negated errno - * value is returned on any failure. - * - ****************************************************************************/ - -int tms570_vim_channel(int request) -{ -#warning Missing logic - return -ENOSYS; -} - /**************************************************************************** * Name: arm_decodeirq * diff --git a/arch/arm/src/tms570/tms570_irq.h b/arch/arm/src/tms570/tms570_irq.h index fd899e2a24..1d4114bec5 100644 --- a/arch/arm/src/tms570/tms570_irq.h +++ b/arch/arm/src/tms570/tms570_irq.h @@ -61,23 +61,6 @@ extern "C" * Public Function Prototypes ****************************************************************************/ -/**************************************************************************** - * Name: tms570_vim_channel - * - * Description: - * Allocate a VIM channel and assign it to the 'request'. - * - * Input Parameters: - * request - The interrupt request to be mapped to a channel - * - * Returned Value: - * One sucess, the allocated channel number is returned. A negated errno - * value is returned on any failure. - * - ****************************************************************************/ - -int tms570_vim_channel(int request); - /**************************************************************************** * Name: up_enable_fiq * diff --git a/arch/arm/src/tms570/tms570_timerisr.c b/arch/arm/src/tms570/tms570_timerisr.c index bd3553b1e9..4744ccbdb8 100644 --- a/arch/arm/src/tms570/tms570_timerisr.c +++ b/arch/arm/src/tms570/tms570_timerisr.c @@ -39,10 +39,160 @@ #include +#include + +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip/tms570_rti.h" + +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* The input clock to the RTI is the RTICLK. The RTI source is always VCLK + * which may be divided down by 2. The correct RTICLK frequency must be + * provided by board.h file as BOARD_RTICLK_FREQUENCY. + */ + +#ifndef BOARD_RTICLK_FREQUENCY +# error BOARD_RTICLK_FREQUENCY not defined +#endif + +/* Timing Calculations: + * + * FRC0CLK = RTICLK / (CPUC0 + 1) Hz + * Tcount = 1 / FRC0CLK Seconds + * = 1,000,000 / FRC0CLK Microseconds + * CMP0 = Period / Tcount + * = CONFIG_USEC_PER_TICK * FRC0CLK / 1,000,000 + * = CONFIG_USEC_PER_TICK * RTICLK / (CPUC0 + 1) / 1,000,000 + * + * For Example: + * VCLK = 80,000,000 Hz + * RTICLK = VCLK / 2 Hz + * = 40,000,000 Hz + * CPUC0 = 39 + * FR0CLK = 1,000,000 Hz + * Tcount = 1 Microsecond + * CONFIG_USEC_PER_TICK = 10,000 Microseconds + * CMP0 = 10,000 * 40,000,000 / 40 / 1,000,000 + * = 10, 000 = CONFIG_USEC_PER_TICK + */ + +#if BOARD_RTICLK_FREQUENCY > 10000000 + /* Use FR0CLK = 1MHz with CPUC0 at least 9 */ + +# define RTI_FRC0CLK (1000000) +#elif BOARD_RTICLK_FREQUENCY > 5000000 + /* Use FR0CLK = 500KHz with CPUC0 at least 9 */ + +# define RTI_FRC0CLK (500000) +#elif BOARD_RTICLK_FREQUENCY > 1000000 + /* Use FR0CLK = 100KHz with CPUC0 at least 9 */ + +# define RTI_FRC0CLK (100000) +#else +# error No logic for this value of RTICLK +#endif + +/* CPUC0 = RTICLK / FRC0CLK - 1 + * + * NOTES: + * - The following calculation performs rounding. + */ + +#define RTI_CPUC0 (((BOARD_RTICLK_FREQUENCY + RTI_FRC0CLK / 2) / RTI_FRC0CLK) - 1) + +/* CMP0 = CONFIG_USEC_PER_TICK * FRC0CLK / 1,000,000 + * + * NOTES: + * - The following calculation performs rounding. + * - The following calculation avoids integer overflow by depending on + * FRCLK being a multiple of 100,000 + */ + +#define RTI_CMP0 ((CONFIG_USEC_PER_TICK * (RTI_FRC0CLK / 100000) + 50) / 100) /**************************************************************************** * Public Functions ****************************************************************************/ + +/**************************************************************************** + * Name: up_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +int up_timerisr(int irq, uint32_t *regs) +{ + /* Cleear the RTI Compare 0 interrupts */ + + putreg32(RTI_INT0, TMS570_RTI_INTFLAG); + + /* Process timer interrupt */ + + sched_process_timer(); + return 0; +} + +/**************************************************************************** + * Name: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize the timer + * interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + /* Disable all RTI interrupts */ + + up_disable_irq(TMS570_REQ_RTICMP0); + putreg32(RTI_ALLINTS, TMS570_RTI_CLEARINTENA); + + /* Configure RTICOMP0 register and the RTIUDCP0 Register to initialize with + * the calculated compare value. + */ + + putreg32(RTI_CMP0, TMS570_RTI_COMP0); + putreg32(RTI_CMP0, TMS570_RTI_UDCP0); + + /* Configure the FRC0CLK clock by setting the RTICPUC0 register to the + * calculated value. + */ + + putreg32(RTI_CMP0, TMS570_RTI_CPUC0); + + /* Initialize the free-running counter and the RTI up-counter */ + + putreg32(0, TMS570_RTI_FRC0); + putreg32(0, TMS570_RTI_UC0); + + /* Clear any pending interrupts */ + + putreg32(RTI_ALLINTS, TMS570_RTI_COMP0); + + /* Enable the RTI Compare 0 interrupts (still disabled at the VIM) */ + + putreg32(RTI_INT0, TMS570_RTI_SETINTENA); + + /* Enable counter 0 */ + + putreg32(RTI_GCTRL_CNT0EN, TMS570_RTI_GCTRL); + + /* Attach the interrupt handler to the RTI Compare 0 interrupt */ + + DEBUGVERIFY(irq_attach(TMS570_REQ_RTICMP0, (xcpt_t)up_timerisr)); + + /* Enable RTI compare 0 interrupts at the VIM */ + + up_enable_irq(TMS570_REQ_RTICMP0); +}