Discussion:
[VxW] system clock interrupt
(too old to reply)
Joseph Hadzima
2003-07-09 16:46:55 UTC
Permalink
HI Yueshi:

There are several common methods used to do something
periodically.

1) // to do something and can tolorate +/- clk tick drift.
// taskDelay uses sysClk to monitor time.
myTask1()
{
for(;;)
{
taskDelay( NUM_SECONDS * sysClkRateGet() );
doSomething( doSomethingArg1 );
}
}

2)// to do something after N clk ticks and minimize drift
// also uses system clock to monitor time to call
WatchDog
doSomething()
{
myWDID = wdCreate();
mySemID = smeBCreate( SEM_Q_PRIORITY, SEM_EMPTY );
for(;;)
{
wdStart( myWDID, NUM_CLK_TICKS, semGive, mySemID );
semTake( mySemID, WAIT_FOREVER );
actuallyDoSomething()
}
}

3)
// to do something at a fast rate (i.e. > 500 Hz) .
// use Aux Clk so can set rate independent of sysClk rate
// CAUTION: doSomething() in this case is an ISR,
// and must comply with ISR design rules
// (no blocking calls, and no IO).
myTask3()
{
sysAuxClkRateSet( NUM_TICS_PER_SECOND );
sysAuxClkConnect( doSomething, doSomethingArg );
sysAuxClkEnable();
taskDelay( NUM_SECONDS * sysClkRateGet() );
sysAuxClkDisable();
}


those are the basics ... play with them to get a better
feel. BTW you can also use the wd timers to detect missed
dead-lines if you design yuor task to reload the timer
(call wdStart()) before the deadline occurs. If it does
occur then run code to handle the missed dead-line.

HTH and happy coding!
Hi,
I am using VxWorks 5.5 on PC Pentium III target. My
question is how
can I make use of the system clock to do something
regularly.
For example, the target computer will receive a command
from other
machine which indicates the start of such a function that
to read a
board every, say, 0.001 second.
So, what's the usual way to realize that on VxWorks, is
it relavent to
some routines in sysLib, for instance, sysAuxClkConnect()
etc.?
Also, if I wish to read the system clock, is that such a
function
availabe in VxWorks API library?
Thank you very much!
Sincerely
Yueshi
_______________________________________________
VxWorks Users Group mailing list
http://www-csg.lbl.gov/vxworks/
=====
HADZ.

Never be afraid to try something new. Remember, amateurs built the ark. Professionals built the Titanic.

(this Email sent using 100% recycled electrons)

__________________________________
Do you Yahoo!?
SBC Yahoo! DSL - Now only $29.95 per month!
http://sbc.yahoo.com
Chris Hann
2003-07-09 17:38:20 UTC
Permalink
Back in 1980 I used the sysAuxClock() on a 25MHz 68040 to run a 1ms
message timing loop, I checked it with a logic analyzer and it was
accurate to a few tens of microseconds. If you are doing something
relatively simple this is a better way than giving a semaphore and then
praying that the tasking systems lets you in.

The first thing we did to any vxWorks system was always to change the
clock to 100 or 200Hz so the system timings were in whole numbers of
milliseconds. The 60Hz system clock is an anachronism.

Chris
Hi,
I am using VxWorks 5.5 on PC Pentium III target. My question is how
can I make use of the system clock to do something regularly.
For example, the target computer will receive a command from other
machine which indicates the start of such a function that to read a
board every, say, 0.001 second.
So, what's the usual way to realize that on VxWorks, is it relavent
to
some routines in sysLib, for instance, sysAuxClkConnect() etc.?
Also, if I wish to read the system clock, is that such a function
availabe in VxWorks API library?
Thank you very much!
Sincerely
Yueshi
_______________________________________________
VxWorks Users Group mailing list
http://www-csg.lbl.gov/vxworks/
Chris Hann
2003-07-09 17:47:25 UTC
Permalink
Oops. 1990. In 1980 I was using a 1MHz 6502 in highschool :-\
Post by Chris Hann
Back in 1980 I used the sysAuxClock() on a 25MHz 68040 to run a 1ms
Keith Arner
2003-07-09 18:47:55 UTC
Permalink
Post by Joseph Hadzima
There are several common methods used to do something
periodically.
1) // to do something and can tolorate +/- clk tick drift.
// taskDelay uses sysClk to monitor time.
myTask1()
{
for(;;)
{
taskDelay( NUM_SECONDS * sysClkRateGet() );
doSomething( doSomethingArg1 );
}
}
2)// to do something after N clk ticks and minimize drift
// also uses system clock to monitor time to call
WatchDog
doSomething()
{
myWDID = wdCreate();
mySemID = smeBCreate( SEM_Q_PRIORITY, SEM_EMPTY );
for(;;)
{
wdStart( myWDID, NUM_CLK_TICKS, semGive, mySemID );
semTake( mySemID, WAIT_FOREVER );
actuallyDoSomething()
}
}
Your method #1 and method #2 will have *exactly* the same
behaviour/drift/jitter/etc. taskDelay() and wdStart() are running off of
the same clock source, and are using the same scheduling queue. Both #1
and #2 suffer from the potential to execute late if actuallyDoSomething()
takes longer than a clock tick to execute (but #2 needs to execute a bit
more code to accomplish this, so it is ever so slightly more subject to
this problem).

On the other hand, if you had coded it up as:

