|
There are many philosophical questions that need to be
answered within our lives. One of great value that requires your assessment
is ... Are you satisfied with your superloop architecture? Have you experienced
any problems or difficulties with it? If not, don't bother, you are lucky,
you can be happy with simple things. If yes, you need a scheduler!
You are about to leave this page, you think you can live
happily with simple things; glorious superloops is all you need. Well,
I doubt it. You possibly had a look at the thermometer tutorial; I will
remind you what the related tasks for this project were. We were taking
a few temperature measurements, then averaged them and displayed temperature.
At the same time we had to poll the button and debounce it to decide if
measurements are to be displayed in Fahrenheit or Celsius. Also, we used
the serial interface to send measurements to a PC. Even this simple project
gets a little bit tricky with tasks and timings.
If I give you the details and the low level routines for
this project are you ready to write the code straight away? I cannot,
it requires some thinking and tweaking, the whole thing is not clear from
the beginning. The truth is, we can get away with our beloved superloop,
especially if we use interrupts for button debouncing. However,
this is a simple project and it doesn't have any timing requirements.
Think about this, say there is a deadline to have a fresh new temperature
measurement every second, on the second! It gets more difficult, isn't
it? Real life projects have such requirements and can be far more complicated.
When your code has strict deadlines, or when you can't get the timing
right or when you want your code to be more modular, I suggest you go for
a scheduler.
Although I am not sure if I convinced you or not ... The
idea with schedulers is, you have a timer ticking, defining a time period.
On overflow, the timer is automatically reloaded to get the desired periodicity.
You can see it as a high level clock responsible for task synchronization.
Now, for each task we define two things, the initial delay before the task
is executed for the very first time (in multiples of timer periods) and the
task execution frequency (in multiples of timer periods). On each timer overflow
interrupt we update the scheduler marking the tasks that are to run. In the main
routine, the "dispatch" routine executes the marked tasks. If there is fog,
it will clear out soon.
Schedulers are one of the main components of operating systems,
since they decide how the processor time will be distributed amongst processes,
to give the illusion of concurrency. Schedulers are classified as cooperative
and preemptive. With preemptive schedulers, within a single period, a single task
executes and finishes its job. We have to be sure that even the longest task
completes before the timer times out. This is nice and simple. With cooperative
schedulers tasks may not finish within a single period, task context is
saved, other tasks may run occupying a few scheduler periods and then the initial
task may be reloaded to continue its operation. Nice but, hard to implement,
there is "too much science" behind this idea. Let's go for the nice and simple one.
|