Here, in my code below, it consist of 7 independent tasks and those are switched from one to another on a timer interrupt. ‘May be’ this could be considered as a simple & very basic RTOS demo…
Scheduling algorithm used: Round-robin (RR)
(one of the simplest scheduling algorithm)
Here, total RAM (2KB) is divided among 7 tasks almost equally in such a way that each one get around 300 bytes of RAM space. This 300 bytes is considered
as the stack for each task. When the timer reaches the compare value, it trigger an interrupt. Now inside ISR, at first all the registers are pushed onto it’s stack. Program counter is already push (automatically) at first when the interrupt is triggered. Now after pushing all the registers, the status register is pushed onto the stack(avr doesn’t do it automatically). Thus we made a backup of all the register values and the status register and we are safe to use those register for some other purpose. Now the next process is the switching between tasks ie the context switching. Before that we need to backup the current stack pointer otherwise we will miss it and couldn’t resume the task when it’s time slot appears for the next time. So a 50(more than enough) bytes are reserved from the RAMEND to store the task index(which task is running now) and the stack pointers of all the tasks. This is considered as the stack pointer backup table or array.
Now, when the task1 is interrupted by the switching timer interrupt, as said above, it push all CPU registers and the status register. Then it checks the ‘task index’ which will be there on the RAMEND. From the task index, we get the task number and thus we can obtain the exact location on the stack backup table on which the stack pointer value is to be stored. Also we can get the next task’s stack pointer value relative to the location where we stored the current one and that is loaded to the stack pointer. So, we got the stack pointer of the next task. Now, we can pop the status register and all the cpu registers and finally the RETI instruction will enable the global interrupt and then divert (jump to new PC value) the cpu to resume the next task…. This repeats with a time slot in range of micro seconds and thus we feel all the tasks are running in parallel and also purely independent even though they are using the same cpu registers in common.
Here are some pictures which I drawn to make the above explanation more clear. It represent the RAM usage for the stack pointer backup table and the process stack.For more detail: Multitasking in AVR (A demo to run 7 tasks on an atmega32)
This free embedded project also found using:
- arduino multitasking
- atmega multitasking