void myWdFunc(void) {
semGive(mySemID);
wdStart(myWDID, NUM_CLK_TICKS, myWdFunc, 0 );
}
doSomething() {
myWDID = wdCreate();
mySemID = semBCreate( SEM_Q_PRIORITY, SEM_EMPTY );
wdStart(myWDID, NUM_CLK_TICKS, myWdFunc, 0 );
for(;;)
{
semTake( mySemID, WAIT_FOREVER );
actuallyDoSomething()
}
}

...you would end up with a much more reliable periodic execution.
Basicly, you want to make the mechanism which determines your period to be
independant of the work you are accomplishing.

Keith
--
"One should not pursue goals that are easily achieved."
- Albert Einstein, 1915
John
2003-07-10 05:35:55 UTC
Permalink
Hello,
Post by Keith Arner
void myWdFunc(void) {
semGive(mySemID);
wdStart(myWDID, NUM_CLK_TICKS, myWdFunc, 0 );
I think I would have swapped those two lines too - for the same
reason. Restart the WD before you do anything else (including the
ever-so-fast semGive). In this case, since the function is executing
in interrupt context it will probably not make much difference, until
a higher priority interrupt comes in between the two calls.

Of course, even with the wdStart() first, there is still a chance of
another interrupt getting in there before the watchdog is restarted.
What you really need for periodic systems is a self-reloading timer...

HTH,
John...

=====
Contribute to the VxWorks Cookbook at:
http://www.bluedonkey.org/cgi-bin/twiki/bin/view/Books/WebHome
Keith Arner
2003-07-10 12:51:41 UTC
Permalink
Post by John
Post by Keith Arner
void myWdFunc(void) {
semGive(mySemID);
wdStart(myWDID, NUM_CLK_TICKS, myWdFunc, 0 );
I think I would have swapped those two lines too - for the same
reason. Restart the WD before you do anything else (including the
ever-so-fast semGive). In this case, since the function is executing
in interrupt context it will probably not make much difference, until
a higher priority interrupt comes in between the two calls.
Of course, even with the wdStart() first, there is still a chance of
another interrupt getting in there before the watchdog is restarted.
True, but in order for a higher priority interrupt to make any difference,
you would need to be executing in interrupt context for an entire system
clock cycle. If this is the case, you've probably got bigger problems in
your system...
Post by John
What you really need for periodic systems is a self-reloading timer...
I just re-read the OP's post, and he was talking about a frequency around
1Khz. At that rate, using watchdog timers and the system clock is
probably not advisable, anyway. The aux clock would be much more
appropriate (so, in retrospect, we should have just pointed him at the
FAQ).

Keith
--
"One should not pursue goals that are easily achieved."
- Albert Einstein, 1915
yueshi
2003-07-26 12:58:20 UTC
Permalink
Thank you so much, Keith and John.

Actually, the situation I've been trapped in consists of two problems:
a) synchronization between two computers, and b) each computer
regularly calls its particular routines.

Let me describe it a little bit more detailedly: I am currently using
VxWorks 5.5 to control two target machines (one Pentium 3, the other
Pentium 2). The idea is when a control loop is about to take place,
master computer sends a package to slave computer informing the
starting of loop as a kind of synchronization; then, each computer
runs some routines regularly at different freqencies (actually master
has a interrupt generater board as its clock, while slave has to rely
on its system clock); finally, after the loop finishes, master also
sends a package informing the termination of program's running.

The below diagram illustrates the whole precedure, numbers show the
sequence of actions :)
(2)slave receives the 'start' signal and starts run-
| ning some particular routine
|
| (4)slave regularly runs some routine depending on
| | its own clock at some slower freq.
| |
| | (6)slave recieves the 'end' signal
| | | and stop executing its routine
| | |
slave computer -----+---+---+---+--+---
^ ^
| |
| |
master computer ---++++++++++++++++++---
|| |
|| |
|| (5)master sends a 'end' singal to
|| slave when its main loop finishes
||
|(3)master starts running its own routine at some
| frequency
|
(1)master send a UDP package to slave computer to
inform 'action starts'

So, it seems there are two major problems here, a)how to synchronise
two computers, and b)how to make sure each computer calls its
respective routines at its respective frequency. We need the accuracy
to be 1ms, and since the whole procedure only lasts two minutes, let's
assume the hardward clock drift is not a problem.

A few relavent issues requires consideration, I guess:

The first is to setup the synchronization, I am thinking about just by
sending UDP, because two computers are connected to one signal
switcher, the Ethernet connection is reliable. There may exist some
better way.

The second is to ensure each call in the slave computer happens
exactly at correct moment, we can use TaskDelay or WatchDog, however
since the system clock rate is at only 60Hz, how can we know the first
calling happens 1/60 second after receiving the synchronization
signal, since that signal will probably comes between two 1/60sec time
instants.

I guess we need another system clock with high resolution, so the
third issue is how to achieve that in Pentium/VxWorks platform, the
sysAuxClock could be one possibility or one colleague in my office
told me he can use clock (incrementor) inside the PowerPc CPU which
can be accurate to 10-15ns, I am not sure if Pentium has similar thing
and if it's easy to implement that in VxWorks.

Hope I have made myself clear, and could anybody lend me some help on
this problem, it seems there's no simple answer for it (as least for
myself)? Thanks again for you VxWorks experts' kind help.

Sincerely
Yueshi

Continue reading on narkive:
Loading...