# Embedded Firmware:
* The Program instructions and or the configuration settings that an embedded system developer dumps
into the Program memory of the embedded system.
* 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.
* Designing embedded firmware requires understanding of the particular embedded product hardware, like
various component interfacing, memory map details, I/O port details, confi guration and register details of
various hardware chips used and some programming language (either target processor/controller specific low
level assembly language or a high level language like C/C++/JAVA).
* Embedded firmware development process starts with the conversion of the fi rmware requirements into
a program model using modelling tools like UML.
* 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.
# Embedded Firmware Design Approach:
* The firmware design approaches for embedded product is purely dependent on:
- the complexity of the functions to be performed, and
- speed of operation required.
* Two basic approaches for the design and implementation of embedded firmware are:
1. The Super loop based approach
2. The Embedded Operating System based approach
* The decision on which approach needs to be adopted for firmware development is purely
dependent on the complexity and system requirements.
1. The Super loop based approach:
* Suitable for application where,
- application which are not time critical
- response time is not so important (i.e systems missing deadline is acceptable)
* Code is executed task by task basis.
* The program/ firmware execution flow:
1. Configure the common parameters and perform initialisation for various hardware components
memory, registers, etc.
2. Start the first task and execute it
3. Execute the second task
4. Execute the next, and so on
5. Exucute the last task
6. Jump back to the first task and repeat the process.
* The order of tasks execution is fixed and they are hard coded in the code itself.
* The operation is an infinite loop based approach.
* Almost all tasks in embedded applications are non-ending and are repeated infinitely throughout the
operation.
* In order to come out of the infinite loop, two approaches can be used:
1. Hardware Reset - Bring the program execution back to the main loop.
2. Interrupt assertion - Suspends the task execution temporarily and performs the corresponding
interrupt service routine and restarts the task execution from the interrupted
point.
* The ''super loop based design'' doesn't require an operating system, since 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.
* Deployed in low-cost embedded products and products where response time is not time critical.
* There is no use in putting the sub-tasks into independent task in case of strict sequential task based product
and running them parallel. It won’t work at all.
* The major drawback is that any failure in any part of a single task may affect the total system.
* Lack of real timeliness.
2. The Embedded Operating System based approach:
* It 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.
* OS in embedded system is required in products where multiple tasks needs to be handled concurrently, or
in systems which handles number of I/O devices which it has to respond.
* OS is responsible for scheduling the real-time tasks based on their priority. It imparts multitasking and
re-scheduling features apart from making sure the real-time response.
* RTOS based design approach is employed in embedded products demanding Real-time response.
* RTOS contains a Real Time kernel responsible for performing pre-emptive multitasking, scheduler for
scheduling tasks, multiple threads, etc.
* RTOS allows flexible scheduling of system resources like the CPU and memory and offers some way
to communicate between tasks.
# Embedded Firmware Development Language:
- Target processor/controller specific language (Assembly or Low level Language)
- Target processor/controller independent language (High level language such as C, C++, Java)
- Combination of both Assembly and High Level Language.
1. Assembly Language based development:
* ‘Assembly language’ is the human readable notation of ‘machine language’, whereas ‘machine language’
is a processor understandable language.
* Processor/Controller understands only binary ('0' and '1').
* Machine language is a binary representation and it consists of 1s and 0s.
* Machine language is made readable by using specific symbols called ‘mnemonics’.
* Assembly language and machine languages are processor/controller dependent.
* Assembly language is often used in writing the low level interaction between the operating system and
the hardware, for instance in device drivers.
* The general format of an assembly language instruction is opcode followed by operand.
* The Opcode tells the processor/controller what to do and the Operands provide the data and information
required to perform the action specifi ed by the opcode.
* It is not necessary that all opcode should have Operands.
* Assembly language instructions are written one per line. Each line of an assembly language program is
split into four fields as given below
LABEL OPCODE OPERAND COMMENTS
* A ‘LABEL’ is an identifier used extensively in programs to reduce the reliance on programmers for
remembering where data or code is located.
* LABEL is commonly used for representing a memory location, address of a program, sub-routine, code portion,
etc.
* The maximum length of a label differs between assemblers. Labels are always suffi xed by a colon and
begin with a valid character. Labels can contain number from 0 to 9 and special character _ (underscore).
# Conversion of Assembly Language to Machine Language:
* Translation of Assembly code to machine code is done by the assembler.
* Assembler for different processor/controller is different and multiple vendors are available for same
controller/processor.
Fig: Assembly language to machine language conversion process
* The object file contains the "Machine code" and "re-locatable addresses of the code byte".
* The object file generated by assembler 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.
* Linker/Locator will provide the absolute address to all the object files.
* Each source file can share variables and functions (subroutines) among them.
* Exporting a variable/function from a module (i.e making a variable/function from a module available to all other
modules) is done by declaring that function/variable as "PUBLIC" in the source file.
* Importing a variable or function from a module (i.e taking a variable or function from any one of other modules)
is done by declaring that variable or function as "EXTRN" in the module where it is going to be accessed.
Advantages:
* Efficient Code Memory and Data Memory Usage (Memory Optimistion)
* High Performance
* Low Level Hardware Access
Disadvantages:
* High Development Time
* Non-portable
2. High Level Language Based Development:
* 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 conversion of source file written in high level language to object file is done by a cross-compiler,
Fig: High level language to machine language conversion process
Advantages:
* Reduced Development Time
* Portability
Disadvantages:
* Some crosscompilers available for high level languages may not be so efficient in generating optimised
target processor specific instructions.
* Cross-compiler development cost is high.
3. Mixing Assembly and High Level Language:
i. Mixing Assembly with High level language
ii. Mixing High Level Language with Assembly
iii. Inline Assembly
i. Mixing Assembly with High Level Language:
* It is needed when entire code is written in 'High Level Language' and the cross-compiler do not have
built in support for implementing certain features. Or the Programmer wants fast and optimized code
as offered by Assembly routines .
* When accessing certain low level hardware, the timing specifications may be very critical and a cross
compiler generated binary may not be able to offer the required time specifications accurately.
* Writing the hardware/peripheral access routine in processor/controller specific Assembly language and
invoking it from ‘C’ is the most advised method to handle such situations.
ii. Mixing High Level Language with Assembly:
* The source code is already available in Assembly language and a routine written in a high level language
needs to be included to the existing code.
Note:
1. To mix C and Assembly language, the programmer must be aware of the following:
a.) How the parameters are passed from the High Level Language routine to Assembly.
b.) How values are returned from Assembly to High Level Language.
c.) How assembly routine is invoked from the high level language code.
2. All the knowledge are cross-compiler dependent and one must be aware of specific cross-compiler rule to
perform these tasks.
* To mix Assembly with 'C' in the C51 cross-compiler (developed by Keil) for 8051 micro-controller, following rules
are followed for effective mixing of the two codes:
1. Write a simple function in C that passes parameters and returns values the way you want your assembly
routine to.
2. Use the SRC directive (#PRAGMA SRC at the top of the file) so that the C compiler generates an .SRC
file instead of an .OBJ file.
3. Compile the C file. Since the SRC directive was specified, the .SRC file is generated. The .SRC file contains
the assembly code generated for the C code you wrote.
4. Rename the .SRC file to a .A51 file.
5. Edit the .A51 file and insert the assembly code you want to execute into the body of the assembly function
shell included in the .A51 file.
Note:
1. C51 allows passing of a maximum of three arguments through general purpose registers R2 to R7.
2. If the three arguments are char variables, they are passed to the function using registers R7, R6 and R5
respectively.
3. If the parameters are int values, they are passed using register pairs (R7, R6), (R5, R4) and (R3, R2).
4. If the number of arguments is greater than three, the first three arguments are passed through registers and
rest is passed through fixed memory locations.
5. Return values are usually passed through general purpose registers. R7 is used for returning char value and
register pair (R7, R6) is used for returning int value.
6. The prefix _ informs the cross compiler that the parameters to the function are passed through registers.
If the function is invoked without the _ prefix, it is understood that the parameters are passed through
fixed memory locations
(i.) and (ii.)
Ex: Accessing memory locations from C program that is reserved in assembly code:
iii. Inline Assembly:
* Inline assembly is another technique for inserting target processor/controller specific Assembly
instructions at any location of a source code written in high level language.
* This avoids the delay in calling an assembly routine from a ‘C’ code.
* Special keywords are used to indicate that the start and end of Assembly instructions and these are
cross-compiler specific.
* C51 uses the keywords #pragma asm and #pragma endasm to indicate a block of code written in assembly.