Internals
Scheduler

The scheduler runs on a clock policy, that is decisions on which tasks will run next are determined at specific time instants, which are stored along with the Job and set by the user. For example, if a soft aperiodic task is running and a hard periodic task is scheduled to run, then the scheduler makes its next scheduling decision at the time instant when the hard periodic task is set to run, as opposed to other schemes such as frame based or priority driven. While this scheduling scheme does not validate actual task running times and cannot guarantee deadlines as well, it is the simplest approach. Any more complicated approach would probably waste more CPU and memory, which the Atmel does not have an abundance of. At every scheduling instant, the scheduler runs through the following algorithm to determine next task to run:

if there exists a HP task ready to run, execute it else if there exists a HA task to run or resume, execute it else if there exists a SP task to run or resume, execute it else if there exists a SA task to run or resume, execute it else run NO_TASK

NO_TASK is merely a "while (1)" loop which is meant to keep the CPU busy until the another task arrives for processing. Another possibility would be to put the CPU to sleep, however we did not have enough time to implement such optimizations. Based on this result, the scheduler sets a timer compare variable for the next instant at which it needs to be called. Of course, if there are tasks during this time which disable interrupts the scheduler will not be accurate, so the user should strive greatly to make such cases as short as possible, at least just in the section which disables interrupts. Even worse is that the time which the scheduler executes with also causes timing error. Another future optimization awaits. If a task returns early, ie before its deadline, the scheduler will attempt to run the next available non-hard periodic task (ie Priority > 0), thus reclaiming much wasted time. This policy is particularly important since there is always likely to exist a significant amount of NO_TASK execution. The only case where this would not happen is if

  • user load is constant and fills the schedule perfectly
  • a task, such as a soft aperiodic task which never ends, always exists to be executed

Even if the average load fills up empty time in the hard periodic queue perfectly, the finite sized queues will prevent the load from reaching the intended average load.