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