View Single Post
  #1   Spotlight this post!  
Unread 22-01-2008, 22:42
pogenwurst pogenwurst is offline
Ubuntu User
AKA: Brian
FRC #2007 (Robots of the Round Table)
Team Role: Leadership
 
Join Date: Jan 2008
Rookie Year: 2007
Location: Duluth, GA
Posts: 78
pogenwurst is on a distinguished road
Send a message via AIM to pogenwurst
Angry Second clock/timer causes red light of death

I'm working with Kevin Watson's 2008 codebase.

I've been fiddling with a clock (based on IFI's whitepaper on the subject) for far too much time I care to remember. I waded through many mistakes on my part along the way (as I am a relative neophyte in programming) but I'm finally stumped.

Here's my relevant code:

Code:
/*******************************************************************************
*
*	FUNCTION:		Initialize_Timer_1()
*
*	PURPOSE:		Initializes the timer 1 hardware.
*
*	CALLED FROM:	teleop.c/Initialization()
*
*	PARAMETERS:		None
*
*	RETURNS:		Nothing
*
*	COMMENTS:
*
*******************************************************************************/
#ifdef ENABLE_TIMER_1_ISR
void Initialize_Timer_1(void)  
{
	TMR1L = 0xED;			// least significant 8-bits of the timer 1 register (this is readable and writable)
	TMR1H = 0x85;			// most significant 8-bits of the timer 1 register (this is readable and writable)
							//
	T1CONbits.T1CKPS0 = 1;	// T1CSP1 T1CSP0
	T1CONbits.T1CKPS1 = 1;	//   0      0		1:1 prescaler (clock=10MHz/each tick=100ns)
							//   0      1		1:2 prescaler (clock=5MHz/each tick=200ns)
							//   1      0		1:4 prescaler (clock=2.5MHz/each tick=400ns)
							//   1      1		1:8 prescaler (clock=1.25MHz/each tick=800ns)
							//
	T1CONbits.T1OSCEN = 0;	// 0: timer 1 oscillator disabled (leave at 0 to allow the use of an external clock)
							// 1: timer 1 oscillator enabled (can't be used because of hardware constraints)
							//
	T1CONbits.TMR1CS = 0;	// 0: use the internal clock
							// 1: use an external clock on RC0/T1OSO/T13CLK (rc_dig_in14 on robot controller)
							//
	T1CONbits.RD16 = 1;		// 0: timer 1 register operations are done in two 8-bit accesses
							// 1: timer 1 register operations are done in one 16-bit access
							//    In this mode, reading TMR1L will latch a copy of TMR1H into a buffer
							//    mapped to the TMR1H memory address. Conversely, a write to the buffer
							//    followed by a write to the TMR1L register will update the entire 16-bit
							//    timer at once. This solves the problem where the timer may overflow
							//    between two 8-bit accesses. Here's an example of how to do a 16-bit read:
							//
							//    unsigned char Temp_Buf; // 8-bit temporary buffer
							//    unsigned int Timer_Snapshot; // 16-bit variable
							//
							//    Temp_Buf = TMR1L; // TMR1L must be read before TMR1H
							//    Timer_Snapshot = TMR1H;
		 					//    Timer_Snapshot <<= 8; // move TMR1H data to the upper half of the variable
							//    Timer_Snapshot += Temp_Buf; // we now have all sixteen bits  
							// 
	IPR1bits.TMR1IP = 0;	// 0: timer 1 overflow interrupt is low priority (leave at 0 on IFI controllers)
							// 1: timer 1 overflow interrupt is high priority
							//
	PIR1bits.TMR1IF = 0;	// 0: timer 1 overflow hasn't happened (set to 0 before enabling the interrupt)
							// 1: timer 1 overflow has happened
							//
							// Brian is stupid and doesn't read in-code documentation
							//
	PIE1bits.TMR1IE = 1;	// 0: disable timer 1 interrupt on overflow (i.e., a transition from FFFF->0)
							// 1: enable timer 1 interrupt on overflow (i.e., a transition from FFFF->0)
							//	
	T1CONbits.TMR1ON = 1;	// 0: timer 1 is disabled
							// 1: timer 1 is enabled (running)
}
#endif

/*******************************************************************************
*
*	FUNCTION:		Timer_1_ISR()
*
*	PURPOSE:		If enabled, the timer 1 interrupt handler is called when
*					the TMR1 register overflows	and rolls over to zero.
*
*	CALLED FROM:	ifi_frc.c/Interrupt_Handler_Low()
*
*	PARAMETERS:		None
*
*	RETURNS:		Nothing
*
*	COMMENTS:
*
*******************************************************************************/
#ifdef ENABLE_TIMER_1_ISR
#pragma tmpdata low_isr_tmpdata

// counter variables
volatile unsigned	char	timerTickCount = 0;
volatile unsigned	int		timerSecondCount = 0;

void Timer_1_ISR(void)
{
	// this function will be called when a timer 1 interrupt occurs
	
	if(timerTickCount > 39) // 40 * 25 ms = 1 sec
	{
		// reset tick count
		timerTickCount = 0;
		
		// increment second counter
		++timerSecondCount;
	}
	else
	{
		++timerTickCount;
	}
}
#pragma tmpdata
#endif
in timers.c

Code:
	// if Brian has stopped being an idiot (unlikely) this will move us for 5 seconds
	if(timerSecondCount < 6)
		pwm13 = pwm15 = 255;
	else
		pwm13 = pwm15 = 127;
in teleop.c within the Teleop() function

Code:
extern timerSecondCount;
in teleop.h

My code has been compiling fine (after much trial and tribulation ), but as indicated in the topic subject, it results in a red program state light.

When I disable the timer 1 overflow interrupt (PIE1bits.TMR1IE), the program state light is green (but as my count-incrementing code is within an ISR, doing so renders my code useless). Strangely, however, if I re-enable the interrupt but comment out the contents of the ISR function, I once again see red.

Can anyone point me in the right direction? Thanks.