This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem reading TCRR for GPT6 on the IVA2 of the OMAP2430

I am trying to read/write to the GPT6 TCRR from the IVA2, however the contents of the register never change. I've properly mapped the IO in a DSP gel file along with setting up the MMU for the range of addresses I am accessing. I can step through my initialization call (TimeSync_Initialize) and see the TLDR get set with the correct period. However, when I write to the trigger register the TCRR does not change ( remains set to 0). I am able to receive timer overflow interrupts at the correct rate- so I assume that the count register has to be incrementing properly. 

I'm pretty much lost right now so any help would be greatly appreciated. Here is my setup code.

/*****************************************************************************
 *  Table 16-12. GPT6 Register Summary (see TRM)
 * .-------------.----.---------------------.--------------.----------------.
 * |Register Name|Type|Register Width (Bits)|Address Offset|Physical Address|
 * '-------------'----'---------------------'--------------'----------------'
 * |         TIDR|   R|                   32|         0x000|     0x4807 E000|
 * |    TIOCP_CFG|  RW|                   32|         0x010|     0x4807 E010|
 * |       TISTAT|   R|                   32|         0x014|     0x4807 E014|
 * |         TISR|  RW|                   32|         0x018|     0x4807 E018|
 * |         TIER|  RW|                   32|         0x01C|     0x4807 E01C|
 * |         TWER|  RW|                   32|         0x020|     0x4807 E020|
 * |         TCLR|  RW|                   32|         0x024|     0x4807 E024|
 * |         TCRR|  RW|                   32|         0x028|     0x4807 E028|
 * |         TLDR|  RW|                   32|         0x02C|     0x4807 E02C|
 * |         TTGR|  RW|                   32|         0x030|     0x4807 E030|
 * |         TWPS|   R|                   32|         0x034|     0x4807 E034|
 * |         TMAR|  RW|                   32|         0x038|     0x4807 E038|
 * |        TCAR1|   R|                   32|         0x03C|     0x4807 E03C|
 * |        TSICR|  RW|                   32|         0x040|     0x4807 E040|
 * |        TCAR2|   R|                   32|         0x044|     0x4807 E044|
 * '-------------'----'---------------------'--------------'----------------'
 *
 *****************************************************************************/
#pragma DATA_ALIGN( GPT_config_reg, 4)
volatile unsigned int *GPT_config_reg            = (unsigned int *)0x4807E010;
#pragma DATA_ALIGN( GPT_status_reg, 4)
volatile unsigned int *GPT_status_reg            = (unsigned int *)0x4807E014;
#pragma DATA_ALIGN( GPT_pending_flag_reg, 4)
volatile unsigned int *GPT_pending_flag_reg      = (unsigned int *)0x4807E018;
#pragma DATA_ALIGN( GPT_interrupt_control_reg, 4)
volatile unsigned int *GPT_interrupt_control_reg = (unsigned int *)0x4807E01C;
#pragma DATA_ALIGN( GPT_wakeup_control_reg, 4)
volatile unsigned int *GPT_wakeup_control_reg    = (unsigned int *)0x4807E020;
#pragma DATA_ALIGN( GPT_control_reg, 4)
volatile unsigned int *GPT_control_reg           = (unsigned int *)0x4807E024;

/*****************************************************************************
 * Table 16-26. GP Timer Counter Register (TCRR)
 *****************************************************************************/
#pragma DATA_ALIGN( GPT_counter_reg, 4)
volatile unsigned int  *GPT_counter_reg         = (unsigned int *)0x4807E028;
/*****************************************************************************
 * Table 16-27. GP Timer Load Register (GPTn.TLDR)
 *****************************************************************************/
#pragma DATA_ALIGN( GPT_load_reg, 4)
volatile unsigned int   *GPT_load_reg            = (unsigned int *)0x4807E02C;
/*****************************************************************************
 * Table 16-28. GP Timer Trigger Register (TTGR)
 *****************************************************************************/
#pragma DATA_ALIGN( GPT_load_trigger_reg, 4)
volatile unsigned int   *GPT_load_trigger_reg    = (unsigned int *)0x4807E030;
/*****************************************************************************
 * Table 14-341. WUGEN Register Summary
 *****************************************************************************/
#pragma DATA_ALIGN( WUGEN_MEVTCLR0_reg, 4)
volatile unsigned int *WUGEN_MEVTCLR0_reg        = (unsigned int *)0x01C21070;
/*****************************************************************************
 * Table 14-341. WUGEN Register Summary
 *****************************************************************************/
