Embedded Systems: Managing the Flow of Activity


Structuring an embedded system without an OS requires an understanding of some things that an Operating System can do for you. 

On a computer, you load up an email program, web browser, and compiler. Each of these programs runs on a computer, in parallel. 

Now to discuss tasks vs threads. A task is something that a processor does and a thread is a task plus an overhead, such as memory. A process is a complete unit of execution with its own memory space usually separate from other processes. A scheduler switches between processes allow each to run in its proper turn. There are many ways to implement schedulers. The key point is that a scheduler knows all about the system things and what it should do right now. You need to do scheduling yourself without an OS through embedded systems. 

The button-press and LED-Blinking are 2 tasks in a tiny system. When we used a global variable to indicate the button state 2 tasks communicate with each other, but you should not share memory between tasks.

The figure shows the normal course of events where the interrupt sets the shared memory. There can be a race condition, where any memory shared between tasks can exhibit uncertainty. Race conditions can lead to unsafe conditions in a more critical system. 

We need a way to prohibit multiple tasks for reading the same memory, and any time memory is shared between tasks, it creates a critical section of code, meaning code that accesses a shared resource. Shared resources are protected so any task can modify it at a time, and this is called a mutex. Now, we will talk about avoiding race conditions.

When two tasks are running you can use a mutex to figure out which task owns a resource if neither of the tasks is interrupted. The atomic ownership change is one that cannot be modified by anything else in the system.



Let's say a task is interruptible, but otherwise runs until it gives up control. When you turn off interrupts, the system cannot respond as quickly, and turning off interrupts increases the system latency. 

Sometimes interrupts can have priority, but this can can create a lot of trouble for yourself. Real-time systems must respond to an event within a fixed amount of time. Sometimes a high priority process needs to stop to get access to something that a low priority process has. However, a start of a medium priority process can block the low priority process, and as a result, the medium priority task will block the high priority task.

For example, let's say we have a high-priority button-press interrupt and low-priority main loop. When the main function accesses button press, it turns off the button-press interrupt to avoid a race condition. 

The highest priority is the most important thing that a processor should be doing. Unfortunately, there are many ways for a processor to get into the position in which running a task is not the highest priority. 



Comments

Popular Posts