Reply by P September 9, 20042004-09-09
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>...
> On 6 Sep 2004 10:49:37 GMT, Hans-Bernhard Broeker > <broeker@physik.rwth-aachen.de> wrote: >
< 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
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. -- Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) Even if all the snow were burnt, ashes would remain.