I'm going to top post this because I want to keep the following
response from Matthais but want to make a couple of short comments
concerning the use of the cooperative tasker.

1) it is possible to wait for an event in a task and still allow
other tasks to run.  Use a construct like:
  while (waiting for keystroke)
    swap();

2) I almost always do use timers with the tasker.  Typically I will
setup the main counter so it rolls over about every 5mSec (you can
choose your own value).  In the ISR for the rollover I increment a
volatile uint16_t I call sysTICs.  Then I create a couple of timer
handler functions; getSysTICs() returns the current value of sysTICs;
uint16_t getElapsedSysTICs(uint16_t startTICs) returns the number of
rollovers from startTICs to now (the current value of sysTICs).
  These two functions can be used in a number of ways:
a) int ch;
   uint16_t startTICs = getSysTICs();
   while ((ch = getKey()) < 0) &&
          (getElaspedSysTICs(startTICS) < timeoutTICs))
     swap();

b) void sleep(uint16_t duartionTICs)
   { uint16_t startTICs = getSysTICs();
     while (getElapsedTICs(startTICs) < durationTICs)
       swap();
   }

Several tasks can have different timeout timers active at the same
time while only using the rollover interrupt from a single timer
channel.

Regards
-Bill Knight
R O SoftWare

On Fri, 12 Dec 2003 15:37:00 +0100, Matthias Weingart wrote:

On Mon, Dec 08, 2003 at 11:45:16PM +0800, Steve Underwood wrote:
> Hi all,
> 
> The tasker code in examples, is function but very basic. Oleg's SOS is 
> rather more functional, but doesn't really address the needs of an 
> MSP430 user - it does nothing about power management. 

Hi Steve,

I have analysed my code, and in most cases my routines are hanging around in
sleep() or busy? statements, waiting for something to get ready. Most of
that sleeps() are not time critical; it does not really matter if the sleep
takes little longer than specified. Most of the time you have all your tasks
sitting in sleep(); the CPU can switched off, until the time elapsed (or you
got an interrupt, and there is some work for you tasks).
 The cooperative multitasker is a good idea to use that idle time in other
parts (tasks) of the firmware. The tasker has one advantage: it does not
need any timer. Timers are a very rare ressource (I wished TI is spending
more timers to their MSP's; timers should not need much silicon, why not 5
timers?), but with a sleep() function (waiting at least xx ms), we need a
piece of code that is executed periodically. The user of the OS should add
this code to one of his timer interrupt routines. If no timer with a fixed
timing is available, one can use a simple 555 like timer at 2 (or 1)
interrupt port pins (slaa119). However, if you do not need sleeps() you can
drop that code, and tasks are switched as long as there is not task ready 
then it goes to LPM until the next interrupt.
 Another advantage of the tasker is that the tasks are switched when
everything in your task is finished and ready to switch to another task (no
critical sections, no headache with hwmul).
 Disadvantage of the cooperative tasker, however, is that you dead lock the
OS if one task is blocking. You should never use while( busy ) statements,
it should always be a while( busy and not timeout() ).
 There should also be a possibility to get a task running immediately (wake
up a task). Example: You get a ADC interrupt. All your tasks are sleeping.
In the ADC interrupt you specify the task that is executed after RETI, and
your ADC results are processed right away (the same implies for other tasks).

summary, extensions to tasker:
- sleep(ms) (until time elapsed) 
- sleepinfinitely() (until interrupt, until another task has finished)
- timeout() 
- code for a timer interrupt
- some possibilities to prioritize tasks
- if all tasks are sleeping switch to LPM

However this tasker would only work if all your tasks are sleeping
periodically and you can broke your code in pieces that are shorter than
your minimal timing requirements (e.g. ADC interrupt intervals).

Next point is non thread save code (e.g. access to hardware). With a
cooperative multitasker, not thread save code is no problem, as long as it
is not using sleep() itself (switching to other tasks), it does not use
globals and you call it from only one task. But is this possible, really?
Sometimes, maybe; then there should be a mechanism that could tell you that
you do not call non thread save code from different tasks (is gcc able to list
a call tree for all function calls?). Probably we need semaphores and events
here.

I have written this from the view of a firmware programmer (not from the
theoretical view of a OS programmer). Ok, lets compare my list with the
features of SOS or uCOS. Oops, I think I reinvented the wheel. ;-) Make it
sense to reinvent the wheel?  Maybe making it modular, let the coder 
only use the parts he really needs...

        Matthias


-------------------------------------------------------
This SF.net email is sponsored by: IBM Linux Tutorials.
Become an expert in LINUX or just sharpen your skills.  Sign up for IBM's
Free Linux Tutorials.  Learn everything from the bash shell to sys admin.
Click now! http://ads.osdn.com/?ad_id=1278&alloc_id=3371&op=click
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users





Reply via email to