Pumpkin, Inc.

Pumpkin User Forums

Unexpected OS_Delay() Behavior

If you can't make Salvo do what you want it to do, post it here.

Unexpected OS_Delay() Behavior

Postby samuel » Thu Jan 24, 2008 1:07 am

I am having a problem with what seems to be a problem with OS_Delay(). If I am in a task and do some work and then do an OS_Delay() for less time than I was in the task, then the task is made eligible without being delayed. Following is an example displaying what I'm talking about, the lowprio_task never gets to run and the variable increment_me never gets incremented. You can put a break before the OS_Delay() and add the OS variable OSlostTicks to the watch, if you change its value to something less than the OS_Delay() value, you will see that the lower priority task does get to run. Is this the desired behavior? I'm using Salvo 4.0.0, an MSP430F1612 and OSTimer() calls are at 100 Hz or every 10 ms.
samuel
 
Posts: 22
Joined: Sun Oct 08, 2006 11:00 pm

Re: Unexpected OS_Delay() Behavior

Postby samuel » Thu Jan 24, 2008 1:23 am

The code from my first post:

code:
#include "salvo.h"
#include "drivers/sys.h"

void highprio_task(void);
void lowprio_task(void);

static uquad increment_me;

void main(void)
{
sys_init();

OSInit();

OSCreateTask(highprio_task, OSTCBP(1), OSHIGHEST_PRIO);
OSCreateTask(lowprio_task, OSTCBP(2), OSLOWEST_PRIO);

while(1)
{
OSSched();
}
}

void highprio_task(void)
{
static uquad counter;

while(1)
{
for(counter = 0; counter < 0x000FFFFF; counter++) ;

OS_Delay(100);
}
}

void lowprio_task(void)
{
increment_me = 0;

while(1)
{
increment_me++;

OS_Yield();
}
}



[This message has been edited by aek (edited January 24, 2008).]

samuel
 
Posts: 22
Joined: Sun Oct 08, 2006 11:00 pm

Re: Unexpected OS_Delay() Behavior

Postby aek » Thu Jan 24, 2008 1:40 am

Your high-priority task is hogging the processor for so long that ticks are being lost (i.e. not processed inside OSSched(). So if your task fails to context-switch for 100 ticks, then OSlostTicks reaches 100, and a call to OS_Delay(100) is effectively a zero-length delay since 100 lost ticks have accumulated while you were failing to context-switch.

This is the correct and desirable behavior, as it minimizes the long-term errors in the timing system.

You can also use OS_DelayTS() and the associated functions if you like ...

IOW, you need to code so that you don't have hugely long periods during which you do not context-switch. While the system won't break, it will not behave as you expect.

If you do OS(Yield), then OS_Delay(100), that will "clear" OSlostTicks.

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: Unexpected OS_Delay() Behavior

Postby aek » Thu Jan 24, 2008 2:17 am

Hi Samuel.

Some further reflection on my part ... I assume the long delay is e.g. some SD card writes that you cannot control the duration of ... Since all of Salvo's context switches are unconditional (meaning that every OS_Xyz() is a combination of OS_Yield() and OSXyz()), an "extra" OS_Yield() to flush the lost ticks ought not be necessary ... therefore I think that even if you do hold off the scheduler for an inordinately long time, the effect of that ought to be only on the already-delayed tasks, and not any that will be delayed immediately after the inordinately long delay ends. So I need to look into this a bit deeper to understand it.

Do you have a minimal CW430 project that I can run here on CSK h/w to test with?

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: Unexpected OS_Delay() Behavior

Postby samuel » Thu Jan 24, 2008 3:31 am

I e-mailed you an example on your gmail account shortly after I posted this. I just e-mailed you a follow up as I well, I overlooked something in the first project.
samuel
 
Posts: 22
Joined: Sun Oct 08, 2006 11:00 pm

Re: Unexpected OS_Delay() Behavior

Postby aek » Thu Jan 24, 2008 4:13 am

I made an error in my last post -- all OS_Xyz()s are in the form of Xyz(), OS_Yield() (by internal design necessity), and therefore the behavior you see is exactly what the system is coded for.

Note that as I suggested, an OS_Yield() immediately prior to the OS_Delay(100) solves your problem. One might suggest a Salvo rule like "Any task body likely to prevent context switching for more than a single timer tick should immediately be followed by an OS_Yield()".

So you have a temporary / expedient solution.

I admit that from a user perspective, this isn't so pretty. It is trivial to add OSlostTicks to OSDelay()'s delay argument inside of OSDelay(), but that ends up causing non-obvious problems in terms of overloading the size of the delay argument -- e.g. with 8-bit delays you could easily overload a specified 8-bit delay, and the result would be .... unexpected. E.g with 8-bit delays, OS_Delay (160) when OSlostTicks has reached 120 gives a delay of 255, not 280. Sure, with 4-byte delays this is much less likely ... I have to think about the best way to resolve this. Personally, I think that the OS_Yield() insertion is the best / most elegant way, since inordinately long delays (whether they're avoidable or not) are a fundamental black thorn in cooperative task switching anyway.

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm


Return to Coding

Who is online

Users browsing this forum: No registered users and 5 guests

cron