#pragma DATA_ALIGN( WUGEN_MEVTSET0_reg, 4)
volatile unsigned int *WUGEN_MEVTSET0_reg        = (unsigned int *)0x01C21080;
/*****************************************************************************
 * Table 4-98.CM_FCLKEN1_CORE Register Summary
 *****************************************************************************/
#pragma DATA_ALIGN( CM_FCLKEN1_CORE, 4)
volatile unsigned int *CM_FCLKEN1_CORE           = (unsigned int *)0x49006200;
/*****************************************************************************
 * Table 4-100. CM_ICLKEN1_CORE Register Summary
 *****************************************************************************/
#pragma DATA_ALIGN( CM_ICLKEN1_CORE, 4)
volatile unsigned int *CM_ICLKEN1_CORE           = (unsigned int *)0x49006210;
/*****************************************************************************
 * Table 4-113. CM_CLKSEL2_CORE Register Summary
 *****************************************************************************/
#pragma DATA_ALIGN( CM_CLKSEL2_CORE, 4)
volatile unsigned int *CM_CLKSEL2_CORE           = (unsigned int *)0x49006244;
/*****************************************************************************
 * Table 4-104. CM_IDLEST1_CORE Register Summary
 *****************************************************************************/
#pragma DATA_ALIGN( CM_IDLEST1_CORE, 4)
volatile unsigned int *CM_IDLEST1_CORE           = (unsigned int *)0x49006220;

time_t_DSP gt_sysTime; //Elapsed time since init

/*
   Disable interrupts specified in mask and return old mask
*/
extern unsigned int C64_disableIER( unsigned int mask );

/*
   Enable interrupts specified by mask
*/
extern void C64_enableIER( unsigned int mask );

/*
   Clear pending interrupts specified by mask
*/
extern void C64_clearIFR( unsigned int mask );

/*****************************************************************************
 * Function:       GPT6_IRQ
 *
 * Description:    This is the General Purpose Timer 6 Interrupt Routine. This
 *                 function is mapped to HWI_INT4 in the bios.
 * Arguments:      None.
 *
 * Returns:        None.
 *****************************************************************************/
//#pragma CODE_SECTION( NameInSect(GPT6_IRQ) "fastfastcode" );
void GPT6_IRQ( void)
{

   gt_sysTime.nanoseconds += TIMER_PERIOD_IN_NSEC;

   if (gt_sysTime.nanoseconds >= 1000000000)
   {
      gt_sysTime.seconds++;
      gt_sysTime.nanoseconds = gt_sysTime.nanoseconds - 1000000000;

   }/*End if (gt_sysTime.nanoseconds >= 1000000000)*/

   /**************************************************************************
    * Clear the pending overflow bit per section 16.2.4.7 Timer Interrupt
    * Control of the TRM.
    **************************************************************************/
   (*GPT_pending_flag_reg) = 0x00000002;

} //end GPT6_IRQ

/*****************************************************************************
 * Function:       sysTimeReset
 *
 * Description:    This function set the current time to 0.
 *
 * Arguments:      None.
 *
 * Returns:        None.
 *****************************************************************************/
void sysTimeReset( void)
{
   gt_sysTime.seconds     = 0;
   gt_sysTime.nanoseconds = 0;

}/*End sysTimeReset*/

/******************************************************************************
 * Function:    SysTimeNow
 *
 * Description: This function reads the GPT6 counter register and returns the
 *              time in nanoseconds.
 *
 * Arguments:   None.
 *
 * Returns:     A time_t_DSP value representing current system time within the
 *              GPT6 interrupt period.
 ******************************************************************************/
static inline void getCurrentTime( time_t_DSP *pt_currTime)
{
   pt_currTime->nanoseconds = TICKS_TO_NANOSECS( *GPT_counter_reg);
   /*See if the timer interrupt fired while we were in this loop*/
   if( getIntStatus( INT4) == True)
   {
      /***********************************************************************
       * Set the time to the period length
       ***********************************************************************/
      pt_currTime->nanoseconds = TIMER_PERIOD_IN_NSEC;
   }/*End if( getIntStatus( INT4) == True)*/

}/*End getCurrentTime*/
 
/******************************************************************************
 * Function:    SysTimeNow
 *
 * Description: This function calculates the current system time in seconds
 *              and nanoseconds.
 *
 * Arguments:   None.
 *
 * Returns:     A time_t_DSP value representing current system time.
 *****************************************************************************/
