Re: Do I need a RTOS?
- From: Jonathan Kirwan <jkirwan@xxxxxxxxxxxxxx>
- Date: Thu, 25 Dec 2008 10:52:47 GMT
On Thu, 25 Dec 2008 02:58:15 -0600, "eeboy" <jason@xxxxxxxxxxxxxxxx>
wrote:
Hmm? Everything from AP up until RP is free. What do you mean "keep
something in an empty slot?" If all the pointers point to the same
place, everything is empty ... by definition.
Ha! Ok.... my confusion here was all based on the definition of empty.
When you said empty I was thinking that you were referring to no tasks in
the queue and requesting that I always keep some task in the queue.
However, in fact, you are simply stating that the queue length (QMAX) needs
to be chosen such that it is sufficiently large to handle the worst case.
In other words... there must always be a hole in the available queue.
Yes. Always. Solves problems.
However... you said, "call Execute function above" at some point. I
... well, I wouldn't necessarily do that there. What I often arrange
is that there is ... in main() ... a busy loop. Something like:
for ( ; ; )
execute();
It is there that I call the execute function, over and over, pumping
processes out. This is why I said you also might not want to always
fire out the processes right away in the timer, itself. Or even in
bursts when all their .delta's == 0. Instead, fire off one at a time
with execute() and call execute() as your basic busy loop in main.
Just a possibility to consider.
I thought about having the main loop call the execute function but I had
two concerns:
1) If I call execute, I can not utilize the sleep pointer in comparison to
the ready pointer (ie: do until RP==SP) to determine if anything needs
execution. I guess this isn't a concern because I could simply look for
.delta ==0.
I'm not following the above point. In fact, I do use RP == SP for
that determination. If they are equal, there is nothing to run.
2) The more idle tasks that I stuff in my main loop the more my queue
execution precision declines. Is it your intention that the only thing in
my main loop be the execute function?
For those applications where small timing jitter is important, yes.
That's all there is. The idea here is "pump" execution when you have
a moment to do so. Just let the timer move processes to the ready
queue, but don't force their execution right away. That allows you a
lot more control about _when_. If you "force" execution on the basis
of the timer event, which can be fine too, then things start getting a
little more complicated when you need to hold things back for some
critical moment, should one arise. You can always call it from the
timer event, of course. But making it a separate function has value,
too.
One of the things this saves you from is having to deal with
pre-emption or setting up separate stacks for co-routines/processes,
while still having pretty good precision on your timing. One of the
nice advantages of the delta queue is that there is only one entry to
examine so it is very, very fast. This permits excellent resolution
in time if you want it (by setting up a faster clock event), moving an
entry from the sleep queue to the run queue. And if your for(;;)
execute(); loop is no more than that, your variation in starting such
functions is rather small on most micros. If done in the timer event,
it's extremely predictable as moving the run queue head forward one
position is ... very fast and consistent. Of course, if you have
several queued up with .delta=0 and ready to be moved and run.. then
you cannot run them all together at once.
In practice, it's just something to be aware of, but not overly
concerned about. Usually, I know almost to a microsecond how long
each function requires (or, at least, its maximum extent in time) and
what its periodic timing is supposed to be. The rest is just a matter
of setting it up in the first place and just letting them run.
It isn't a panacea, though.
I do see the drawback of calling execute from within the ISR though. It
doesn't allow me to immediately respond to other interrupts coming in and
that could be troublesome if the function I am to execute is of substantial
length.
Yes.
In a somewhat related question, at what point do you draw the line for
implementing a software delay (burn cycles) versus implementing some sort
of call back with the method described above.
What would the callback do for you?
For example, I might have a situation where I must wait 20ms after writing
to an external Flash memory device or perhaps a 300ms to wait after
initializing an external delay. Where/how do you determine where to draw
the line?
If you don't have anything else to do, then there is no issue. Just
wait, I suppose. But there is no reason why other functions might not
be scheduled to run at other times. For flash transactions, where
there are necessary delays as well, you can keep a queue within that
module that tracks pending operations and have it schedule itself,
appropriately. If there is a delay to be done, it just schedules its
next event after the delay. Since no other module even cares about
the queue of flash transactions except perhaps to add some more to it,
they can be doing their thing in between. But the flash module will
be sleeping on the queue until some delay has taken place and before
going on to the next transaction to be done.
Maybe I didn't understand your point, though.
And I didn't say NOT to perform the execute() from your timer event.
Just suggested that you should keep in mind you don't necessarily have
to do that and that it can actually be better sometimes not to do
that. If you know enough about your scheduled functions to know it
won't be an issue, do it. I have had things like a serial eeprom
module driven hard by the timer interrupt; performing exactly one
state transition and then exiting. Ran in the background without any
problems. But I knew that each state transition was short, too. It's
really up to you.
You can also just do some work between calls to execute(), too. If
you really do need pre-emption, though, or want to benefit from the
clean coding that can take place when threads have separate stacks of
their own, you may want to consider an operating system of a more
traditional form -- cooperative or pre-emptive. I have to admit it is
very risky quarterbacking some project I know nothing much about. So
all this I've discussed may not be right for you.
Ok... I think I have a clear picture. I'll get busy on implementing but I
am sure I'll have more questions at some point.
If I'm around (and I haven't been for quite some time), I'll respond.
Thanks again!
No problem.
Jon
.
- References:
- Do I need a RTOS?
- From: eeboy
- Re: Do I need a RTOS?
- From: eeboy
- Re: Do I need a RTOS?
- From: Jonathan Kirwan
- Re: Do I need a RTOS?
- From: eeboy
- Re: Do I need a RTOS?
- From: Jonathan Kirwan
- Re: Do I need a RTOS?
- From: eeboy
- Do I need a RTOS?
- Prev by Date: Re: Do I need a RTOS?
- Next by Date: Re: Do I need a RTOS?
- Previous by thread: Re: Do I need a RTOS?
- Next by thread: Re: Do I need a RTOS?
- Index(es):
Relevant Pages
|