From: briggs@thalia.jpl.nasa.gov (Clark Briggs)
Newsgroups: comp.os.vxworks
Subject: how to implement a controller
Date: Sat, 5 Sep 92 08:14:36 PDT
Organization: Lawrence Berkeley Laboratory, Berkeley CA
NNTP-Posting-Host: 128.3.112.16
Originator: daemon@vxw.ee.lbl.gov

Terry Fong (terry@ptolemy.arc.nasa.gov) summarized his findings about controlling period tasks as:

there are three basic approaches:

1) LOW FREQUENCY

If the controller runs at less than about 60 Hz, and latency on the
order of a few milliseconds is not a problem, the easiest method is to
run a high priority task that uses taskDelay() to wait between cycles.
The caveats are that taskDelay() runs at system clock granularity and
that the task needs to complete in less than a clock tick (or "time"
will be lost). It is possible to run faster than 60 Hz if you change
the system clock speed (though this will mess up other timing
functions), or if you use an auxiliary clock (if your board has one).


2) MEDIUM - HIGH FREQUENCIES
For controllers that run between 30 and 10,000 Hz, a better method
than using taskDelay() is to setup a controller task that synchs on a
binary semaphore. The semaphore is given at the required frequency by
an ISR tied to either the system or auxiliary clock. This is the
recommended method for task synchronization by Wind River Systems, and
is covered in the VxWorks programmer's guide in the synchronization
using semaphores section. Sample code is:

code omitted for brevity...

3) HIGH FREQUENCY / LOW LATENCY
 
If the controller needs to run *really* fast (greater than 10 KHz) or
if low latency (jitter) is critical, then as much processing as
possible should be done at the interrupt level (since this runs at the
highest priority with the lowest latency). One method is to do
everything in the ISR. This has problems, however, if other concurrent tasks
can't handle interrupts that long. Another approach is to do things
similiar to the previous method (i.e., synch a task off of a
semaphore), but to try to do some/all of the calcuations in the ISR
and to disable the system clock (since the kernel steals 100-300 usecs
servicing the clock interrupt).

end of copy of Terry's story...

My Comments:
method 1): changing sysclk from 60hz should not be a problem, in
most respects.  good code can get the sysclk freq and shouldnt code
in 60hz.  I have run sysclk all the way up until the system cant
service the sysclk interrupts fast enough.  This was my first attempt
at running fast controllers.  I got violent frowns from WRS when I
turned sysclk up.  It seems there is nothing inherently wrong with this
its just that they never intended for us to do that to their system.
The most significant problem is this causes the scheduler to run
a lot more and sink a lot of cpu cycles. (In version 4.0 this was
horribly expensive.)
 
Method 2) is the way we run in our labs.  It works well enough, but
is limited by only one sysauxclk.  The isr gets tricky if you are trying
to control several tasks at different rates.
 
We have used method 3, too.  The biggest difficulty, beyond the obvious
poor behavior of tieing up the cpu, it that the processing done in the
ISR really has no context.  this means no file I/O (no surprise, no one
would really violate convention that much would they? you bet they would!)and no floating point!
 
I suggested turning off sysclk, which seems like another
terrible thing to do.  It works but can have severe consequences.  This
makes sense to me only if the task is soooo important it is necessary
to starve everything else, including the network deamons. But, we've
been there too.
 
A final method, is to simply never give up the CPU.  We do this to get
14Khz with 50MHz 68030s.  Make your task highest priority, never sleep,
spin on a sync byte (set by the auxclk isr or a companion cpu), turn off
sysclk, no file I/O....  This simply dedicates the entire cpu to your
task.
 
Thanks to Terry for the prompt posting and the work to get the information.
Clark Briggs
briggs@csi.jpl.nasa.gov