#pragma CODE_SECTION( NameInSect(sysTimeNow) "fastfastcode" );
time_t_DSP sysTimeNow( void)
{
   time_t_DSP result;
  
   intDisable( INT4);
  
   getCurrentTime( &result );

   /**************************************************************************
    * Add the current time within the timer period to the overall running
    * system time.
    **************************************************************************/
   result.seconds     += gt_sysTime.seconds;
   result.nanoseconds += gt_sysTime.nanoseconds;
  
   /**************************************************************************
    * Check to see if we crossed the 1 second boundary
    **************************************************************************/
   if (result.nanoseconds >= 1000000000)
   {
      result.seconds++;
      result.nanoseconds = result.nanoseconds - 1000000000;

   }/*End if (result.nanoseconds >= 1e9)*/
   
   intEnable( INT4);

   return result;

}/*End sysTimeNow*/

/*****************************************************************************
 * Function:       TimeSync_Initialize
 *
 * Description:    This function initializes all variables used in TimeSync.
 *
 * Arguments:      None.
 *
 * Returns:        None.
 *****************************************************************************/
void TimeSync_Initialize()
{
   static uint32 i_waitCount = 0;

   /**************************************************************************
    * Ensure all interrupts are disabled during initialization
    **************************************************************************/
   globalIntDisable();
   intDisable( INT15);
  
   /**************************************************************************
    * Make sure GPT6 is using the system clock (IVA2_SYSTEM_CLOCK_IN_HZ)
    **************************************************************************/
   (*CM_CLKSEL2_CORE) |= BIT_10;

   /**************************************************************************
    * Enable the functional clock
    **************************************************************************/
   (*CM_FCLKEN1_CORE) |= BIT_8;

   /**************************************************************************
    * Enable the interface clock
    **************************************************************************/
   (*CM_ICLKEN1_CORE) |= BIT_8;

   /**************************************************************************
    * Wait for the timer to be ready to use
    **************************************************************************/
   while( ((*CM_IDLEST1_CORE) & BIT_8) == 0)
   {
   }

   sysTimeReset();
  
   /**************************************************************************
    * Run GPT through a software reset...see note (1) under Table 16-20.
    * GP Timer L4 Interface Configuration Register (TIOCP_CFG)
    **************************************************************************/
   (*GPT_config_reg) = 0x00000002;
  
   i_waitCount = 0;
  
   /**************************************************************************
    * Wait here for reset completed on GPT
    **************************************************************************/
   while ( (*GPT_status_reg) != 1 )
   {

      i_waitCount++;
   }
  
   /**************************************************************************
    * The timer is setup to generate an interrupt on an overflow - which
    * occures when the timers count value reaches 0xFFFFFFFF. Therefore, we
    * must reference all our period times to the end of the counter register
    * not the beginning.
    **************************************************************************/
   (*GPT_load_reg) = 0xFFFFFFFF - TIMER_PERIOD_IN_TICKS;
  
   /**************************************************************************
    * Initialize the count register to (*GPT_load_reg).
    **************************************************************************/
   (*GPT_load_trigger_reg) = 0;

   /**************************************************************************
    * Reload the counter register with the correct time on every overflow
    * event.
    **************************************************************************/
   (*GPT_control_reg) |= BIT_1;

   /**************************************************************************
    * Make sure pending interrupts are all reset
    **************************************************************************/
   (*GPT_interrupt_control_reg) = 0x00000000;
   (*GPT_pending_flag_reg)      = 0x00000007;

   /**************************************************************************
    * Setup timer interrupt on period overflow
    **************************************************************************/
   (*GPT_interrupt_control_reg) |= BIT_1;

   /**************************************************************************
    * Mask Bit GPT6 (IVA2_IRQ[7]) in WUGEN module by writing a '1' to bit
    * location 7 of the WUGEN Event Set register. This maps to EVT 52 see
    * table 14-4 Interrupt mapping and figure 14-24 IVA2 Interrupt flow for
    * further details.
    **************************************************************************/
   (*WUGEN_MEVTSET0_reg) = BIT_7;

   /**************************************************************************
    * Clear Mask Bit GPT6 (IVA2_IRQ[7]) in WUGEN function
    **************************************************************************/
   (*WUGEN_MEVTCLR0_reg) = BIT_7;

   /**************************************************************************
    * enable the interrupt.
    **************************************************************************/
   intEnable( INT15);
   globalIntEnable();

   /**************************************************************************
    * Start the timer
    **************************************************************************/
   (*GPT_control_reg) |= BIT_0;

}/*End TimeSync_Initialize*/