BEC601 Module 3 Final
BEC601 Module 3 Final
Prepared By:
Dr. Madhumathy P
Associate Professor,
Department of ECE
RVITM, Bengaluru – 560076
Email: [email protected]
RV Institute of Technology and Management®
Module 3
RTOS and IDE for Embedded System Design
Syllabus
Operating System basics, Types of operating systems, Task, process and threads (Only POSIX
Threads with an example program), Thread preemption, Multiprocessing and Multitasking, Task
Communication (without any program), Task synchronization issues – Racing and Deadlock,
Concept of Binary and counting semaphores (Mutex example without any program), How to
choose an RTOS, Integration and testing of Embedded hardware and firmware, Embedded
system Development Environment – Block diagram (excluding Keil), Disassembler/decompiler,
simulator, emulator and debugging techniques, target hardware debugging, boundary scan.
An Operating System (OS) is an interface between computer user and computer hardware. An
operating system is software which performs all the basic tasks like file management, memory
management, process management, handling input and output, and controlling peripheral devices
such as disk drives and printers. Some popular Operating Systems include Linux Operating
System, Windows Operating System, VMS, OS/400, AIX, z/OS, etc.
5.1 DEFINITION
An operating system is a program that acts as an interface between the user and the computer
hardware and controls the execution of all kinds of programs.
Following are some of important functions of an operating System.
Memory Management
Processor Management
Device Management
File Management
Security
Control over system performance
Job accounting
Error detecting aids
Coordination between other software and users
An Operating System provides services to both the users and to the programs. It provides
programs an environment to execute.
It provides users the services to execute the programs in a convenient manner.
Following are a few common services provided by an operating system: Program execution
I/O operations
File System manipulation
Communication
Error Detection
Resource Allocation
Protection
1. Process Management:
• A program does nothing unless their instructions are executed by a CPU.A process is a program
in execution. A time shared user program such as a complier is a process. A word processing
program being run by an individual user on a pc is a process.
• A system task such as sending output to a printer is also a process. A process needs certain
resources including CPU time, memory files & I/O devices to accomplish its task.
• These resources are either given to the process when it is created or allocated to it while it is
running. The OS is responsible for the following activities of process management.
• Creating & deleting both user & system processes.
• Suspending & resuming processes.
• Providing mechanism for process synchronization.
• Providing mechanism for process communication.
• Providing mechanism for deadlock handling.
3. File Management:
File management is one of the most important components of an OS computer can store
information on several different types of physical media magnetic tape, magnetic disk & optical
disk are the most common media. Each medium is controlled by a device such as disk drive or tape
drive those has unique characteristics. These characteristics include access speed, capacity, data
transfer rate & access method (sequential or random).For convenient use of computer system the
OS provides a uniform logical view of information storage. The OS abstracts from the physical
properties of its storage devices to define a logical storage unit the file. A file is collection of
related information defined by its creator. The OS is responsible for the following activities of file
management.
• Creating & deleting files.
• Creating & deleting directories.
• Supporting primitives for manipulating files & directories.
• Mapping files into secondary storage.
• Backing up files on non-volatile media.
Networking:- A distributed system is a collection of processors that don’t share memory peripheral
devices or a clock. Each processor has its own local memory & clock and the processor
communicate with one another through various communication lines such as high speed buses or
networks. The processors in the system are connected through communication networks which are
configured in a number of different ways. The communication network design must consider
message routing & connection strategies are the problems of connection & security.
Protection or security-If a computer system has multi users & allow the concurrent execution of
multiple processes then the various processes must be protected from one another’s activities. For
that purpose, mechanisms ensure that files, memory segments, CPU & other resources can be
operated on by only those processes that have gained proper authorization from the OS.
Command interpretation:
One of the most important functions of the OS is connected interpretation where it acts as the
interface between the user & the OS.
to modify the sensors inputs. System that controls scientific experiments, medical imaging systems
and some display systems are real time systems. The disadvantages of real time system are:
a. A real time system is considered to function correctly only if it returns the correct result within
the time constraints.
b. Secondary storage is limited or missing instead data is usually stored in short term memory or
ROM.
c. Advanced OS features are absent. Real time system is of two types such as
• Hard real time systems: It guarantees that the critical task has been completed on time. The
sudden task is takes place at a sudden instant of time.
• Soft real time systems: It is a less restrictive type of real time system where a critical task gets
priority over other tasks and retains that priority until it computes. These have more limited utility
than hard real time systems. Missing an occasional deadline is acceptable e.g. QNX, VX works.
Digital audio or multimedia is included in this category. It is a special purpose OS in which there
are rigid time requirements on the operation of a processor. A real time OS has well defined fixed
time constraints. Processing must be done within the time constraint or the system will fail. A real
time system is said to function correctly only if it returns the correct result within the time
constraint. These systems are characterized by having time as a key parameter.
The kernel of a Real Time Operating System is referred as Real Time kernel. In complement to
the conventional OS kernel, the Real Time kernel is highly specialized and it contains only the
minimal set of services required for running the user applications/tasks. The basic functions of a
Real Time kernel are
a) Task/Process management
b) Task/Process scheduling
c) Task/Process synchronization
d) Error/Exception handling
e) Memory Management
f) Interrupt handling
g) Time management
Real Time Kernel Task/Process Management: Deals with setting up the memory space for the tasks,
loading the task’s code into the memory space, allocating system resources, setting up a Task
Control Block (TCB) for the task and task/process termination/deletion. A Task Control Block
(TCB) is used for holding the information corresponding to a task. TCB usually contains the
following set of information
Task ID: Task Identification Number
Task State: The current state of the task. (E.g. State= ‘Ready’ for a task which is ready to
execute)
Task Type: Task type. Indicates what is the type for this task. The task can be a hard real
time or soft real time or background task.
Task Priority: Task priority (E.g. Task priority =1 for task with priority =1)
Task Context Pointer: Context pointer. Pointer for context saving
Task Memory Pointers: Pointers to the code memory, data memory and stack memory for
the task
Task System Resource Pointers: Pointers to system resources (semaphores, mutex etc) used
by the task
Task Pointers: Pointers to other TCBs (TCBs for preceding, next and waiting tasks)
Other Parameters Other relevant task parameters The parameters and implementation of the
TCB is kernel dependent. The TCB parameters vary across different kernels, based on the
task management implementation
Task/Process Scheduling: Deals with sharing the CPU among various tasks/processes. A kernel
application called ‘Scheduler’ handles the task scheduling. Scheduler is nothing but an algorithm
implementation, which performs the efficient and optimal scheduling of tasks to provide a
deterministic behavior
Task/Process Synchronization: Deals with synchronizing the concurrent access of a resource, which
is shared across multiple tasks and the communication between various tasks.
Error/Exception handling: Deals with registering and handling the errors occurred/exceptions raised
during the execution of tasks. Insufficient memory, timeouts, deadlocks, deadline missing, bus error,
divide by zero, unknown instruction execution etc, are examples of errors/exceptions.
Errors/Exceptions can happen at the kernel level services or at task level. Deadlock is an example
for kernel level exception, whereas timeout is an example for a task level exception. The OS kernel
gives the information about the error in the form of a system call (API)
Memory Management:
The memory management function of an RTOS kernel is slightly different compared to
the General Purpose Operating Systems
The memory allocation time increases depending on the size of the block of memory needs
to be allocated and the state of the allocated memory block (initialized memory block
consumes more allocation time than uninitialized memory block)
Since predictable timing and deterministic behavior are the primary focus for an RTOS,
RTOS achieves this by compromising the effectiveness of memory allocation
RTOS generally uses ‘block’ based memory allocation technique, instead of the usual
dynamic memory allocation techniques used by theGPOS.
RTOS kernel uses blocks of fixed size of dynamic memory and the block is allocated for
a task on a need basis. The blocks are stored in a ‘Free buffer Queue’.
Most of the RTOS kernels allow tasks to access any of the memory blocks without any
memory protection to achieve predictable timing and avoid the timing overheads
RTOS kernels assume that the whole design is proven correct and protection is
unnecessary. Some commercial RTOS kernels allow memory protection as optional and
the kernel enters a fail-safe mode when an illegal memory access occurs
The memory management function of an RTOS kernel is slightly different compared to
the General Purpose Operating Systems
A few RTOS kernels implement Virtual Memory concept for memory allocation if the
system supports secondary memory storage (like HDD and FLASH memory) In the ‘block’
based memory allocation, a block of fixed memory is always allocated for tasks on need
basis and it is taken as a unit. Hence, there will not be any memory fragmentation issues.
The memory allocation can be implemented as constant functions and thereby it consumes
fixed amount of time for memory allocation. This leaves the deterministic behavior of the
RTOS kernel untouched.
Interrupt Handling:
Interrupts inform the processor that an external device or an associated task requires
immediate attention of the CPU.
Interrupts can be either Synchronous or Asynchronous.
Interrupts which occurs in sync with the currently executing task is known as Synchronous
interrupts. Usually the software interrupts fall under the Synchronous Interrupt category.
Divide by zero, memory segmentation error etc are examples of Synchronous interrupts.
For synchronous interrupts, the interrupt handler runs in the same context of the
interrupting task.
Asynchronous interrupts are interrupts, which occurs at any point of execution of any task,
and are not in sync with the currently executing task.
The interrupts generated by external devices (by asserting the Interrupt line of the
processor/controller to which the interrupt line of the device is connected) connected to the
processor/controller, timer overflow interrupts, serial data reception/ transmission
interrupts etc are examples for asynchronous interrupts.
For asynchronous interrupts, the interrupt handler is usually written as separate task
(Depends on OS Kernel implementation) and it runs in different context. Hence, a context
switch happens while handling the asynchronous interrupts.
Priority levels can be assigned to the interrupts and each interrupts can be enabled or
disabled individually.
Most of the RTOS kernel implements ‘Nested Interrupts’ architecture. Interrupt nesting
allows the pre-emption (interruption) of an Interrupt Service Routine (ISR), servicing an
interrupt, by a higher priority interrupt.
Time Management:
Interrupts inform the processor that an external device or an associated task requires
immediate attention of the CPU.
Accurate time management is essential for providing precise time reference for all
applications
The time reference to kernel is provided by a high-resolution Real Time Clock (RTC)
hardware chip (hardware timer)
The hardware timer is programmed to interrupt the processor/controller at a fixed rate. This
timer interrupt is referred as ‘Timer tick’
The ‘Timer tick’ is taken as the timing reference by the kernel. The ‘Timer tick’ interval
may vary depending on the hardware timer. Usually the ‘Timer tick’ varies in the
microseconds range
The time parameters for tasks are expressed as the multiples of the ‘Timer tick’
The System time is updated based on the ‘Timer tick’
If the System time register is 32 bits wide and the ‘Timer tick’ interval is 1microsecond,
the System time register will reset in 232 * 10-6/ (24 * 60 * 60) = 49700 Days =~ 0.0497
Days = 1.19 Hours
If the ‘Timer tick’ interval is 1 millisecond, the System time register will reset in 232 * 10-
3 / (24 * 60 * 60) = 497 Days = 49.7 Days =~ 50 Days the ‘Timer tick’ interrupt is handled
by the ‘Timer Interrupt’ handler of kernel.
5.6.1 Task
Task is a piece of code or program that is separate from another task and can be executed
Task States
In an operation system there are always multiple tasks. At a time only one task can be executed.
This means that there are other tasks which are waiting their turn to be executed. Depending upon
execution or not a task may be classified into three states as depicted in Figure 5.1:
• Running state - Only one task can actually be using the processor at a given time that task is said
to be the “running” task and its state is “running state”. No other task can be in that same state at
the same time
• Ready state - Tasks that are not currently using the processor but are ready to run are in the
“ready” state. There may be a queue of tasks in the ready state.
• Waiting state - Tasks that are neither in running nor ready state but that are waiting for some
event external to themselves to occur before they can go for execution on are in the “waiting” state.
Difference between process & program: A program by itself is not a process. A program in
execution is known as a process. A program is a passive entity, such as the contents of a file stored
on disk whereas process is an active entity with a program counter specifying the next instruction
to execute and a set of associated resources may be shared among several process with some
scheduling algorithm being used to determinate when the stop work on one process and service a
different one.
Process state: As a process executes, it changes state. The state of a process is defined by the
correct activity of that process as depicted in Figure 5.2. Each process may be in one of the
following states.
• New: The process is being created.
• Ready: The process is waiting to be assigned to a processor.
• Running: Instructions are being executed.
• Waiting: The process is waiting for some event to occur.
• Terminated: The process has finished execution.
Many processes may be in ready and waiting state at the same time. But only one process can be
running on any processor at any instant.
Scheduling queues: As processes enter the system, they are put into a job queue. This queue
consists of all process in the system. The process that are residing in main memory and are ready
& waiting to execute or kept on a list called ready queue.
Process control block: Each process is represented in the OS by a process control block. It is also
known as task control block.
A process control block contains many pieces of information associated with a specific process.
It includes the following information’s.
Process state: The state may be new, ready, running, waiting or terminated state.
Program counter: it indicates the address of the next instruction to be executed for this
purpose.
CPU registers: The registers vary in number & type depending on the computer
architecture. It includes accumulators, index registers, stack pointer & general purpose
registers, plus any condition- code information must be saved when an interrupt occurs to
allow the process to be continued correctly after- ward.
CPU scheduling information: This information includes process priority pointers to
scheduling queues & any other scheduling parameters.
Memory management information: This information may include such information as the
value of the bar & limit registers, the page tables or the segment tables, depending upon the
memory system used by the operating system.
Accounting information: This information includes the amount of CPU and real time used,
time limits, account number, job or process numbers and so on.
I/O Status Information: This information includes the list of I/O devices allocated to
this process, a list of open files and so on. The PCB simply serves as the repository
for any information that may vary from process to process
5.6.3 Threads
Applications use concurrent processes to speed up their operation. However, switching between
processes within an application incurs high process switching overhead because the size of the
process state information is large, so operating system designers developed an alternative model
of execution of a program, called a thread, which could provide concurrency within an application
with less overhead
To understand the notion of threads, let us analyze process switching overhead and see where a
saving can be made. Process switching overhead has two components:
Execution related overhead: The CPU state of the running process has to be saved and the
CPU state of the new process has to be loaded in the CPU. This overhead is unavoidable.
Resource-use related overhead: The process context also has to be switched. It involves
switching of the information about resources allocated to the process, such as memory and
files, and interaction of the process with other processes. The large size of this information
adds to the process switching overhead.
Consider child processes Pi and Pj of the primary process of an application. These processes inherit
the context of their parent process. If none of these processes have allocated any resources of their
own, their context is identical; their state information differs only in their CPU states and contents
of their stacks. Consequently, while switching between Pi and Pj, much of the saving and loading
of process state information is redundant. Threads exploit this feature to reduce the switching
overhead.
A process creates a thread through a system call. The thread does not have resources of its own,
so it does not have a context; it operates by using the context of the process, and accesses the
resources of the process through it. We use the phrases ―thread(s) of a process and ―parent
process of a thread to describe the relationship between a thread and the process whose context it
uses.
Figure 5.4 illustrates the relationship between threads and processes. In the abstract view of Figure
5.4 process Pi has three threads, which are represented by wavy lines inside the circle representing
process Pi. Figure 5.4 shows an implementation arrangement. Process Pi has a context and a PCB.
Each thread of Pi is an execution of a program, so it has its own stack and a thread control block
(TCB), which is analogous to the PCB and stores the following information:
1. Thread scheduling information—thread id, priority and state.
2. CPU state, i.e., contents of the PSW and GPRs.
3. Pointer to PCB of parent process.
4. TCB pointer, which is used to make lists of TCBs for scheduling.
POSIX Threads
POSIX Threads, usually referred to as pthreads, is an execution model that exists independently
from a language, as well as a parallel execution model. It allows a program to control multiple
different flows of work that overlap in time. Each flow of work is referred to as a thread, and
creation and control over these flows is achieved by making calls to the POSIX Threads API.
POSIX Threads is an API defined by the standard POSIX.1c, Threads extensions (IEEE Std
1003.1c-1995).
Implementations of the API are available on many Unix-like POSIX-conformant operating
systems such as FreeBSD, NetBSD, OpenBSD, Linux, Mac OS X, Android[1] and Solaris,
VI- Semester, Embedded Systems Page 12 of 28
RV Institute of Technology and Management®
typically bundled as a library libpthread. DR-DOS and Microsoft Windows implementations also
exist: within the SFU/SUA subsystem which provides a native implementation of a number of
POSIX APIs, and also within third-party packages such as pthreads-w32,[2] which implements
pthreads on top of existing Windows API.
Program 5.1
Shortest Job First Scheduling (SJF) Algorithm: This algorithm associates with each process if
the CPU is available. This scheduling is also known as shortest next CPU burst, because the
scheduling is done by examining the length of the next CPU burst of the process rather than its
total length.
Round Robin Scheduling Algorithm: This type of algorithm is designed only for the time sharing
system. It is similar to FCFS scheduling with preemption condition to switch between processes.
A small unit of time called quantum time or time slice is used to switch between the processes.
The average waiting time under the round robin policy is quiet long.
Consider the following example: Time Slice = 1 millisecond.
Process CPU
time
P1 3
P2 5
P3 2
P4 4
P1 P2 P3 P4 P1 P2 P3 P4 P1 P2 P4 P2 P4 P2
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
The waiting time for process
P1 = 0 + (4 – 1) + (8 – 5) = 0 + 3 + 3 = 6
P2 = 1 + (5 – 2) + (9 – 6) + (11 – 10) + (12 – 11) + (13 – 12) = 1 + 3 + 3 + 1 + 1 + 1 = 10
P3 = 2 + (6 – 3) = 2 + 3 = 5
P4 = 3 + (7 – 4) + (10 – 8) + (12 – 11) = 3 + 3 + 2 + 1 = 9
The average waiting time = (6 + 10 + 5 + 9)/4 = 7.5
Priority based preemptive scheduling algorithm is same as that of the non-preemptive priority based
scheduling except for the switching of execution between tasks. In preemptive scheduling, any high
priority process entering the ‘Ready’ queue is immediately scheduled for execution whereas in the
non-preemptive scheduling any high priority process entering the ‘Ready’ queue is scheduled only
after the currently executing process completes its execution or only when it voluntarily relinquishes
the CPU. The priority of a task/ process in preemptive scheduling is indicated in the same way as
that of the mechanism adopted for non- preemptive multitasking.
figure 5.5 shows two processes and their address spaces. The yellow rectangle is a shared memory
attached to both address spaces and both process 1 and process 2 can have access to this shared
memory as if the shared memory is part of its own address space. In some sense, the original
address space is "extended" by attaching this shared memory.
Co-operating Processes: In the co-operating interaction model one process requires the inputs from
other processes to complete its execution.
Competing Processes: The competing processes do not share anything among themselves but they
share the system resources. The competing processes compete for the system resources such as fi le,
display device, etc. Co-operating processes exchanges information and communicate through the
following methods.
Co-operation through Sharing: The co-operating process exchange data through some shared
resources.
Co-operation through Communication: No data is shared between the processes. But they
communicate for synchronization.
A. Shared Memory
Shared Memory Processes share some area of the memory to communicate among them . Information
to be communicated by the process is written to the shared memory area. Other processes which
require this information can read the same from the shared memory area.
Definition - What does Pipe mean?
A pipe is a method used to pass information from one program process to another. Unlike other
types of inter-process communication, a pipe only offers one-way communication by passing a
parameter or output from one process to another. The information that is passed through the pipe
is held by the system until it can be read by the receiving process. also known as a FIFO for its
behavior.
In computing, a named pipe (also known as a FIFO) is one of the methods for intern- process
communication.
It is an extension to the traditional pipe concept on Unix. A traditional pipe is “unnamed”
and lasts only as long as the process.
A named pipe, however, can last as long as the system is up, beyond the life of the process.
It can be deleted if no longer used.
Usually a named pipe appears as a file, and generally processes attach to it for inter- process
communication. A FIFO file is a special kind of file on the local storage which allows two
or more processes to communicate with each other by reading/writing to/from this file.
A FIFO special file is entered into the file system by calling mkfifo() in C. Once we have created
a FIFO special file in this way, any process can open it for reading or writing, in the same way as
an ordinary file. However, it has to be open at both ends simultaneously before you can proceed
to do any input or output operations on it.
B. Message passing:
Message passing can be synchronous or asynchronous. Synchronous message passing
systems require the sender and receiver to wait for each other while transferring the
message. In asynchronous communication the sender and receiver do not wait for each
other and can carry on their own computations while transfer of messages is being done.
The advantage to synchronous message passing is that it is conceptually less complex.
Synchronous message passing is analogous to a function call in which the message sender
is the function caller and the message receiver is the called function. Function calling is
easy and familiar. Just as the function caller stops until the called function completes, the
sending process stops until the receiving process completes.
This alone makes synchronous message unworkable for some applications. For example,
if synchronous message passing would be used exclusively, large, distributed systems
generally would not perform well enough to be usable. Such large, distributed systems may
need to continue to operate while some of their subsystems are down; subsystems may
need to go offline for some kind of maintenance, or have times when subsystems are not
open to receiving input from other systems.
Message queue:
Message queues provide an asynchronous communications protocol, meaning that the sender
and receiver of the message do not need to interact with the message queue at the same time.
Messages placed onto the queue are stored until the recipient retrieves them. Message queues have
implicit or explicit limits on the size of data that may be transmitted in a single message and the
number of messages that may remain outstanding on the queue.
Many implementations of message queues function internally: within an operating system
or within an application. Such queues exist for the purposes of that system only. Other
implementations allow the passing of messages between different computer systems, potentially
connecting multiple applications and multiple operating systems. These message queuing systems
typically provide enhanced resilience functionality to ensure that messages do not get "lost" in the
event of a system failure. Examples of commercial implementations of this kind of message
queuing software (also known as message- oriented middleware) include IBM WebSphere MQ
(formerly MQ Series) and Oracle Advanced Queuing (AQ). There is a Java standard called Java
Message Service, which has several proprietary and free software implementations.
Implementations exist as proprietary software, provided as a service, open source software, or a
hardware-based solution.
Mail box: Mailboxes provide a means of passing messages between tasks for data exchange or
task synchronization. For example, assume that a data gathering task that produces data needs to
convey the data to a calculation task that consumes the data. This data gathering task can convey
the data by placing it in a mailbox and using the SEND command; the calculation task uses
RECEIVE to retrieve the data. If the calculation task consumes data faster than the gatherer
produces it, the tasks need to be synchronized so that only new data is operated on by the
calculation task. Using mailboxes achieves synchronization by forcing the calculation task to wait
for new data before it operates. The data producer puts the data in a mailbox and SENDs it. The
data consumer task calls RECEIVE to check whether there is new data in the mailbox; if not,
RECEIVE calls Pause() to allow other tasks to execute while the consuming task is waiting for the
new data.
Signaling: Signals are commonly used in POSIX systems. Signals are sent to the current process
telling it what it needs to do, such as, shutdown, or that it has committed an exception. A process
has several signal-handlers which execute code when a relevant signal is encountered. The ANSI
header for these tasks is <signal.h>, which includes routines to allow signals to be raised and read.
Signals are essentially software interrupts. It is possible for a process to ignore most signals, but
some cannot be blocked. Some of the common signals are Segmentation Violation (reading or
writing memory that does not belong to this process), Illegal Instruction (trying to execute
something that is not a proper instruction to the CPU), Halt (stop processing for the moment),
Continue (used after a Halt), Terminate (clean up and quit), and Kill (quit now without cleaning
up).
RPC: Remote Procedure Call (RPC) is a powerful technique for constructing distributed, client-
server based applications. It is based on extending the conventional local procedure calling, so that
the called procedure need not exist in the same address space as the calling procedure. The two
processes as depicted in Figure 5.8 may be on the same system, or they may be on different systems
with a network connecting them.
The decision of an RTOS for an embedded design is very critical. A lot of factors need to be
analyzed carefully before making a decision on the selection of an RTOS. These factors can be
either
1. Functional
2. Non-functional requirements
.
A. Functional Requirements:
Processor support: It is not necessary that all RTOS’s support all kinds of processor
architectures. It is essential to ensure the processor support by the RTOS
Memory Requirements: The RTOS requires ROM memory for holding the OS files and it is
normally stored in a non-volatile memory like FLASH.
OS also requires working memory RAM for loading the OS service. Since embedded systems
are memory constrained, it is essential to evaluate the minimal RAM and ROM requirements
for the OS under consideration.
.Real-Time Capabilities: It is not mandatory that the OS for all embedded systems need to be
RealTime and all embedded OS’s are ‘Real-Time’ in behavior.The Task/process scheduling
policies plays an important role in the Real Time behavior of an OS.
Kernel and Interrupt Latency: The kernel of the OS may disable interrupts while executing
certain services and it may lead to interrupt latency. For an embedded system whose response
requirements are high, thislatency should be minimal. Inter process Communication (IPC) and
Task Synchronization: The implementation of IPC and Synchronization is OS kernel
dependent.
Modularization Support: Most of the OS’s provide a bunch of features. It is very useful if the
OS supports modularization where in which the developer can choose the essential modules
and re-compile the OS image for functioning.
Support for Networking and Communication: The OS kernel may provide stack
implementation and driver support for a bunch of communication interfaces and networking.
Ensure that the OS under consideration provides support for all the interfaces required by the
embedded product.
Development Language Support: Certain OS’s include the run time libraries required for
running applications written in languages like JAVA and C++. The OS may include these
components as built-in component, if not , check the availability of the same from a third
party.
B. Non-Functional Requirements:
Custom Developed or Off the Shelf: It is possible to go for the complete development of an
OS suiting the embedded system needs or use an off the shelf, readily availableOS. It may be
possible to build the required features by customizing an open source OS. The decision on
which to select is purely dependent on the development cost, licensing fees for the OS,
development time and availability of skilled resources.
Cost: The total cost for developing or buying the OS and maintaining it in terms of
commercial product and custom build needs to be evaluated before taking a decision on the
selection of OS.
Development and Debugging tools Availability: The availability of development and
debugging tools is a critical decision making factor in the selection of an OS for embedded
design. Certain OS’s may be superior in performance, but the availability of tools for
supporting the development may be limited.
Ease of Use: How easy it is to use a commercial RTOS is another important feature that needs
to be considered in the RTOS selection.
After Sales: For a commercial embedded RTOS, after sales in the form of e-mail, on-call
services etc. for bug fixes, critical patch updates and support for production issues etc. should
be analyzed thoroughly
A. Racing
Racing or Race condition is the situation in which multiple processes compete (race) each other to
access and manipulate shared data concurrently. In a Race condition the final value of the shared
data depends on the process which acted on the data finally.
Process B increments the shared variable ‘counter’ in the middle of the operation where
Process A tries to increment it. When Process A gets the CPU time for execution, it starts from the
point where it got interrupted (If Process B is also using the same registers eax and ebp for executing
counter++; instruction, the original content of these registers will be saved as part of the context
saving and it will be retrieved back as part of context retrieval, when process A gets the CPU for
execution.
Hence the content of eax and ebp remains intact irrespective of context switching). Though
the variable counter is incremented by Process B, Process A is unaware of it and it increments the
variable with the old value. This leads to the loss of one increment for the variable counter. This
problem occurs due to non-atomic§ operation on variables. This issue wouldn’t have been occurred
if the underlying actions corresponding to the program statement counter++; is fi nished in a single
CPU execution cycle. The best way to avoid this situation is make the access and modifi cation of
shared variables mutually exclusive; meaning when one process accesses a shared variable, prevent
the other processes from accessing it.
B. Deadlock
A race condition produces incorrect results whereas a deadlock condition creates a situation
where none of the processes are able to make any progress in their execution, resulting in a set of
deadlocked processes
A race condition produces incorrect results whereas a deadlock condition creates a situation where
none of the processes are able to make any progress in their execution, resulting in a set of
deadlocked processes. In its simplest form ‘deadlock’ is the condition in which a process is waiting
for a resource held by another process which is waiting for a resource held by the first process. To
elaborate: Process A holds a resource x and it wants a resource y held by Process B. Process B is
currently holding resource y and it wants the resource x which is currently held by Process A. Both
hold the respective resources and they compete each other to get the resource held by the respective
processes. The result of the competition is ‘deadlock’. None of the competing process will be able
to access the resources held by other processes since they are locked by the respective processes (If
a mutual exclusion policy is implemented for shared resource access, the resource is locked by the
process which is currently accessing it).
Mutual Exclusion: The criteria that only one process can hold a resource at a time. Meaning
processes should access shared resources with mutual exclusion. Typical example is the accessing
of display hardware in an embedded device
Hold and Wait: The condition in which a process holds a shared resource by acquiring the lock
controlling the shared access and waiting for additional resources held by other processes.
No Resource Preemption: The criteria that operating system cannot take back a resource from a
process which is currently holding it and the resource can only be released voluntarily by the process
holding it.
Circular Wait: A process is waiting for a resource which is currently held by another process which
in turn is waiting for a resource held by the first process. In general, there exists a set of waiting
process P0, P1 … Pn with P0 is waiting for a resource held by P1 and P1 is waiting for a resource
held by P0, …, Pn is waiting for a resource held by P0 and P0 is waiting for a resource held by Pn
and so on… This forms a circular wait queue. ‘Deadlock’ is a result of the combined occurrence of
these four conditions listed above. These conditions are first described by E. G. Coffman in 1971
and it is popularly known as Coffman conditions.
Deadlock Handling A smart OS may foresee the deadlock condition and will act proactively to
avoid such a situation. Now if a deadlock occurred, how the OS responds to it? The reaction to
deadlock condition by OS is nonuniform. The OS may adopt any of the following techniques to
detect and prevent deadlock conditions.
Ignore Deadlocks: Always assume that the system design is deadlock free. This is acceptable for
the reason the cost of removing a deadlock is large compared to the chance of happening a deadlock.
UNIX is an example for an OS following this principle. A life critical system cannot pretend that it
is deadlock free for any reason.
Detect and Recover: This approach suggests the detection of a deadlock situation and recovery
from it. This is similar to the deadlock condition that may arise at a traffic junction. When the
vehicles from different directions compete to cross the junction, deadlock (traffic jam) condition is
resulted. Once a deadlock (traffic jam) is happened at the junction, the only solution is to back up
the vehicles from one direction and allow the vehicles from opposite direction to cross the junction.
If the traffic is too high, lots of vehicles may have to be backed up to resolve the traffic jam. This
technique is also known as ‘back up cars’ technique. Operating systems keep a resource graph in
their memory. The resource graph is updated on each resource request and release. A deadlock
condition can be detected by analysing the resource graph by graph analyser algorithms. Once a
deadlock condition is detected, the system can terminate a process or preempt the resource to break
the deadlocking cycle.
Avoid Deadlocks: Deadlock is avoided by the careful resource allocation techniques by the
Operating System. It is similar to the traffic light mechanism at junctions to avoid the traffic jams.
Prevent Deadlocks: Prevent the deadlock condition by negating one of the four conditions
favouring the deadlock situation. ∑ Ensure that a process does not hold any other resources when it
requests a resource.
Livelock The Livelock condition is similar to the deadlock condition except that a process in
livelock condition changes its state with time. While in deadlock a process enters in wait state for a
resource and continues in that state forever without making any progress in the execution, in a
livelock condition a process always does something but is unable to make any progress in the
execution completion.
Starvation In the multitasking context, starvation is the condition in which a process does not get
the resources required to continue its execution for a long time. As time progresses the process starves
on resource. Starvation may arise due to various conditions like byproduct of preventive measures of
deadlock, scheduling policies favouring high priority tasks and tasks with shortest execution time, etc
Semaphore
Semaphore is a sleep and wakeup based mutual exclusion implementation for shared
resource access.
Semaphore is a system resource and the process which wants to access the shared resource
can first acquire this system object to indicate the other processes which wants the shared
resource that the shared resource is currently acquired by it.
The resources which are shared among a process can be either for exclusive use by a process
or for using by several processes at a time.
The display device of an embedded system is a typical example for the shared resource
which needs exclusive access by a process.
The Hard disk (secondary storage) of a system is a typical example for sharing the resource
among a limited number of multiple processes. Various processes can access the different
sectors of the hard-disk concurrently.
Based on the implementation of the sharing limitation of the shared resource, semaphores
are classified into two; namely ‘Binary Semaphore’ and ‘ Counting Semaphore’.
The binary semaphore provides exclusive access to shared resource by allocating the
resource to a single process at a time and not allowing the other processes to access it when
it is being owned by a process. The implementation of binary semaphore is OS kernel
dependent. Under certain OS kernel it is referred as mutex.
Unlike a binary semaphore, the ‘Counting Semaphore’ limits the access of resources by a
fixed number of processes/threads. ‘Counting Semaphore’ maintains a count between zero
and a maximum value.
It limits the usage of the resource to the maximum value of the count supported by it. The
state of the counting semaphore object is set to ‘signalled’ when the count of the object is
greater than zero. The count associated with a ‘Semaphore object’ is decremented by one
when a process/thread acquires it and the count is incremented by one when a process/thread
releases the ‘Semaphore object’.
The state of the ‘Semaphore object’ is set to non-signalled when the semaphore is acquired
by the maximum number of processes/threads that the semaphore can support (i.e. when the
count associated with the ‘Semaphore object’ becomes zero). A real world example for the
counting semaphore concept is the dormitory system for accommodation . A dormitory
contains a fixed number of beds (say 5) and at any point of time it can be shared by the
maximum number of users supported by the dormitory.
If a person wants to avail the dormitory facility, he/she can contact the dormitory caretaker
for checking the availability. If beds are available in the dorm the caretaker will hand over
the keys to the user. If beds are not available currently, the user can register his/her name to
get notifications when a slot is available.
Those who are availing the dormitory shares the dorm facilities like TV, telephone, toilet,
etc. When a dorm user vacates, he/she gives the keys back to the caretaker. The caretaker
informs the users, who booked in advance, about the dorm availability
Integration of hardware and firmware deals with the embedding of firmware into the target hardware
board. It is the process of ‘Embedding Intelligence’ to the product. The embedded
processors/controllers used in the target board may or may not have built in code memory.
Out-of-Circuit Programming
The sequence of operations for embedding the firmware with a programmer is listed below.
1. Connect the programming device to the specifi ed port of PC (USB/COM port/parallel
port)
2. Power up the device (Most of the programmers incorporate LED to indicate Device
power up. Ensure that the power indication LED is ON)
3. Execute the programming utility on the PC and ensure proper connectivity is
established between PC and programmer. In case of error, turn off device power and
try connecting it again
4. Unlock the ZIF socket by turning the lock pin
5. Insert the device to be programmed into the open socket as per the insert diagram
shown on the programmer
6. Lock the ZIF socket
With ISP, programming is done ‘within the system’, meaning the fi rmware is embedded into the
target device without removing it from the target board. It is the most fl exible and easy way of fi
rmware embedding.
Devices with SPI In System Programming support contains a built-in SPI interface and the on-chip
EEPROM or FLASH memory is programmed through this interface. The primary I/O lines involved
in SPI – In System Programming are listed below.
MOSI – Master Out Slave In
MISO – Master In Slave Out
SCK – System Clock
RST – Reset of Target Device
GND – Ground of Target Device
In Application Programming (IAP) is a technique used by the firmware running on the target device
for modifying a selected portion of the code memory. It is not a technique for first time embedding
of user written firmware. It modifies the program code memory under the control of the embedded
application. Updating calibration data, look-up tables, etc., which are stored in code memory, are
typical examples of IAP
is over and the firmware achieved operational stability, the firmware fi les can be sent to the chip
fabricator to embed it into the code memory
One aim of the IDE is to reduce the configuration necessary to piece together multiple development
utilities, instead providing the same set of capabilities as a cohesive unit. Reducing that setup time
can increase developer productivity, in cases where learning to use the IDE is faster than manually
integrating all of the individual tools. Tighter integration of all development tasks has the potential
to improve overall productivity beyond just helping with setup tasks. For example, code can be
continuously parsed while it is being edited, providing instant feedback when syntax errors are
introduced. That can speed learning a new programming language and its associated libraries.
Some IDEs are dedicated to a specific programming language, allowing a feature set that most
closely matches the programming paradigms of the language. However, there are many multiple-
language IDEs, such as Eclipse, ActiveState Komodo, IntelliJ IDEA, Oracle JDeveloper,
NetBeans, Codenvy and Microsoft Visual Studio. Xcode, Xojo and Delphi are dedicated to a
closed language or set of programming languages.
While most modern IDEs are graphical, text-based IDEs such as Turbo Pascal were in popular use
before the widespread availability of windowing systems like Microsoft Windows and the X
Window System (X11). They commonly use function keys or hotkeys to execute frequently used
commands or macros.
5.14 DISASSEMBLER/DECOMPILER
Disassembler is a utility program which converts machine codes into target processor specific
Assembly codes/instructions. The process of converting machine codes into Assembly code is
known as ‘Disassembling’. In operation, disassembling is complementary to
assembling/crossassembling. Decompiler is the utility program for translating machine codes into
corresponding high level language instructions. Decompiler performs the reverse operation of
compiler/cross-compiler
A. Simulators
Simulators and emulators are two important tools used in embedded system development. Both
the terms sound alike and are little confusing. Simulator is a software tool used for simulating the
various conditions for checking the functionality of the application firmware. The Integrated
Development Environment (IDE) itself will be providing simulator support and they help in
debugging the firmware for checking its required functionality. In certain scenarios, simulator
refers to a soft model (GUI model) of the embedded product.
Simulator based debugging techniques are simple and straightforward. The major advantages of
simulator based firmware debugging techniques are explained below.
No Need for Original Target Board Simulator based debugging technique is purely software
oriented. IDE’s software support simulates the CPU of the target board. User only needs to know
about the memory map of various devices within the target board and the firmware should be
written on the basis of it. Since the real hardware is not required, firmware development can start
well in advance immediately after the device interface and memory maps are finalised. This saves
development time.
Simulate I/O Peripherals Simulator provides the option to simulate various I/O peripherals.
Using simulator’s I/O support you can edit the values for I/O registers and can be used as the
input/output value in the firmware execution. Hence it eliminates the need for connecting I/O
devices for debugging the firmware.
Simulates Abnormal Conditions With simulator’s simulation support you can input any
desired value for any parameter during debugging the firmware and can observe the control flow
of firmware. It really helps the developer in simulating abnormal operational environment for fi
rmware and helps the firmware developer to study the behaviour of the firmware under abnormal
input conditions.
Deviation from Real Behaviour Simulation-based firmware debugging is always carried out in
a development environment where the developer may not be able to debug the firmware under all
possible combinations of input. Under certain operating conditions we may get some particular
result and it need not be the same when the firmware runs in a production environment.
Lack of Real Timeliness The major limitation of simulator based debugging is that it is not
real-time in behaviour. The debugging is developer driven and it is no way capable of creating a
real time behaviour. Moreover in a real application the I/O condition may be varying or
unpredictable. Simulation goes for simulating those conditions for known values.