WARP Project Forums - Wireless Open-Access Research Platform

You are not logged in.

#1 2011-Aug-18 05:24:18

Christian
Member
Registered: 2010-Feb-26
Posts: 124

Synchronize hardware & software

Hi,

I'm working on a MAC protocol that has several timers. When working with the timers, I came across a nasty behavior I was not able to track down efficiently. Maybe, you have an idea. A rough example in C-like pseudocode is the following:

Code:

unsigned int state = 0; // field that holds state
// check for active timers - existing timers from CSMAMAC disabled in warpmac.c
inline int checkTimers() {
return (warp_timer_isActive(TIMER1) || warp_timer_isActive(TIMER2) ||
		warp_timer_isActive(TIMER3) || warp_timer_isActive(TIMER4) ||
		warp_timer_isActive(TIMER5)) ? true : false;
}

...

void packetHandlerCallback(*packet) {
...
	if (certainpacket received) {
		warp_timer_pause(1);
		warp_timer_resetDone(1);
		state = 2; // change the state from state 1 to state 2 >> also remove associated timer
		if (checkTimers() == true) { // check if all timers have been cleared before
			printf("A timer is still running. That should not happen! Check implementation.");
			if (checkTimers() == true)
				printf("As expected. still true.");
			else
				printf("this should NEVER happen.");
		}
	}
}

After having received a certain packet, the state of the node should change. While transiting to another state, the node should check, if old timers are still pending. All timers should be cleared when changing the state. After removing the one particular timer that was still active in that state and after changing the state value, I check for active timers. The function returns true, a printout happens. Then, sometimes (often) the second check inside fails. It seems, the software calls are faster than the hardware calls (due to different clocking speeds I assume). Is there a "nice" way to synchronize hardware and software w/o having to include usleeps everywhere?!

Offline

 

#2 2011-Aug-18 11:31:12

murphpo
Administrator
From: Mango Communications
Registered: 2006-Jul-03
Posts: 5159

Re: Synchronize hardware & software

A few thoughts:

-checkTimers() is polling timers 1-5, returning true if any are active. But packetHandlerCallback is only resetting timer 1, then calling checkTimers(). Is it possible timers 2-5 are still running?

-The first printf ("A timer is...") will take a *long* time, almost 10msec (71 characters * 8-bits/character * 1/57600 bps). This is probably long enough for some timers to expire in between calls to checkTimers().

Offline

 

#3 2011-Aug-19 11:42:18

Christian
Member
Registered: 2010-Feb-26
Posts: 124

Re: Synchronize hardware & software

other timers are not active. the printf was just an example, I also tested it with counting up a variable and then printing it out much later, or by setting a value on the hex display.

a question that comes to my mind is: how to stop and delete running timers? I think, for the first timer it should be:

Code:

warp_timer_pause(1);
warp_timer_resetDone(1);

If so, do I need to delay software code that is later on polling the timer, as in:

Code:

warp_timer_pause(1);
warp_timer_resetDone(1);
// usleep(5) necessary here?
state = 2;
if (checkTimers() == true) warpmac_leftHex(0xE);

I think so because doing sth that takes more time after the warpmac_leftHex() call, then (within the same function call! no other code segment manipulated the resetDone mask) calling the checkTimers() function again results in the expected return value "false".

Last edited by Christian (2011-Aug-19 11:46:58)

Offline

 

#4 2011-Aug-21 14:05:05

murphpo
Administrator
From: Mango Communications
Registered: 2006-Jul-03
Posts: 5159

Re: Synchronize hardware & software

I think you may have uncovered a bug the timer logic/code.

Here's the Sysgen model for one timer (of eight in warp_timer.mdl):

http://i.imgur.com/pDgf1.png

The inputs [start, pause, mode, done_reset] are tied to register bits. Notice that the pause input is edge-sensitive. On a rising edge, pause clears the first SR latch and stops the main counter from advancing. On a falling edge, it re-asserts the latch and allows the counter to resume. The problem here is that if pause is asserted but not de-asserted, subsequent writes to the pause register will have no effect (since the pause bit is already high, there can't be another rising edge).

In warpmac.c, warpmac_clearTimer(id) asserts pause, then toggles reset_done. It does not de-assert pause. I think this is a problem, and might be the underlying cause of the behavior you've observed.

Another subtlety- if you pause/reset_done/resume a timer, the output 'running' could be high, even though the output 'done' will never assert (at least until the timer gets started via the 'start' register again). This behavior is enforced by the top SR latch, that is asserted by 'start' and cleared by 'done_reset'. If that latch is cleared (i.e. 'done_reset' was asserted at some point after the last 'start'), 'done' won't assert.

A workaround for this behavior would be to set the timer's slotCount target to zero after pausing it. This would hold the first SR latch in reset (since the slotCount comparison would immediately be true), de-asserting the 'running'  output.

So to fully (and safely) clear a running timer:
1) warp_timer_pause(id) //Clears first SR latch, stops main counter
2) warp_timer_resetDone(id) //Clears top SR latch (and done SR latch)
3) warp_timer_setTimer(id, 0, 0) //Clears counter state; forces 'running' low
4) warp_timer_resume(id) //Clears pause register (won't assert first SR latch, since R overrides S)

At this point, the 'pause' register and the 'running' and 'done' outputs will all be low.

Then, at some point in the future, when you re-start the timer:
1) warp_timer_setTimer(id, yourSlotTime, yourSlotCount) //Sets timer count-to values
2) warp_timer_start(id) //Asserts first SR latch and top SR latch

This logic/code is obviously a prime candidate for a re-design in the next overhaul of the OFDM Reference Design.

Offline

 

#5 2013-Aug-29 06:15:51

Christian
Member
Registered: 2010-Feb-26
Posts: 124

Re: Synchronize hardware & software

Just as an addition and a note to others: The pollTimer function needs consideration: If timer1 and timer2 expire at almost the same time, the following (standard) handler routine processes both events within one run with a certain "priority" (implicitly set by timer ID).

Code:

inline void warpmac_pollTimer() {

	unsigned int timerStatus;
	timerStatus = warp_timer_getStatuses();

	//We check the status of each of the timers, and call necessary callbacks
	// The ifdef's below keep this funciton from wasiting time checking unused timers
	// You can enable polling timers invididually by modifying warpmac.h
#ifdef POLL_TIMER0
	if((timerStatus & TIMER0_MASK & TIMER_STATUS_DONE_MASK) != 0){
		warp_timer_resetDone(0);
		usr_timerCallback(0);
	}
#endif
#ifdef POLL_TIMER1
	if((timerStatus & TIMER1_MASK & TIMER_STATUS_DONE_MASK) != 0){
		warp_timer_resetDone(1);
		usr_timerCallback(1);
	}
#endif
//...

The status of expiry is retrieved once in the very beginning. If the handler of timer1 removes timer2, it might still be processed since the expiry status is not updated in the WARPMAC framework. It is not really a bug in the framework, but just has to be kept in mind when having timers whose expiry might be tightly coupled. Workarounds would be to allow one timer processing at most in the handler function (some "fairness" needed if timer deadlines are very short) or update the status variable after each usr_timerCallback return.

Offline

 

Board footer