Module4: Embedded Firmware Design and Development
Module4: Embedded Firmware Design and Development
The embedded firmware is responsible for controlling the various peripherals of the
embedded hardware and generating response in accordance with the functional
requirements.
Firmware is considered as the master brain of the embedded system.
Imparting intelligence to an Embedded system is a one time process and it can happen at
any stage.
It can be immediately after the fabrication of the embedded hardware or at a later
stage.
For most of the embedded products, the embedded firmware is stored at a permanent
memory (ROM) and they are non-alterable by end users.
Some of the embedded products used in the Control and Instrumentation domain
are adaptive.
Designing embedded firmware requires understanding of the particular embedded product
hardware, like various component interfacing, memory map details, I/O port details,
configuration and register details of various hardware chips used and some programming
language.
Embedded firmware development process starts with the conversion of the firmware
requirements into a program model using modelling tools.
Once the program model is created, the next step is the implementation of the tasks and
actions by capturing the model using a language which is understandable by the target
processor/controller.
The firmware design approaches for embedded product is purely dependent on the
complexity of the functions to be performed, the speed of operation required, etc.
Two basic approaches are used for embedded firmware design:
Super Loop Based Approach (Conventional Procedural Based Design)
Embedded Operating System (OS) Based Approach
The Super Loop based firmware development approach is adopted for applications that
are not time critical and where the response time is not so important.
It is very similar to a conventional procedural programming where the code is executed
task by task.
The task listed at the top of the program code is executed first and the tasks just below the
top are executed after completing the first task.
In a multiple task based system, each task is executed in serial in this approach.
The firmware execution flow for this will be
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Configure the common parameters and perform initialisation for various hardware
components memory, registers, etc.
Start the first task and execute it
Execute the second task
Execute the next task
:
:
Execute the last defined task
Jump back to the first task and follow the same flow
The order in which the tasks to be executed are fixed and they are hard coded in the code
itself.
Also the operation is an infinite loop based approach.
We can visualise the operational sequence listed above in terms of a 'C' program code as
Almost all tasks in embedded applications are non-ending and are repeated infinitely
throughout the operation.
This repetition is achieved by using an infinite loop.
Hence the name 'Super loop based approach’.
The only way to come out of the loop is either a hardware reset or an interrupt assertion.
Advantage of Super Loop Based Approach:
It doesn't require an operating system
There is no need for scheduling which task is to be executed and assigning priority
to each task.
The priorities are fixed and the order in which the tasks to be executed are also
fixed.
Hence the code for performing these tasks will be residing in the code memory
without an operating system image.
Applications of Super Loop Based Approach:
This type of design is deployed in low-cost embedded products and products
where response time is not time critical.
Some embedded products demands this type of approach if some tasks itself are
sequential.
For example, reading/writing data to and from a card using a card reader requires
a sequence of operations like checking the presence of card, authenticating the
operation, reading/writing, etc.
It should strictly follow a specified sequence and the combination of these series
of tasks constitutes a single task-namely data read/write.
A typical example of a 'Super loop based’ product is an electronic video game toy
containing keypad and display unit.
The program running inside the product may be designed in such a way that it
reads the keys to detect whether the user has given any input and if any key press
is detected the graphic display is updated.
The keyboard scanning and display updating happens at a reasonably high rate.
Even if the application misses a key press, it won't create any critical issues; rather
it will be treated as a bug in the firmware.
Drawbacks of Super Loop Based Approach:
Any failure in any part of a single task will affect the total system.
If the program hangs up at some point while executing a task, it will remain
there forever and ultimately the product stops functioning.
Watch Dog Timers (WDTs) can be used to overcome this, but this, in turn,
may cause additional hardware cost and firmware overheads.
Lack of real timeliness.
If the number of tasks to be executed within an application increases, the
time at which each task is repeated also increases.
This brings the probability of missing out some events.
The Embedded Operating System (OS) based approach contains operating systems, which
can be either a General Purpose Operating System (GPOS) or a Real Time Operating
System (RTOS) to host the user written application firmware.
The General Purpose OS (GPOS) based design is very similar to a conventional PC based
application development where the device contains an operating system
(Windows/Unix/Linux, etc. for Desktop PCs) and you will be creating and running user
applications on top of it.
Example of a GPOS used in embedded product development is Microsoft
Windows XP Embedded.
Examples of Embedded products using Microsoft Windows XP OS are Personal
Digital Assistants (PDAs), Hand held devices/Portable devices and Point of Sale
(POS) terminals.
Use of GPOS in embedded products merges the demarcation of Embedded Systems and
general computing systems in terms of OS.
For developing applications on top of the OS, the OS supported APIs are used.
Similar to the different hardware specific drivers, OS based applications also require
'Driver software' for different hardware present on the board to communicate with them.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Real Time Operating System (RTOS) based design approach is employed in embedded
products demanding Real-time response.
RTOS responds in a timely and predictable manner to events.
Real Time operating system contains a Real Time kernel responsible for performing pre-
emptive multitasking, scheduler for scheduling tasks, multiple threads, etc.
A Real Time Operating System (RTOS) allows flexible scheduling of system resources like
the CPU and memory and offers some way to communicate between tasks. 'Windows CE',
'pSOS', 'VxWorks', 'ThreadX', 'MicroC/OS-II’, 'Embedded Linux', 'Symbian’, etc. are
examples of RTOS employed in embedded product development.
Mobile phones, PDAs (Based on Windows CE/Windows Mobile Platforms), handheld
devices, etc. are examples of 'Embedded Products' based on RTOS.
Each source module is written in Assembly and is stored as .src file or .asm file.
Each file can be assembled separately to examine the syntax errors and incorrect assembly
instructions.
On successful assembling of each .src/.asm file a corresponding object file is created with
extension '.obj’.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
The object file does not contain the absolute address of where the generated code
needs to be placed on the program memory and hence it is called a re-locatable
segment.
It can be placed at any code memory location and it is the responsibility. of the
linker/locater to assign absolute address for this module.
Libraries are specially formatted, ordered program collections of object modules that may
be used by the linker at a later time.
Library files are generated with extension '. lib’.
When the linker processes a library, only those object modules in the library that are
necessary to create the program are used.
Library file is some kind of source code hiding technique.
For example, 'LIB51' from Keil Software is an example for a library creator and it
is used for creating library files for A51 Assembler/C51 Compiler for 8051 specific
controllers.
Linker and Locater is another software utility responsible for "linking the various object
modules in a multi-module project and assigning absolute address to each module".
Linker generates an absolute object module by extracting the object modules from the
library, if any, and those obj files created by the assembler, which is generated by
assembling the individual modules of a project.
It is the responsibility of the linker to link any external dependent variables or functions
declared on various modules and resolve the external dependencies among the modules.
An absolute object file or module does not contain any re-locatable code or data.
All code and data reside at fixed memory locations.
The absolute object file is used for creating hex files for dumping into the code memory
of the processor/controller.
'BL51' from Keil Software is an example for a Linker & Locater for A51
Assembler/C51 Compiler for 8051 specific controller.
This is the final stage in the conversion of Assembly language (mnemonics) to machine
understandable language (machine code).
Hex File is the representation of the machine code and the hex file is dumped into the
code memory of the processor/controller.
The hex file representation varies depending on the target processor/controller make.
HEX files are ASCII files that contain a hexadecimal representation of target application.
Hex file is created from the final 'Absolute Object File' using the Object to Hex File
Converter utility.
'OH51' from Keil software is an example for Object to Hex File Converter utility
for A51 Assembler/C51 Compiler for 8051 specific controller.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Also more lines of assembly code are required for performing an action which can
be done with a single instruction in a high-level language like 'C'.
Developer Dependency
Unlike high level languages, there is no common written rule for developing
assembly language based applications.
In assembly language programming, the developers will have the freedom to
choose the different memory location and registers.
Also the programming approach varies from developer to developer depending on
his/her taste.
For example, moving data from a memory location to accumulator can be achieved
through different approaches.
If the approach done by a developer is not documented properly at the
development stage, he/she may not be able to recollect why this approach is
followed at a later stage or when a new developer is instructed to analyse this code,
he/she also may not be able to understand what is done and why it is done.
Hence upgrading an assembly program or modifying it on a later stage is very
difficult.
Non-Portable
Target applications written in assembly instructions are valid only for that
particular family of processors (e.g. Application written for Intel x86 family of
processors) and cannot be re-used for another target processors/controllers (Say
ARM11 family of processors).
If the target processor/controller changes, a complete re-writing of the application
using the assembly instructions for the new target processor/controller is required.
Any high level language (like C, C++ or Java) with a supported cross compiler for the
target processor can be used for embedded firmware development.
The most commonly used high level language for embedded firmware application
development is 'C’.
‘C’ is well defined, easy to use high level language with extensive cross platform
development tool support.
Nowadays cross-compilers for C++ is also emerging out and embedded developers are
making use of C++ for embedded application development.
The various steps involved in high level language based embedded firmware development
is same as that of assembly language based development except that the conversion of
source file written in high level language to object file is done by a cross-compiler.
In Assembly language based development it is carried out by an assembler.
The various steps involved in the conversion of a program written in high level language
to corresponding binary file/machine language is illustrated in the figure.
The program written in any of the high level languages is saved with the corresponding
language extension (.c for C, .cpp for C++ etc).
Any text editor like ‘Notepad' or 'WordPad' from Microsoft or the text editor provided by
an Integrated Development (IDE) tool can be used for writing the program.
Most of the high level languages support modular programming approach and hence we
can have multiple source files called modules written in corresponding high level language.
The source files corresponding to each module is represented by a file with corresponding
language extension.
Translation of high level source code to executable object code is done by across-compiler.
Each high level language should have a cross-compiler for converting the high level source
code into the target processor machine code.
C51 Cross-compiler from Keil software is an example for Cross-compiler used for
'C' language for the 8051 family of microcontroller.
Conversion of each module's source code to corresponding object file is performed by the
cross-compiler.
Rest of the steps involved in the conversion of high level language to target processor's
machine code are same as that of the steps involved in assembly language based
development.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Bare minimal knowledge of the memory organisation and register details of the
target processor in use and syntax of the high level language are the only pre-
requisites for high level language based firmware development.
With high level language, each task can be accomplished by lesser number of lines
of code compared to the target processor/controller specific assembly language
based development.
Developer Independency
The syntax used by most of the high level languages are universal and a program
written in the high level language can easily be understood by a second person
knowing the syntax of the language.
High level languages always instruct certain set of rules for writing the code and
commenting the piece of code.
If the developer strictly adheres to the rules, the firmware will be 100% developer
independent.
Portability
Target applications written in high level languages are converted to target
processor/controller understandable format (machine codes) by a cross-compiler.
An application written in high level language for a particular target processor can
easily be converted to another target processor/controller specific application,
with little or less effort by simply re-compiling/little code modification followed
by recompiling the application for the required target processor/controller,
provided, the cross-compiler has support for the processor/controller selected.
This makes applications written in high level language highly portable.
Little effort may be required in the existing code to replace the target processor
specific files with new header files, register definitions with new ones, etc.
This is the major flexibility offered by high level language based design.
Certain embedded firmware development situations may demand the mixing of high level
language with Assembly and vice versa.
High level language and assembly languages are usually mixed in three ways:
Mixing Assembly Language with High Level Language
Mixing High Level Language with Assembly Language
Inline Assembly programming
Mixing the code written in a high level language like 'C' and Assembly language is useful
in the following scenarios:
The source code is already available in Assembly language and a routine written in
a high level language like 'C' needs to be included to the existing code.
The entire source code is planned in Assembly code for various reasons like
optimised code, optimal performance, efficient code memory utilisation and
proven expertise in handling the Assembly, etc. But some portions of the code may
be very difficult and tedious to code in Assembly. For example, 16-bit
multiplication and division in 8051 Assembly Language.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
To include built in library functions written in 'C' language provided by the cross
compiler. For example, Built in Graphics library functions and String operations
supported by 'C’.
Most often the functions written in 'C' use parameter passing to the function and returns
value/s to the calling functions.
Parameters are passed to the function and values are returned from the function using
CPU registers, stack memory and fixed memory.
Its implementation is cross compiler dependent and it varies across cross compilers.
The special compiler directive SRC generates the Assembly code corresponding to the ‘C’ function
and each lines of the source code is converted to the corresponding Assembly instruction. You can
easily identify the Assembly code generated for each line of the source code since it is implicitly
mentioned in the generated .SRC file. By inspecting this code segments you can find out which
registers are used for holding the variables of the ‘C’ function and you can modify the source code
by adding the assembly routine you want.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Some IDEs may provide interface to target board emulators, Target processor’s/controller’s
Flash memory programmer, etc. and incorporate other software development utilities like
‘Version Control Tool’, ‘Help File for the Development Language’, etc. IDEs can be either
command line based or GUI based.
IDEs used in embedded firmware development are slightly different from the generic IDEs used
for high level language based development for desktop applications. In Embedded Applications,
the IDE is either supplied by the target processor/controller manufacturer or by third party
vendors or as Open Source.
MPLAB is an IDE tool supplied by microchip for developing embedded fi rmware using their
PIC family of microcontrollers.
Cross-compilation is the process of converting a source code written in high level language (like
‘Embedded C’) to a target processor/ controller understandable machine code (e.g. ARM
processor or 8051 microcontroller specific machine code).
The conversion of the code is done by software running on a processor/controller (e.g. x86
processor based PC) which is different from the target processor. The software performing this
operation is referred as the ‘Cross-compiler’.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Listing file is generated during the cross-compilation process and it contains an abundance of
information about the cross compilation process, like cross compiler details, formatted source
text (‘C’ code), assembly code generated from the source file, symbol tables, errors and
warnings detected during the cross-compilation process.
The type of information contained in the list file is cross-compiler specific.
The preprocessor output file generated during cross-compilation contains the preprocessor
output for the preprocessor instructions used in the source file.
Preprocessor output file is used for verifying the operation of macros and conditional
preprocessor directives.
The preprocessor output file is a valid C source file. File extension of preprocessor output file is
cross compiler dependent.
Hex file is the binary executable file created from the source code. The absolute object file
created by the linker/locater is converted into processor understandable binary code.
The utility used for converting an object file to a hex file is known as Object to Hex file
converter. Hex files embed the machine code in a particular format.
The format of Hex file varies across the family of processors/controllers.
Intel HEX and Motorola HEX are the two commonly used hex file formats in embedded
applications.
DISASSEMBLER/DECOMPILER
Disassembler is a utility program which converts machine codes into target processor specifi c
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.
The disassemblers/decompilers for different family of processors/controllers are different.
Disassemblers/Decompilers are available as either freeware tools readily available for free
download from internet or as commercial tools.
It is not possible for a disassembler/decompiler to generate an exact replica of the original
assembly code/high level source code in terms of the symbolic constants and comments used.
However disassemblers/decompilers generate a source code which is somewhat matching to the
original source code from which the binary code is generated.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Simulators simulate the target hardware and the firmware execution can be inspected using
simulators.
The features of simulator based debugging are listed below.
Firmware debugging deals with examining the firmware execution, execution fl ow, changes to
various CPU registers and status registers on execution of the firmware to ensure that the
firmware is running as per the design.
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
The Emulator POD forms the heart of any emulator system and it contains the following
functional units. Emulation Device Emulation device is a replica of the target CPU which
receives various signals from the target board through a device adaptor connected to the target
board and performs the execution of firmware under the control of debug commands from the
debug application.
The emulation device can be either a standard chip same as the target processor (e.g. AT89C51)
or a Programmable Logic Device (PLD) configured to function as the target CPU. If a standard
chip is used as the emulation device, the emulation will provide real-time execution behaviour.
At the same time the emulator becomes dedicated to that particular device and cannot be re-used
for the derivatives of the same chip.
PLD-based emulators can easily be re-configured to use with derivatives of the target CPU
under consideration. By simply loading the configuration fi le of the derivative
processor/controller, the PLD gets re-confi gured and it functions as the derivative device.
A major drawback of PLD-based emulator is the accuracy of replication of target CPU
functionalities. PLD-based emulator logic is easy to implement for simple target CPUs but for
complex target CPUs it is quite diffi cult.
Emulation Memory It is the Random Access Memory (RAM) incorporated in the Emulator
device. It acts as a replacement to the target board’s EEPROM where the code is supposed to be
downloaded after each firmware modification. Hence the original EEPROM memory is
emulated by the RAM of emulator. This is known as ‘ROM Emulation’.
ROM emulation eliminates the hassles of ROM burning and it offers the benefit of infinite
number of reprogrammings (Most of the EEPROM chips available in the market supports only
a few 1000 re-program cycles).
Emulation memory also acts as a trace buffer in debugging. Trace buffer is a memory pool
holding the instructions executed/registers modified/related data by the processor while
debugging.
The common features of trace buffer memory and trace buffer data viewing are
listed below:
∑ Trace buffer records each bus cycle in frames
∑ Trace data can be viewed in the debugger application as Assembly/Source code
∑ Trace buffering can be done on the basis of a Trace trigger (Event)
∑ Trace buffer can also record signals from target board other than CPU signals (Emulator
dependent)
∑ Trace data is a very useful information in firmware debugging
AJIET | D E P T . O F CSE
INTRODUCTION TO EMBEDDED SYSTEMS | MODULE 4:
Embedded Firmware Design and Development
Emulator Control Logic Emulator control logic is the logic circuits used for implementing
complex hardware breakpoints, trace buffer trigger detection, trace buffer control, etc. Emulator
control logic circuits are also used for implementing logic analyser functions in advanced emulator
devices. The ‘Emulator POD’ is connected to the target board through a ‘Device adaptor’ and signal
cable.
Device Adaptors Device adaptors act as an interface between the target board and emulator POD.
Device adaptors are normally pin-to-pin compatible sockets which can be inserted/plugged into the
target board for routing the various signals from the pins assigned for the target processor. The
device adaptor is usually connected to the emulator POD using ribbon cables. The adaptor type
varies depending on the target processor’s chip package. DIP, PLCC, etc. are some commonly used
adaptors.