Design Article

The basics of embedded multitasking on a PIC: Part 1 - Reentrant multitasking

Gamal Ali Labib

12/3/2007 12:30 AM EST

High-end concepts typically aren't applied to an 8-bit MCU. But don't rule them out just yet.

Applying multitasking to an embedded system based on a PIC microcontroller may look appealing. It permits full use of the PIC resources by serving more than one task at a time rather than staying idle waiting for an external event to occur and reacting accordingly from within an application. However, multitasking can turn applications into memory-hungry monsters that barely fit in your PIC. Task reentrancy is one approach that tackles expanded memory tasks, especially in small to medium PICs.

In this, the first part one of a three part series about reentrant multitasking and how you can realize it with two working examples of a Microchip's PICmicro MCU, I begin with an introduction to multitasking. In part two and three, available on Embedded.com, I'll get more into the meat of multitasking on the PIC.

Embedded multitasking is not new. It goes back some 30 years. The Intel 8080, Zilog Z80, and Motorola 68000 were popular microcontrollers 30 years ago. Interestingly, they were very similar in processing capabilities to many of today's microcontrollers. Those ancient devices had multiple general-purpose and index registers that could perform arithmetic and logic operations, and supported vectored interrupts and I/O ports. They had data buses with widths up to 16 bits, and address buses up to 24-bits wide. They also had large and powerful instruction sets that gave way to efficient programming and ran at moderate speeds of around 10 MHz. What's changed over the years is that today, that same processor is packaged with RAM and EPROM. Adding analog-to-digital modules and EEPROM gives us today's "microcontrollers."

Thirty years ago, full-fledged real-time operating systems (RTOSs) existed and professional features like multitasking and multiprocessing were applied and implemented. This brings up an interesting point: where exactly does multitasking fit with this technology? With a little research, I found that products are available to handle multitasking with an RTOS. Developers must then question whether the RTOS is really required for their application, or near-real-time would suffice.

Back then, in the absence of multitasking, serial task execution was the only way to run embedded systems. Figure 1 shows two tasks running in a system. Task #1 executes until it concludes its operation, then passes control to Task #2. Task #2 runs and eventually terminates causing system operation to end.


Next:




cpns

12/3/2007 5:22 AM EST

I was with you right up to to the point where you characterised priority-based scheduling as "higher priority tasks use resources more frequently than lower priority ones". This may be the case on a time-sharing scheduler as used in general purpose desktop operating systems, but it is not usually a characteristic of an RTOS, where a task with higher-priority merely has the right to access a resource in preference to lower priority tasks. That does not mean that it executes more often, merely that it executes when it needs to rather than waiting for lower priority tasks to complete or yield. In most cases such tasks in fact run far less frequently. An RTOS is about deterministic behaviour and guaranteed execution latencies, not about how often a task runs.

It mat have been a throw-away point not critical to the overall article, but I have seen inexperienced developers misapply priorities based upon similar misconceptions, resulting in systems that do not meet their real-time constraints.

Sign in to Reply



glabib

12/3/2007 6:53 PM EST

To make my point clearer, consider the scheduler of Windows CE (a true RTOS) for example. You find that threads that have a higher priority are scheduled to run first. Threads that have a lower priority do not run (or get suspended) until all of the threads that have a higher priority have finished. Threads that have the same priority (whatever high or low) run in a round-robin fashion for a time slice, or quantum. This gives an indication that Windows CE has a time-sharing and priority-based scheduler. This also gives some indication to the time slices a task gets, to access system resources, relative to the lifetime of the task invocation.

Sign in to Reply



GT Bradley

12/6/2007 11:36 AM EST

I have to agree with cpns. Especially with respect to Liu's paper on Rate-Monotonic-Scheduling. Where shorter tasks have higher priorities. Conceptually you could imagine an interrupt handler which has a very high priority (e.g. emergency shutdown), but that doesn't necessarily mean it is running more often. The expected frequency of operation does not directly map to it's priority.

good article though..

Sign in to Reply



Stefan Daystrom

12/6/2007 4:03 PM EST

I find the transition from discussing non-OS cooperative to OS cooperative confusing. Are there multiple defintions of cooperative? How "cooperative" is it if you insert a breakpoint into a task (without the task being aware of it)? The cooperative OS approaches I'm familiar with on the PIC (for example, Pumpkin's Salvo) use the concept of the programmer inserting Yield() calls into each task, which return control to the OS, which can then decide whether to switch to another task or give this task some more time.

Maybe this is what the author meant, but that's not how I interpret the term "breakpoint". (As I know the term from debugging, it is a stop to a task determined at run time, not at coding time. But Yield() is a stop to a task determined at coding time.)

Sign in to Reply



Tom Mariner

12/31/2007 10:19 AM EST

All very good points. To add a few perspectives and opinions:

"Higher Priority" -- the understanding of that term is the difference between the vast sea of computer programmers and embedded designers. The very essence of the main task that is really doing the work is that it is normally close to the lowest priority. For example, in the field of medical imaging, one is, well, processing images. We have hade experience with partners who take that to mean that once an image is being converted from pixels of a depth to a medically usable image, that task grabs almost the highest priority and slows down Ethernet and other comms, basic sensing, etc. The point we all know is that the highest priority task has to have the shortest duration and the very measure of a real-time system is how short one can make these tasks. Our lower level products are built on Pics and the higher level on Windows / Windows CE under .Net.

"Lack of decent stack". Yup, one of the reasons the PIC can execute real tasks so quickly is that it has a grotty stack configuration. But real-time is not the only way to handle the allocation of storage. The HiTech compilers, for example, do a great job of looking at the whole program during compile time and making sure that an automatic variable in a calling function is not reused in a called function, not matter how deep the stack. As long as the compiler knows what the operational sequence is (they call it the "call graph") one can be guaranteed that the variable will not be used. Of course, reentrant or reused code cannot use this method. We normally run 8 time sliced tasks that do not bump into each other.

But I do like the article from the prespective that one can execute an RTOS that properly utilizes the multi-tasking abilities of the PIC.

Sign in to Reply



Please sign in to post comment

Navigate to related information

Datasheets.com Parts Search

185 million searchable parts
(please enter a part number or hit search to begin)

Feedback Form