CreateThread(wThreadName......... this is an attempt to open for discussion
the variety of styles that PIC software engineers have developed to
implement operating systems. Assertion: Every PIC program that "works" has
an operating system in the broadest sense.
If this topic interests you, you might as well print this out and read it
when you have spare time. It's rather lengthy. Toward the end I dwell on
event-driven operating systems. If you read on you'll notice that I'm rather
fond (obsessed) with event-driven programming languages and I've extended my
interests into EDOS's (EventDrivenOperatingSystems).
I've been researching operating systems theory and implementation
for about a month now. My starting point was the app note "A real-time
operating system for the Pic.." in the MCHIP ECH. It contains an
introduction to RTOS terminology and theory of multitasking, and two code
examples (one for a 16C5x and one for 16C64). The code part was frustrating
to try to relate to the theory (and difficult to follow even with comments).
I read some of the "further reading" books the appnote author listed
in the bibliography. I took a copious amount of notes. I drew diagrams and
flow charts. I struggled with the logic of semaphores. I'm still trying to
prove the appnote author's assertion that the binary semaphore can be
implemented using interrupts.
I printed several Windows System Journal articles which further also
defined and elucidated the concepts of semaphore, mutex, critical section,
thread, and process.
Being somewhat versed in the Event-driven programming languages of
AccessBASIC and VisualBASIC, I'm looking to build an event-driven front end
for my PIC projects. If the event-driven paradigm can be applied to the PIC
(and it seems likely) I won't have to throw away my VB training. The
buzzword these days is "reuseable/recycleable software" and I have extended
that to "reuseable self education". So whatever programming style you have
been exposed to and latched onto, you will want to stick with for
After a maximum length conversation with Chris@Microchip (he cut it short
but I could have talked for another 30 minutes) my eyes opened to the
possibility of an EDOS. He pointed out several AppNotes in the ECH that
relied upon the following simplistic model for an operating system.
ORG 04h ;vectored interrupt
lzz GOTO lzz ;Wait for Events
CaseElse ;an unknown interrupt occured
CallErrorHandler ;do whatever you do with the
END ;end of program memory
Chris at Microchip mentioned that Case0 should be either the most important
interrupt to be serviced or the most frequently executed interrupt (like the
system's clock tick). CaseElse is my own way of trapping the runtime error
much like in VisualBasic's OnErrorGoto ErrorHandler
In event driven programming error trapping is like batting practice to a
ballplayer. You spend most of your time anticipating, trapping, and
analyzing errors. Then you go back into your program and try to fix it so
the errors are handled in a more graceful way. The least graceful method of
dealing with system errors is "abnormal program termination" which for a PIC
would be a software RESET and in Windows Programming it would be the "white
window of death", with a user message like "fatal error executing
KERNAL.EXE" On a really boring day at my terminal at work, even the "white
window" event is welcome.
I encourage everyone who finished this article to keep this thread going. I
am willing to discuss the topic on a personal basis via my email address as
Generalisation: *Every* program eventually *is* an operating system
- it tends to end up as an exercise in resource management and scheduling!
>If this topic interests you, you might as well print this out and read it
>when you have spare time. It's rather lengthy. Toward the end I dwell on
>event-driven operating systems. If you read on you'll notice that I'm rather
>fond (obsessed) with event-driven programming languages and I've extended my
>interests into EDOS's (EventDrivenOperatingSystems).
I was thinking of using the event-driven model for a recent project; I'll
explain why I didn't as a counter-example... Primarily this was due to
the need to constrain the state space of the solution. In the event
driven model, it may be important to only allow events to be triggered at
certain times. This may be in order to preserve the overall semantics of
the system, or due to contention for an unsharable resource. For example,
if I've just written data to my EEPROM, I can't allow a read attempt
until the write time is over. As a system grows, thinking about all the
possible interactions can be quite fun (I suspect you've come across this
in Windoze programming - I've certainly been bitten by unforeseen interactions
between VB dialogues)
You need to worry about event sequences, and you're probably heading for
CSP (Communicating Sequential Process - for reasoning about parallel
systems) territory. Of course, in practice it's easier than this, but...
Further, you have to ensure that events are correctly routed - ie: ensure
that a 'keypress' event is directed to the right place.
My project needed a heavily modal user interface, with a number of other
`background' actions running at the same time - so I can't just busy-wait.
Now the nasty bit - I need this to work on a PIC16C57, so I can't use
interrupts, and I'm embarrasingly short of stack (and memory).
My solution was to write a nano-scheduler to handle the background stuff,
and communicate with the foreground system through some booleans. The
foreground task was required to call the scheduler at least every 500
instructions (it could call early, since the RTCC was used to work out
whether it was really time to do the background work yet).
This reserves one level of stack for the scheduler calls (the scheduler
preserves FSR (and hence code bank), and shares no variables with the
foreground except the designated flags). Mutex is not a problem, since
the processor has no interrupts, so we must exit every critial section
and flag access is indivisible within a code block. Race conditions
are also avoided, since the shared flags can only change when the scheduler
The main task is written in the standard imperative style. This does mean
that certain things can't happen at the same time - but these are all things
I don't _want_ to be able to occur together, so I'm happy about that.
The background code runs the timers/keyscan/switch checking stuff - and
since the CLRWDT is in the scheduler, code crashes in the foreground
The one remaining level of stack is needed for the generic `entry editor'
and a few I/O routines for the external h/w and EEPROM.
So, for this app I wouldn't want to use events, because the extra complexity
is not useful to me - I actually want to limit the number of things that
can happen at any point. On the other hand, I'm probably going to use
events in my next project, but that'll be on the '84 so I can have
interrupts and a decent level of sub-routine nesting...
In the end, it depends on the application, the programmer, and probably
the phase of the moon ;-)... But I'd be wary of applying the same method
universally - there is no silver bullet.
Still, a topic worth some discussion - any comments, from those who've read
this far? ;-)
At 6:40 PM 5/16/96, David Warman wrote:
>Now the nasty bit - I need this to work on a PIC16C57, so I can't use
>interrupts, and I'm embarrasingly short of stack (and memory).
>Still, a topic worth some discussion - any comments, from those who've read
>this far? ;-)
Is it possible to have a generalized dicusssion when the PIC family offers
>Still, a topic worth some discussion - any comments, from those who've read
>this far? ;-)
Until I attended the Microchip seminar a couple days ago, I would have
thought an operation system would be a waste of code on the PIC. What
changed my mind was the 7x series which are really on par with the
But I was really interested in the 14000 series and started thinking how to
use these things in parallel. For the type of data acquisition I do the
PICs are just too slow, but in parallel they could grab the data all at
once and analyse it in parallel too.
So back to this operation system. Except for the 7x series is it worth
having an operation system on a single PIC? Certainly debatable. But
could we extend the operation system for a parallel PIC network? Each
PIC could run a micro-kernel that runs the task(s) specific to that PIC
then transmits its results via SPI or parallel slave port to another PIC.
The PICs could be arranged in a ring or star network pattern depending
on the communications system.
I think a parallel PIC OS (PIC-POS?) is _definitely_ worth a look. In
my opinion, a PIC is good for a task or two but not much more (except
for the 7x possibly). What good is writing an OS to switch between a
couple tasks. If your tasks are slow enough (and many applications are)
then an OS could be useful. But for my applications I need speed. My
PICs run smaller tasks that my bigger/faster microcontroller can't
spare the time to run. An operation/network system that monitors all
the PICs in a system could be useful.