Hi
I've designed and used a minimal RTOS for the last 15 years I call it RTE51 (Real Time Executive). Because of the way that it is used, it is fairly immune to latch ups. It can execute up to 8 task preemptively
. I use register bank 0 for all the tasks, this leaves the other register banks free for interrupts. This however means that I have to copy the contents of register bank 0 to xram during context switching. This adds some latency to the context switching but it saves a tremendous amount of stack space.
I've originally used it with PL/M51 but changed it later to work with KEIL-C which I use extensively. A later change and experiment that I made was to add an additional layer that enabled me to put a task to sleep. These task can be woken after a certain time or after reception of a telegram.
On the original version, once a task have been scheduled, it must execute till it is finished. Higher priority tasks can however preempt lower priority tasks which makes it preemptive.
What might be of interest to you is how to get from an interrupt routine. As you know once you enter an interrupt routine on the 8051 a flag is set which prevents the 8051 from entering a same priority interrupt again. This flag is only reset once the iret instruction is executed but then control is passed back to the program from where it interrupted. With a RTE you would normally want to pass control to the executive after execution of an interrupt. The following snippet shows how to release the 8051 to again be able to interrupt while entering the scheduler and thus reducing latency:
;###################################################** ;* * ;* Call here from 'c' interrupt routines * ;* in order to execute tasks * ;* * ;###################################################**
RteIntExecC: mov r1,#2 sjmp rie05
;###################################################** ;* * ;* Call here from PL/M interrupt routines * ;* in order to execute tasks * ;* * ;###################################################** rte_int_exec_us1: rte_int_exec_us2: rte_int_exec_us3: mov r1,#4 rie05: clr ea ;dissable interrupt mov a,sp ;remove redundant stack clr c subb a,r1 mov sp,a mov a,#low rie10 ;restore the interrupt priority push acc mov a,#high rie10 push acc reti ;the interrupt is over rie10: clr c ;change to register bank 0 mov psw.4,c mov psw.3,c sjmp r_e05 ;regular task scheduler
;#############################################** ;* * ;* Call here from task or background * ;* * ;#############################################** RteExec: rte_exec: push acc ;save register PL/M style push b push dph push dpl push psw clr ea ;dissable interrupt . . ; this is where teh scheduler starts
If you're interested, I can e-mail the assembler code to you.
Regards Kobus