On Sun, 05 Sep 2004 11:03:49 GMT, Ken Smith <nospam@thanks.com> wrote:
>> Hi folk,
>> We were designing an RTOS for a general 8 bit microcontroller.
>> We have designed a round robin schedular.
>Source code for 8051 RTOS here. Why not use this?
>http://www.FreeRTOS.org
>Why use RTOS on 8051?
Or use Intel's iDCX (RMX), also free, public domain etc. Is very good.
Pieter Hoeben
http://www.hoeben.com
Reply by Jonathan Kirwan●September 8, 20042004-09-08
On 8 Sep 2004 06:27:00 -0700, robin.pain@tesco.net (robin.pain@tesco.net) wrote:
>This is excellent stuff. I learn something. Thanks Jon (and Hans for triggering it).
You are too kind. :) Or else, you like to stir the pot. ;) But for such kind
comments, I'll add a couple of notes that reply to the OP's original points...
In my mind, the concept of "round robin" implies either that there is no support
for process priorities or else that equal process priorities are permitted *and*
that there must be pre-emption support involved. Without pre-emption, for
example, changing processes is cooperative rather than forced and the idea of
"round robin" sharing of the CPU time loses meaning. Similarly, if there are
process priorities, but no two processes can have the same priority, then there
is no way that round robin sharing is going on -- the highest priority process
that is ready to run simply runs.
Stacks for separate threads or processes can be allocated using the usual static
arrays (I often use this method) or they can be allocated dynamically with heap
(malloc) or else allocated on a local function stack frame (unusual, but
workable.) What's chosen depends on what features are desired and what emphasis
is placed on problems to avoid. Stacks can be allocated upon process creation
when running or at compile time, or even some mixture. But with very small
micros, it is usually advisable to use static allocation and to avoid run-time
creation issues. It takes less code and it runs faster, usually.
In the case of the 8051, I'm must admit I'm not experienced using 8051 C
compilers (I have always used assembly in that case.) But I believe I've read
that the 8051 C compilers (competitive ones, anyway) perform a call-tree
analysis so that they know at compile time the maximum amount of stack required
by an application. (I don't know how that works across separately compiled
modules, if true, but I guess it would probably have to involve some kind of
link-time analysis.) At least, that could be true where recursion isn't used.
Anyway, they may perform this analysis and place what appears to the application
programmer as 'auto' instances within functions into static memory, as though
'static' had been used.
If so, I'd also guess that those functions appearing further down the call-tree
than recursive ones would have to have their stacks implemented in the
traditional fashion, without static allocations, or else a real mess would take
place. I don't know the details here, either. All of this suggests that there
is a somewhat complex process model that is active in the output of modern 8051
C compilers.
Now, in writing an operating system for micro/embedded use, I've never
experienced a case where I wanted completely separate processes, with all of the
automatic variables as well as all of the static variables completely separated.
It's always been the case for me that I merely wanted the automatic variables in
C (those local to the function instance) distinct in each thread, but where the
static variables (scoped appropriately) were held in common. I think this is
the usual case.
To handle that, the exact details of each C compiler output in handling these
auto variables (when the compiler makes decisions to convert them to static
locations) is needed in order to properly design an operating system that can
support pre-emption of threads in C applications. Auto variables used in C
functions are an important part of the process context and how these are better
preserved will depend on the detailed understanding of what C compilers do with
them.
What do the various C compilers to be supported actually do? What about their
libraries? (Floating point, for example, if supported at all.)
Usually, by the time this question has been carefully crafted accurately, the
answer about the better way to save and restore the context will be much clearer
in mind.
Finally, the idea of 'atomic operations' can be based on both design as well as
the use of the interrupt system. As an example, a system can be designed so
that only one process may be using the operating system functions at a time and
this fact may serve to protect static data structures without the need for
always enabling and disabling the interrupt system every time the data in the
O/S is accessed.
Jon
Reply by robi...@tesco.net●September 8, 20042004-09-08
Jonathan Kirwan <jkirwan@easystreet.com> wrote in message news:<q42pj0tocb86mm88e2augmne7d737jqrjl@4ax.com>...
< terrific description snipped >
This is excellent stuff. I learn something. Thanks Jon (and Hans for triggering it).
Robin
Reply by ruffrecords●September 7, 20042004-09-07
Hans-Bernhard Broeker wrote:
> ruffrecords <ruffrecords@yahoo.com> wrote:
> [...]
>
>>Not necessarily. The _only_ way to pre-empt a running task on an 8051
>>is by a hardware interrupt. This automaticaly saves the return
>>address of the pre-empted code on the stack. If you want to save any
>>other registers that is up to you.
>
>
> Not if what you're trying to do is to go under the term of
> "multi-tasking" it isn't. Note: running an interrupt handler isn't
> multi-tasking yet, even though it certainly is pre-emptive.
Yes and no. You can certainly multi-task this way, but I agree just
running an interrupt handler is not really multi-tasking.
>
> There's a difference between having an actual multi-tasking system,
> and running a plain old embedded system with a couple of interrupt
> handlers set up. And the need to switch/save state, including (on
> machines that have them, ...) registers and stack contents, is a major
> aspect of that very difference.
Again, yes and no. There are many ways to design a mutli-tasking
system and one way to make them work on low resource processors like
the 8051 is minimise the state data that nees to be saved when task
switcing. As I think I mentioned, one way to do this is to use global
variables and just save the program counter,accumulator and PSW and
avoid using the other registers in tasks. If you decide to allow
tasks to use the entire register set then of course you need to save
it when you switch tasks. But I would suggest that in many cases this
is innecessary and inappropriate, especially on a resource limited
micro like the 8051.
>
> If you actually want to *switch* among multiple tasks (of unspecified
> number, and unspecified order of execution), then someone (either the
> kernel, or the task itself) has to save everything that the task may
> be expecting to remain intact, and restore it before switching back to
> that task. On a '51 that quite definitely includes all the usual
> registers (A, B, r0..r7, PSW, and then some) and the call stack, or
> madness would ensue.
See my answer above.
As I said in my original reply, the concept of a general purpose rtos
on an 8051 seems to me to be rather misplaced.
Ian
Reply by Hans-Bernhard Broeker●September 7, 20042004-09-07
ruffrecords <ruffrecords@yahoo.com> wrote:
[...]
> Not necessarily. The _only_ way to pre-empt a running task on an 8051
> is by a hardware interrupt. This automaticaly saves the return
> address of the pre-empted code on the stack. If you want to save any
> other registers that is up to you.
Not if what you're trying to do is to go under the term of
"multi-tasking" it isn't. Note: running an interrupt handler isn't
multi-tasking yet, even though it certainly is pre-emptive.
There's a difference between having an actual multi-tasking system,
and running a plain old embedded system with a couple of interrupt
handlers set up. And the need to switch/save state, including (on
machines that have them, ...) registers and stack contents, is a major
aspect of that very difference.
If you actually want to *switch* among multiple tasks (of unspecified
number, and unspecified order of execution), then someone (either the
kernel, or the task itself) has to save everything that the task may
be expecting to remain intact, and restore it before switching back to
that task. On a '51 that quite definitely includes all the usual
registers (A, B, r0..r7, PSW, and then some) and the call stack, or
madness would ensue.
--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply by Jim Granville●September 6, 20042004-09-06
ruffrecords wrote:
>
>> Jonathan Kirwan <jkirwan@easystreet.com> wrote:
>> We do happen to be talking about 8051s, though, which quite certainly
>> do have a stack, and therefore this stack _will_ to be switched or
>> saved, if you want to pre-empt a task on this platform.
>>
>
> Not necessarily. The _only_ way to pre-empt a running task on an 8051
> is by a hardware interrupt. This automaticaly saves the return address
> of the pre-empted code on the stack. If you want to save any other
> registers that is up to you. In simple 8051 real time systems it is
> common to use global variables to make it unnecessary to save anything
> other than the accumulator on the stack. No stack switching is
> necessary but is is certainly pre-emptive.
To further this point, the 8051 also has register banks, designed
specifically for interrupt switching. The 8051 direct memory opcodes,
and Boolean processor engine makes it possible to have a
practical interrupt and NOT even USE the accumulator, or PUSH/POP.
You can save PSW with PUSH/POP, but you can also more quickly save the
carry flag into a boolean variable.
-jg
Reply by ruffrecords●September 6, 20042004-09-06
Hans-Bernhard Broeker wrote:
> Jonathan Kirwan <jkirwan@easystreet.com> wrote:
>
>>On 6 Sep 2004 10:49:37 GMT, Hans-Bernhard Broeker
>><broeker@physik.rwth-aachen.de> wrote:
>
>
> [...]
>
>>>The need for stack switching is a property of pre-emptive scheduling,
>
>
>>No, this isn't strictly true and it suggests you don't have a clear mental
>>model.
>
>
> Maybe --- I'm simply not old enough to ever have come across platforms
> without a stack.
>
>
>>Pre-emptive scheduling can even be performed on CPUs that don't even
>>support stacks in their hardware architecture, such as the HP-2116
>>from the days of the late 1960's and early 1970's, for example. So
>>it cannot be that stack switching is a __property__ of pre-emptive
>>scheduling.
>
>
> Now where's that grain of salt when you need it? :-) That you don't
> have to switch or copy stacks, if there are no stacks to do that with,
> should go without saying, shouldn't it?
>
> We do happen to be talking about 8051s, though, which quite certainly
> do have a stack, and therefore this stack _will_ to be switched or
> saved, if you want to pre-empt a task on this platform.
>
Not necessarily. The _only_ way to pre-empt a running task on an 8051
is by a hardware interrupt. This automaticaly saves the return
address of the pre-empted code on the stack. If you want to save any
other registers that is up to you. In simple 8051 real time systems
it is common to use global variables to make it unnecessary to save
anything other than the accumulator on the stack. No stack switching
is necessary but is is certainly pre-emptive.
Ian
Reply by Jonathan Kirwan●September 6, 20042004-09-06
On 6 Sep 2004 19:15:01 GMT, Hans-Bernhard Broeker
<broeker@physik.rwth-aachen.de> wrote:
>Jonathan Kirwan <jkirwan@easystreet.com> wrote:
>> On 6 Sep 2004 10:49:37 GMT, Hans-Bernhard Broeker
>> <broeker@physik.rwth-aachen.de> wrote:
>
>[...]
>> >The need for stack switching is a property of pre-emptive scheduling,
>
>> No, this isn't strictly true and it suggests you don't have a clear mental
>> model.
>
>Maybe --- I'm simply not old enough to ever have come across platforms
>without a stack.
Understood. But the point wasn't whether or not you were old enough to see such
things or not. I was offering only one example that shows that the precision of
your point was lacking.
You said, "The need for stack switching is a property of pre-emptive
scheduling," and it was this point I took issue with, using just one possible
example of a great many others I could also provide. Stack switching quite
simply is NOT a property associated 1:1 with pre-emptive scheduling. Switching
stacks does not imply pre-emption; and pre-emption does not imply switching
stacks. They are separate things and you were conflating them in your comments.
It was that I was addressing.
>> Pre-emptive scheduling can even be performed on CPUs that don't even
>> support stacks in their hardware architecture, such as the HP-2116
>> from the days of the late 1960's and early 1970's, for example. So
>> it cannot be that stack switching is a __property__ of pre-emptive
>> scheduling.
>
>Now where's that grain of salt when you need it? :-) That you don't
>have to switch or copy stacks, if there are no stacks to do that with,
>should go without saying, shouldn't it?
We could get into that argument, of course. But again, my point clearly remains
that switching stacks isn't a property of pre-emption. In other words,
pre-emption is about saving and restoring the important context and it goes
further and provides implications about just what state is considered
'important'. That *may* (and often does) imply switching stacks, where that is
convenient, of course.
But what I'd like you to take away from this is that conflating the two ideas
turns some very precise terms which are very useful and mushes them together
into a 'gooo' that is less helpful over a broad range of possibilities. It's
better to keep the theories precise, than to glop them together without clarity.
>We do happen to be talking about 8051s, though, which quite certainly
>do have a stack, and therefore this stack _will_ to be switched or
>saved, if you want to pre-empt a task on this platform.
That again depends. I can imagine a specific case in my mind on the 8051 where
pre-emption and a separate process is involved without the switching of stacks.
Point remains -- keep the concepts clean and use the right terms for the right
things.
Jon
Reply by Paul Keinanen●September 6, 20042004-09-06
On 6 Sep 2004 19:15:01 GMT, Hans-Bernhard Broeker
<broeker@physik.rwth-aachen.de> wrote:
>Maybe --- I'm simply not old enough to ever have come across platforms
>without a stack.
You must have seen the RCA 1802 :-).
It has 16 registers, of which all could be used as program counter. So
it was easy to have up to 16 separate subroutines each with an own
program counter. You could also view the system as up to 16
cooperative tasks, each with a separate program counter.
When the program was running with say R7 as the program counter, to
call a subroutine/task that was written with say, R9 as the program
counter, simply specify which register to use as the program counter
with the SEP R9 instruction and the original PC register (R7) is no
longer updated. When the subroutine is going to "exit", it will jump
one byte before the actual start point and switch back to the original
register using the SEP R7 instruction and the calling routine
continues execution where it performed the call. With the jump ahead
of the actual subroutine, the subroutine PC (R9) is ready for the next
activation.
Thus, one can argue, are these routines subroutines or cooperative
tasks.
Paul
Reply by Hans-Bernhard Broeker●September 6, 20042004-09-06
> >The need for stack switching is a property of pre-emptive scheduling,
> No, this isn't strictly true and it suggests you don't have a clear mental
> model.
Maybe --- I'm simply not old enough to ever have come across platforms
without a stack.
> Pre-emptive scheduling can even be performed on CPUs that don't even
> support stacks in their hardware architecture, such as the HP-2116
> from the days of the late 1960's and early 1970's, for example. So
> it cannot be that stack switching is a __property__ of pre-emptive
> scheduling.
Now where's that grain of salt when you need it? :-) That you don't
have to switch or copy stacks, if there are no stacks to do that with,
should go without saying, shouldn't it?
We do happen to be talking about 8051s, though, which quite certainly
do have a stack, and therefore this stack _will_ to be switched or
saved, if you want to pre-empt a task on this platform.
--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.