TMS570: Add system timer logic

This commit is contained in:
Gregory Nutt 2015-12-23 13:41:36 -06:00
parent fa36531fee
commit a76f2b853a
5 changed files with 236 additions and 85 deletions

View File

@ -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 */

View File

@ -61,6 +61,50 @@
#include <arch/board/board.h>
/****************************************************************************
* 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 */

View File

@ -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
*

View File

@ -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
*

View File

@ -39,10 +39,160 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/arch.h>
#include "up_internal.h"
#include "up_arch.h"
#include "chip/tms570_rti.h"
#include <arch/board/board.h>
/****************************************************************************
* 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);
}