Developer info to improve scheduler
When
- we move some high priority trigger-data processing to userspace
- move some tables from SRAM to EEPROM (to free space for MMC logging and networking), where there are limits of when it can be accessed for read (not during EPPROM write)
- implement more convenience features
See the priority ideas on GenBoard/UnderDevelopment/FirmWare
Even though it is relatively simple, it's a good idea to model it in JAVA first (see package org.vemsgroup.firmware.scheduler in JTune CVS) to verify operation (and maybe tune some variables).
Similar scheduler is implemented in most real-time operating systems.
See task-states on an [an x86 RTOS].
However we don't need preemptive multitasking. Cooperative is fine. So no need for separate stack for each process. When the process returns, it's stack is back to normal anyway. Timing sensitive tasks must be done in interrupt or high-priority process.
A nice OS with non-preemptive multitasking running on the atmega16 (gpl and compilable with avr-gcc) can be found here [ethernut.de]
I created a very simple scheduler:
(some stuff like interrupt management is left out)\n
void scheduler_run(void) { for(;;) { func = schedule_list[current_sched]; schedule_list[current_sched] = NULL; current_sched++; if(func) { func(); } if(current_sched == Last_Prio) { scheduler_sleep(); } }
I've decided to instead of having 4 different queues I just have one huge. Every 'task' has an entry in a large enum, where being first means having more priority.
While this would be very convenient, since it is already implemented (for slightly different purpose) in lcd.c find_dirty(), unfortunately this is not suitable, because it results in "starvation".
scheduler_sleep() is putting the AVR to sleep. Any IO or interrupt will wake it up. On the emulator this will probably be a semaphore.\n
void scheduler_add(prio_t prio, func_t function) { if(current_sched > prio) current_sched = prio; schedule_list[prio] = function; scheduler_wakeup(); }
This function can both be called from interrupt context or from userspace (if one task wants to run another).
scheduler_wakeup() is a NOP on AVR. Emulator will signal the semaphore.
Any task may re-schedule itself either by calling scheduler_add itself, or using the eventqueue to schedule itself sometimes in the future. Can I use the existing eventqueue for this?