PIT ISR prioity Timing

Discussion to talk about software related topics only.
Post Reply
Ridgeglider
Posts: 513
Joined: Sat Apr 26, 2008 7:14 am

PIT ISR prioity Timing

Post by Ridgeglider »

Here's a timing issue I'm trying to figure out. I have PIT timer1 running at a 0.01 sec interval triggering an ISR. The ISR increments two variables, one forever, the other from 0 to 99. When the 2nd variable is 99, I reset it to 0, and post a semaphore to a pending task called the ControlTask (which therefore runs 1X/sec). When ControlTask runs, it sets an output hi, does a OSTimeDly(1) to generate a 50mSec delay, then sets the output low. TICKS_PER_SECOND is set at the default of 20. As expected, I get a pulse every second, however, the pulsewidth varies a lot: from several microsecs at the shortest, to something less than the expected 50mSec. Have I mis-configured the prios for the PIT1 ISR? I'd like to ensure that ticks used in the ControlTask for variety of future purposes are not skewed somehow... Should I change the SR mask in the INTERRUPT macro (2200), or the IRQ level (2) or the IRQ priority (3) in the SetIntc() function? My understanding is that the SR mask digit "X" 2X00 must be the same as the IRQ "level" in SetIntc( IRQController, ISRFuctionAddr, vector, level, priority).

I've fooled with both the level (2, 3, or 4) and prio ( 3 or 7) variables, but don't seem to get much improvement. I also changed the OSTimeDly(1) in the Controltask to OSTimeDly(2). This produced time delays that were between 50 and 100 mSec, biut not the expected 100mSec. Looks like the last tick gets chopped off short?

Here's how the PIT1 is set up:

Code: Select all

//////VARIABLES: ===============================================================

	//The following variables are incremented by the PIT and used to sequence
	// when the tasks run.
	volatile DWORD PIT_CountsSincePwrOn = 0;	//++ every 10 msec = 1/100 sec).
	volatile unsigned int PIT_TicksSinceControlTaskRan = 0;
	

//////OS SEMAPHORES, MAILBOXES, Qs, or FIFOs ===================================
	OS_SEM ControlTaskSemaphore;

INTERRUPT( IRQ2TimeslicePIT_ISR, 0x2200)	//SR mask= x2?00 where, here, ? = 2.
	WORD tmp = sim.pit[1].pcsr;			// Get PIT1 Control & Status Register
										// data
	// Clear PIT1 - Refer to table 23-3 for more information on what
	// bits are being cleared and set
	tmp &= 0xFF0F; // Bits 4-7 cleared
	tmp |= 0x0F; // Bits 0-3 set
	sim.pit[1].pcsr = tmp;

	PIT_CountsSincePwrOn++;				// Increment when an interrupt occurs
	PIT_TicksSinceControlTaskRan++;

	//	Now see if it's time to post the semaphores to trigger other tasks...
		if ( PIT_TicksSinceControlTaskRan >= (PIT_TICKS_IN_CONTROL_LOOP - 1) ) {
		PIT_TicksSinceControlTaskRan = 0 ;
		if ( PIT_ControlTaskEnabled ) {
			ControlTaskSemPostRetVal = OSSemPost( &ControlTaskSemaphore) ;
		}
	}
}

///////////////////////////////////////////////////////////////////////
// SetUpPITR - PIT setup function. See chapter 23 of the 5235 reference
// manual for details
//


void SetUpPITR( int pitr_ch, WORD clock_interval, BYTE pcsr_pre	/* See
table 23-3 in the reference manual for bits 8-11 */ )
{
	WORD tmp;
	if ( ( pitr_ch < 1 ) || ( pitr_ch > 3 ) ) {
		iprintf( "*** ERROR - PIT channel out of range ***\r\n" );
		return;
	}

	SetIntc( 0,								// Interrupt controller 0
			( long) &IRQ2TimeslicePIT_ISR,	// Addr of function to install in
											//		the IRQ vector table
			36 + pitr_ch, 					// The IRQ vector number
			2,			 					// The IRQ level ( Must be >= to
											//    the ? in SRmask or the
											//    INTERRUPT macro above.
			3 );							// The IRQ priority
	//
	// Configure the PIT for the specified time values
	//
	sim.pit[pitr_ch].pmr = clock_interval; 	// Set PIT modulus value
	tmp = pcsr_pre;
	tmp = ( tmp << 8 ) | 0x0F;
	sim.pit[pitr_ch].pcsr = tmp; 			// Set system clock divisor to 16 &
											// set bits [3:0] in PCSR
}

void ControlTask (void *pdata) {
	iprintf("     Starting ControlTask...\r\n");


	while (1) {
		OSSemPend ( &ControlTaskSemaphore, WaitForever ); //Pend on PIT
		iprintf("Control\r\n");
		ControlTaskActiveHiOutputPin	= 1;	// Task active: pin hi.
		OSTimeDly(1);
		ControlTaskActiveHiOutputPin	= 0; 	//Task not active: pin lo.
	}
 }
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: PIT ISR prioity Timing

Post by pbreed »

Your problem is in the OSTimeDly

The way OSTimeDly works is that the time delay can be anything from n-1 to n

It works by setting up a time delay counter and decrementing every tick.
when it gets to zero the timer is released.

Since your pit interrupt is asynchronous to the Timer tick, then your delay gets called at random times in
the 0->1 time tick interval.

Since you already have the pit and semaphore setup just make a status variable and hit the semaphore again
0.2 sec (or whatever pulse period you want) later.

Paul
greengene
Posts: 164
Joined: Wed May 14, 2008 11:20 am
Location: Lakeside, CA

Re: PIT ISR prioity Timing

Post by greengene »

the only problem is the assumed performance of the OSTimeDly() function.
what OSTimeDly does is delays the count of ticks specified NOT the time of
count times 50 ms.

the ticks come every 50 ms. however, when you make the call,
the next tick could be "microsecs at the shortest, to something less than
the expected 50mSec".

so if you need 50 ms, better add another semaphore to turn it off.
Post Reply