embedded systems

Published on June 2016 | Categories: Types, Instruction manuals | Downloads: 41 | Comments: 0 | Views: 378
of 32
Download PDF   Embed   Report

programming in embedded c

Comments

Content


Programming for Embedded Systems
GETTING MOST OF ‘C’:
Low level programming languages are used for system programming because they have
powerful features such as low-level access to memory. Similarly, high-level languages are used
for application programming because they are flexible and easy to use. C language combines the
power of low-level languages and the flexibility and simplicity of high-level languages.
Therefore, it is a widely used computer language.
In !"!, #en Thompson and $ennis %itchie designed a file system for &ell Laboratories
in order to provide a more convenient environment for programming. This file system evolves
into an early version of the '(I) *perating System. The language & was developed by
Thompson in attempt to write a +*%T,( language. & was interpreter-based, and thus had
performance drawbac-s. so %itchie developed the C language, which was compiler-based. In
!/0, the new file system was rewritten in C language giving a thrust to its acceptance among an
increasing number of users.
C language possesses the powerful low-level features of second generation languages
such as pointers, memory allocation and bit-manipulation. It also supports conditional constructs,
loop structures, loop structures, a rich list of operators and a variety of data structures as in third
generation languages.
Features of the ‘C’ language:
C language has various features that ma-e it widely-used languages. Some of the
important features are1
• 2ointers
• 3emory allocation
• %ecursion
• &it manipulation
4,ssembly language5 is a human readable notation of machine language. 3achine
language is a processor understandable language. It is made readable by using specific symbols
called mnemonics. 3achine language can be considered as an interface between processor and
programmer. ,ssembly language and machine language are processor6controller family will not
wor- with others.
7henever the conventional c language and its extensions are used for programming
embedded systems, it is referred to as 4embedded C5 programming. 2rogramming in embedded
C is 8uite different from conventional des-top application development using C language for a
particular *S platform.
9mbedded application developers should be aware of this fact and should develop
application in the best possible way which optimi:es the code memory and wor-ing memory
usage as well as performance.
‘C’ Vs Embedded C:
C is a well structured, well defined and standardi:ed general purpose programming
language with extensive bit manipulation support. Conventional C follows ,(SII C standard. ,
platform ;*S< specific application -nown as complier is user for conversion of programs written
in C to target processor ;on which *S is running< specific binary files. Therefore it is specific
platform development. 9mbedded C can be considered as a subset of conventional =C> language.
9mbedded C supports all =c> instructions and incorporates a few target processor specific
function and instructions.
, software program called =cross compiler> is used for the conversion of programs
written in embedded C to target processor6controller specific instruction ;machine language<
Compler Vs Cross Compler:
Complier is software tool that converts a source code written in high level language on
top of a particular operating system running on specific target processor architecture. Compiler is
generally named as =native compilers> which generates machines code for same machine on
which it is running.
Cross compilers are software tools used in cross platform development application. In
cross platform development, the complier running on a particular target processor6*S converts
the source code to machine code for a target processor whose architecture and instruction set is
different from the processor on which the compiler is running or for an operating system which
is different from the C? platform environment *S. 9.g.1 #eil C@.
!sng ‘C’ n Embedded C:
"e#$ords and dentfers:
#eywords are the reserved names used by the C. ,ll -eywords have fixed meaning in C
context and are not allowed for programmers for naming their own variables or functions. ,(SI
C supports 0A -ws. 9.g.1 auto, do it etc.
Identifiers are user defined names and labels. Identifiers can contain letters of 9nglish
alphabets and numbers. ;-< is the only special character allowed here and starting character
should be a letter.
%&T& T'(ES:
The types of data structures provided by C can be classified under the following categories1
• +undamental data types
• $erived data types
Fundamental data t#pes:
They include the data types at the lowest level, i.e. those which are used for actual data
representation in the memory. ,ll other data types are based on the fundamental data types.
The fundamental data types are1
• Char 1 for characters and strings
• Int 1 for integers
• +loat 1 for numbers with decimal such as amounts,8uotients,and salary
%ata t#pes n Embedded :
It represents the type of data held by the variable. The data type si:e and range for an
ordinary c compiler for 0A bit platform. The storage si:e may vary for data type depending on
the cross compiler in use for embedded application. Therefore memory is a big constraint in
embedded applications. select the optimum data type variable.
Storage )lass
#eywords related to storage class provide information on the scope and life time of a
variable. =C> supports four types of storage class. They are auto, register, static, extern.
M&NI(!*&TING +ITS IN MEMO,' &N% I-O (O,TS:
+t manpulaton operatons:
Thou 9mbedded C does not support a built in &oolean variable ;&it variable< for holding
a =true> ;logic< or =+alse>;Logic B< condition, it provides extensive support for &IT manipulation
operation. &oolean variables re8uired in embedded application are 8uite often stored as variables
with least storage memory re8uirement.
If the &oolean variables are pac-ed for saving memory, depending upon the program
re8uirement each variable may have to be extracted and some manipulation needs to be
performed on the bits.
+t$se &N%:
*perator C performs &itwise ,($. The C operator acts on individual bits of the operands. They
are usually performed for selective clearing of bits and testing the present state of a bit.
+t$se O,:
*perator D performs bitwise *% operation .It is performed on individual bits of the operands. It is
usually performed for selectively setting of bits and testing the current state of the bit.
+t$se E.)lus/e O, 0 1O,:
&itwise )*% operator E acts on individual operand bits and performs exclusive *% operation on
the bits. It is used for toggling bits in embedded application.
+t$se NOT:
It negates ;inverts< the state of a bit .The operator F is used as &it (*T operator.
Setting and clearing the bits1
Setting the value of a bit to => is achieved by &itwise *% operator.
To set B
th
bit always
+lag G flag6 or flag6G
Set "
th
bit of flag
+lag G flag6;HH"< or flag 6G;HH"<.
• +or clearing a bit is achieved by &itwise ,($ing the bit with =B>.&itwise ,($ operation
combined with left shifting of can be used for clearing any desired bit in a variable.
+lag CG F ;HH"< or flag CG *)&+.
• Toggling a bit is performed to negate the current state of a bit .Toggling is also -nown as
inverting bits.
+lag E G ;HH"<.
E.tra)tng and nsertng bts:
It is meaningful to store related information as the bits of single variables instead of saving them
as separate variables. This saves considerable amount of memory in a 9S where data memory is
a big bottlenec-.
In embedded application, where information can be stored using bits of single variable is
information provided by real time cloc- ;%TC<.
%TC chip provides various data li-e current date6month6year, day of the wee-, current time in
hrs6mins6sec etc.
If the application demands the storage of all these information in the data memory of the 9S
for some reason, it can be achieved in A ways1
. 'se separate variables for storing each data.
A. Club the related data and store them as a bit of single variable.
7e need to store the information of the %TC in the data memory in $636I format, $ J date to
0 3 -month to A I-year B to !!.7e need 0 characters if approach is of type.
In the second approach, only @ bits for date ;with @ bits we can represent B to AE@ J no ;B to
0< K bits for month and / bits for year.
Iear ;B to !!< Month (1 to 12 ) Date (1 to 31)
&it ! to @ Bit 5 to 8 Bit 0 to 4
15 9 5
0
This is " bit integer arranged as year, month or date, each should be extracted from the single
variable date.
The following code snippet illustrates the extraction of year
Char year G ;data LL !< and *)/+
;date LL !< shifts the contents ! bits to the left and now =year> is stored in the variable date in bits
B to " ;including both<.The content of other bits ;/ to @< are not relevant to us and only the first
/ bits ;B to "<are needed for getting the =Iear> value. ,($ing with mas- *)/+;B<
retains the content of bits B to " and now the variable year contains the =Iear> value extracted
from variable =$ate>. Similarly to extracting of bits, we may have to insert bits to change the
value of certain data.
In order to ensure the inserted bits are not exceeding the number of bits assigned for the
particular bit variable, bitwise ,($ the new value with the mas- corresponding to the number of
bits allocated to the corresponding value.
$ate G date F ;*)/+ HH !<.-- date6G;new-year C *)/f<HH!.
$ate G ;newMyearHH!<.--
Testng bts:
&it wise operators can also be used for chec-ing the present status of a bit without modifying it
for decision ma-ing operations
If ;flagC;HHb<<, or if ;flag C BNKB<
,e)urs/e fun)ton:
, function which calls itself repeatedly is called a recursive function using recursive function, a
complex problem is split into its single simplest form.
It is useful in evaluating certain types of mathematical function, creating and accessing dynamic
data structure.
&CCESSING MEMO,' M&((E% I-O %EVICES:
3emory-3apped I6* is a mechanism by which the processor performs I6* access by
using memory access techni8ues. This is often put into effect because the memory bus is
fre8uently much faster than the I6* bus. ,nother reason that memory mapped I6* might be used
is that the architecture in use does not have a separate I6* bus.
In memory mapped I*, certain range of C2'Os address space is -ept aside for the external
peripherals. These locations can be accessed using the same instructions as used for other
memory accesses. &ut instead, the read6writes to these addresses are interpreted as access to
device rather than a location on the main memory.
, C2' may expect a particular device at a fixed location or can dynamically assign a
space for it. The way this wor-s is that memory interfaces are often designed as a bus ;a shared
communications resource<, where many devices are attached. These devices are usually arranged
as master and slave devices, where a master device can send and receive data from any of the
slave devices. , typical system would have1
• , C2' as the master
• *ne or more %,3 and6or %*3 devices for program code and data storage
• 2eripheral devices for interfacing with the outside world. 9xamples of these might be a
',%T ;serial communications<, $isplay device or Input device
ST,!CT!,ES:
, structure is a collection of variables that share a single name. In an array, each element
has the same format. 7ith structures we specify the types and names of each of the elements or
members of the structure. The individual members of a structure are referenced by their sub
name. Therefore, to access data stored in a structure, we must give both the name of the
collection and the name of the element. Structures are one of the most powerful features of the C
language. In the same way that functions allow us to extend the C language to include new
operations, structures provide a mechanism for extending the data types. 7ith structures we can
add new data types derived from an aggregate of existing types.
Stru)ture %e)laratons:
Li-e other elements of C programming, the structure must be declared before it can be
used. The declaration specifies the tag name of the structure and the names and types of the
individual members. The following example has three members1 one "-bit integer and two
character pointers
structtheport {
int mode; // 0 for I/O, 1 for in only -1 for out only
unsigned char volatile *addr; // pointer to its address
unsigned char volatile *ddr;}; // pointer to its direction reg
The above declaration does not create any variables or allocate any space. Therefore to
use a structure we must define a global or local variable of this type. The tag name ;theport<
along with the -eyword struct can be used to define variables of this new data type1
tructtheport!ort", !ort#, !ort$;
The above line defines the three variables and allocates " bytes for each of variable. If
you -new you needed Pust three copies of structures of this type, you could have defined them as
tructtheport {
int mode;
unsigned char volatile *addr;
unsigned char volatile *ddr ;} !ort", !ort#, !ort$;
$efinitions li-e the above are hard to extend, so to improve code reuse we can use
typedef to actually create a new data type ;called port in the example below< that behaves
syntactically li-e charintshort etc.
tructtheport {
int mode; // 0 for I/O, 1 for in only -1 for out only
unsigned char volatile *addr; // address
unsigned char volatile *ddr ;}; // direction reg
typedefstructtheport port;
port !ort", !ort#, !ort$;
*nce we have used typedef to create port, we donOt need access to the name theport
anymore. Conse8uently, some programmers use to following short-cut1
typedefstruct {
int mode; // 0 for I/O, 1 for in only -1 for out only
unsigned char volatile *addr; // address
unsigned char volatile *ddr ;} port; // direction reg
port !ort", !ort#,!ort$;
Similarly, the following approach to creating structures that uses the same structure name as the
typedef name1
struct port{
int mode; // 0 for I/O, 1 for in only -1 for out only
unsigned char volatile *addr; // address
unsigned char volatile *ddr;}; // direction reg
typedefstruct port port;
port !ort",!ort#,!ort$;
Intal2aton of a Stru)ture:
Qust li-e any variable, we can specify the initial value of a structure at the time of its definition.
path the!ath%{{0,0,&,',1()},{&,',-10,',1()},1};
line the!ath%{0,0,&,',1()};
port !ort*%{1,
+unsigned char volatile *,+0-100",,
+unsigned char volatile *,+0,};
If we leave part of the initiali:ation blan- it is filled with :eros.
path the!ath%{{0,0,&,',1()},};
line the!ath%{&,',10,1(,};
port !ort*%{1, +unsigned char volatile *,+0-100",,};
To place a structure in %*3, we define it as a global constant. In the following example
the structure fsm will be allocated and initiali:ed in %*3-space. The lin-ed-structure finite
syatem machine is a good example of a %*3-based structure.
const struct tate{
unsigned char Out; /* Output to !ort . */
unsigned short /ait; /* 0ime +* cycles, to 1ait */
unsigned char "nd2as3456;
unsigned char *7u2as3456;
const struct tate *8e-t456;}; /* 8e-t states */
typedef const struct tate tate0ype;
typedef tate0ype * tate!tr;
9define stop :fsm406
9define turn :fsm416
9define ;end :fsm4(6
tate0ype fsm4<6%{
{0-<5, (000, // stop 1 ms
{0-==, 0-=0, 0-(>, 0-00},
{0-&1, 0-"0, 0-0>, 0-00},
{turn, stop, turn, ;end}},
{0-#<,&000, // turn (?& ms
{0-)0, 0-=0, 0-00, 0-00},
{0-00, 0-@0, 0-00, 0-00},
{;end, stop, turn, turn}},
{0->&,5000, // ;end ( ms
{0-==, 0-0=, 0-01, 0-00},
{0-1(, 0-0&, 0-00, 0-00},
{stop, stop, turn, stop}}};
Example of initializing a structure in ROM
MI1ING C TO &SSEM+*':
*ften it is a good idea to lin- assembly language programs or routines with high-level
programs which may contain resources unavailable to you through direct assembly
programming--such as using COs built in graphics library functions or string-processing
functions. Conversely, it is often necessary to include short assembly routines in a compiled
high-level program to ta-e advantage of the speed of machine language.
,ll high-level languages have specific calling conventions which allow one language to
communicate to the other. i.e., to send variables, values, etc. The assembly-language program
that is written in conPunction with the high-level language must also reflect these conventions if
the two are to be successfully integrated. 'sually high-level languages pass parameters to
subroutines by utili:ing the stac-. This is also the case for C.
3ixing the code written in a high level language li-e C and ,ssembly language in the
following scenarios.
. The source code is already available in ,ssembly language and a routine written in a
high level language >C>, needs to be included to the existing code.
A. The entire source code is planned in ,ssembly code for various reasons li-e
optimi:ed code, optimal performance, efficient code memory utili:ation and proven
expertise in handling the ,ssembly, etc. but some portions of the code may be very
difficult and tedious to code in ,ssembly.
0. To include built-in library function written in =C> provided by the cross compiler.
3ore often the functions written in =C> use parameters passing to the function and return
values to the calling functions. 2arameters are passed to the function and values are returned
from the function using C2' registers, stac- memory and fixed memory. Its implementation is
cross compiler dependent and it varies across cross compiler.
, typical example is given below for the -eil C@ cross compiler. C@ allows the passing
of a maximum of three arguments through general purpose registers %A to %/. If the three are
character variables, they are passed to function using registers %/, %" and %@ respy. 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.
LC,LL M C function
C function is a function written in =C>. The prefix M informs the cross compiler that the
parameter to the function are passed through registers. If the function is invo-ed without the M
prefix, it is understood that the parameters are passed through fixed memory locations.
Inlne &ssembl#:
It is another techni8ue for inserting target processor 6 controller specific ,ssembly
instruction at any location of a source code written in high level language C. this avoids the delay
the delay in calling an ,ssembly routine from a code.
C@ uses cross compiler specific -eywords R pragma asm and R pragma endasm to
indicate a bloc- of code written in ,ssembly.


!sng &ssembl# (ro)edures n C Fun)tons
(ro)edure Setup
In order to ensure that the assembly language procedure and the C program will combine
and be compatible, the following steps should be followed1
• $eclare the procedure label global by using the ABO#"B directive. In addition, also
declare global any data that will be used.
• 'se the *C0*D8 directive to declare global data and procedures as external. It is best to
place the *C0*D8 statement outside the segment definitions and to place near data inside
the data segment.
• +ollow the C naming conventions--i.e., precede all names ;both procedures and data<
with underscores.
Sta)3 Setup
7henever entering a procedure, it is necessary to set up a stac- frame on which to pass
parameters. *f course, if the procedure doesnOt use the stac-, then it is not necessary. To
accomplish the stac- setup, include the following code in the procedure1
push e;p
mov e;p, esp
*#! allows us to use this pointer as an index into the stac-, and should not be altered throughout
the procedure unless caution is ta-en. 9ach parameter passed to the procedure can now be
accessed as an offset from *#!. This is commonly -nown as a Sstandard stac- frame.S
,EGISTE, !S!&GE:
These are some of the %egister usage conventions
%egister;s< 'sage in C functions
9,) +unctions return all pointers and integer values up to 0A-bits in this register.
9$) and 9,) +unctions return "K-bit values ;long long ints< in this register pair.;(ote19$)
holds bits "0-0A,9,) holds bits 0-B<.
9&2 'sed to access;<The arguments that were passed to a function when it was
called, and ;A< any automatic variables allocated by the function
9&),9SI,9$I
,9&2,$S,9S,and
SS.
These registers must be preserved by functions written in assembly language.
,ny of these registers that the function modifies should be pushed on entry to
the function and popped on exit.
9,),9C),
9$),+S and
TS
4Scratch5 registers. These registers may be used without preserving the
current content.
$S,9S,SS,
9&2,and 9S2
'sed to reference data. If modified by a function, the current contents these
registers must be preserved on entry and restored on return.
(reser/ng ,egsters:
It is necessary that the procedure preserve the contents of the registers *I, *EI, *#!, and all
segment registers. If these registers are corrupted, it is possible that the computer will produce
errors when returning to the calling C program.
(&,&METE, (&SSING:
(ormally, parameters are passed between functions ;either written in C or in ,ssembly<
via the stac-. +or example, if a function foo;< calls a function fooA;< with A parameters ;say
characters x and y<, then before the control Pumps to the starting of fooA;<, two bytes ;normal
si:e of a character in most of the systems< are filled with the values that need to be passed. *nce
control Pumps to the new function fooA;<, and you use the values ;passed as parameters< in the
function, they are retrieved from the stac- and used.
There are two parameter passing techni8ues in use,
. 2ass by Ualue
A. 2ass by %eference
2arameter passing techni8ues can also use
• right-to-left ;C-style<
• left-to-right ;2ascal style<
*n processors with lots of registers ;such as the ,%3 and the Sparc<, the standard calling
convention puts NallN the parameters ;and even the return address< in registers.
(ass b# Value:
7ith pass-by-value, a copy of the actual value ;the literal content< is passed. +or
example, if you have a function that accepts two characters li-e
void foo(char x, char y){
- % - F 1;
y % y F (;
putchar+-,;
putchar+y,;
}
and you invo-e this function as follows
char a,;;
a%G"G;
;%G#G;
foo(a,b);
then the program pushes a copy of the ,SCII values of O,O and O&O ;"@ and "" respectively< onto
the stac- before the function foo is called. Iou can see that there is no mention of variables OaO or
ObO in the function foo;<. So, any changes that you ma-e to those two values in foo will not affect
the values of a and b in the calling function.
(ass b# ,eferen)e:
Imagine a situation where you have to pass a large amount of data to a function and apply
the modifications, done in that function, to the original variables. ,n example of such a situation
might be a function that converts a string with lower case alphabets to upper case. It would be
an unwise decision to pass the entire string ;particularly if it is a big one< to the function, and
when the conversion is complete, pass the entire result bac- to the calling function. Vere we
pass the address of the variable to the function. This has two advantages, one, you donOt have to
pass huge data, therby saving execution time and two, you can wor- on the data right away so
that by the end of the function, the data in the calling function is already modified.
&ut remember, any change you ma-e to the variable passed by reference will result in the
original variable getting modified. If thatOs not what you wanted, then you must manually copy
the variable before calling the function.
• 2arameters are pushed onto stac- prior to C,LL.
-gcc pushes parameters in reverse order.
-W6"-bit parameters are extended to 0A-bits.
• Caller removes parameters after function returns
+unction call
w6parameters1
&yteA2ort;Bx0&C,data<.
Code generated by
the complier1
2'SV $7*%$ XMdataY .2ush A
nd
param
3*U 9,),B0&Ch .2ush
st
param
2'SV 9,)
C,LL -&yteA2ort .Call the function.
,$$ 9S2,W .%emove params
2assing an W-bit Integer J Signed Uersus 'nsigned
C ,ssembly
'nsigned char data.
Z
$o MSomething;data<.
Z
3*U[) 9,),XMdata\
2'SV 9,)
C,LL M$oMSomething
,$$ 9S2,K
2assing a "K-bit Integer J Little 9ndian +ormat
C ,ssembly
6N signed or unsigned N6
long long data .
...
$oMSomething;data< .
Z
2'SV $7*%$ XMdata?KY
2'SV $7*%$ XMdataY
C,LL M$oMSomething
,$$ 9S2,W
(assng (arameters n C to the (ro)edure:
C passes arguments to procedures on the stac-. +or example, consider the following statements
from a C main program1
H
e-tern int um+,;
H
int a1, a(, -;
H
- % um+a1, a(,;
7hen C executes the function call to um, it pushes the input arguments onto the stac- in
reverse order, then executes a call to um. 'pon entering um, the stac- would contain the
following1
Since a and aA are declared as int variables, each ta-es up one word on the stac-. The
above method of passing input arguments is called passng b# /alue. The code for um, which
outputs the sum of the input arguments via register *"C, might loo- li-e the following1
Ium
push e;p ; create stac3 frame
mov e;p, esp
mov ea-, 4e;pF)6 ; gra; the first argument
mov ec-, 4e;pF1(6 ; gra; the second argument
add ea-, ec- ; sum the arguments
pop e;p ; restore the ;ase pointer
ret
It is interesting to note several things. +irst, the assembly code returns the value of the
result to the C program through *"C implicitly. Second, a simple D*0 statement is all that is
necessary when returning from the procedure. This is due to the fact that C ta-es care of
removing the passed parameters from the stac-.
'nfortunately, passing by value has the drawbac- that we can only return one output
value. 7hat if um must output several values, or if um must modify one of the input variables]
To accomplish this, we must pass arguments by reference. In this method of argument
transmission, the addresses of the arguments are passed, not their values. The address may be
Pust an offset, or both an offset and a segment. +or example, suppose um wishes to modify aA
directly--perhaps storing the result in aA such that aA G a ? aA. The following function call from
C could be used1
um+a1, :a(,;
The first argument is still passed by value ;i.e., only its value is placed on the stac-<, but
the second argument is passed by reference ;its address is placed on the stac-<. The SCS prefix
means Saddress of.S 7e say that CaA is a SpointerS to the variable aA. 'sing the above statement,
the stac- would contain the following upon entering um1
(ote that the address of aA is pushed on the stac-, not its value. 7ith this information,
um can access the variable aA directly. ;Vint1 use an index register to hold the offset, then use a
memory access to access the variable<.
,eturnng a Value from the (ro)edure:
,ssembly can return values to the C calling program using only the *"C register. If the
returned value is only four bytes or less, the result is returned in register *"C. If the item is larger
than four bytes, a pointer is returned in *"C which points to the item. Vere is a short table of the
C variable types and how they are returned by the assembly code1
Data Type Register
char
"B
short
"C
int, long, pointer ;N<
*"C
&llo)atng *o)al %ata Spa)e on the Sta)3:
Temporary storage space for local variables or data can be created by decreasing the
contents of *! Pust after setting up a stac- frame at the beginning of the procedure. It is
important to restore the stac- space at the end of the procedure. The following code fragment
illustrates the basic idea1
push e;p ; ave callerGs stac3 frame
mov e;p, esp ; *sta;lish ne1 stac3 frame
su; esp, 5 ; "llocate local data space of
; 5 ;ytes
push esi ; ave critical registers
push edi
???
pop edi ; Destore critical registers
pop esi
mov esp, e;p ; Destore the stac3
pop e;p ; Destore the frame
ret ; Deturn to caller
!sng C Fun)tons n &ssembl# (ro)edures:
In most cases, calling C library routines or functions from an assembly program is more
complex than calling assembly programs from C. ,n example of how to call the printf library
function from within an assembly program is shown next, followed by comments on how it
actually wor-s.
glo;al Imain
e-tern Iprintf
section ?data
te-t d; J(@1 is the ;estKJ, 10, 0
strformat d; JLsJ, 0
section ?code
Imain
push d1ord te-t
push d1ord strformat
call Iprintf
add esp, )
ret
(otice that the procedure is declared global, and its name must be Imain, which is the starting
point of all C code.
Since C pushes its arguments onto the stac- in reverse order, the offset of the string is
pushed first, followed by the offset of the format string. The C function can then be called, but
care must be ta-en to restore the stac- once it has completed. 7hen lin-ing the assembly code,
include the standard C library ;or the library containing the functions you use< in the lin-..
The static refers =fixed> and it is no way related to the storage class static. ,llocating memory
on demand and freeing the memory at run time is the most adviced method for handling the
storage of dynamic data and this memory allocation techni8ue is -nown as dynamic memory.
,ET,IEVING (&,&METE,S MEMO,' M&N&GEMENT:
Address Contents Description:
X9S2?WY _data The And function parameter ;data to write to I6* port<
X9S2?KY B0&Ch The st function parameter ;an I6* port address<
X9S2Y
%eturn
,ddress
2ushed onto stac- by the C,LL instruction
Stack immediately after the CALL
PUSH DWRD !"data# $ Push %nd parameter
&' (A)*+,-Ch $ Push .st parameter
PUSH (A) $ onto the stack/
CALL "-yte%Port $ Call the function
Can>t use 2*2 instructions to access parameters.
^_Parameters expect to be removed from te stac! later b" te caller#
^_RE$ instruction expects return address to be on top of te stac!#
` (eed a way to access parameters without actually removing them from the stac-a
M&yteA2ort1
3*U $),X9S2?KY . Copy st parameter to $) ;the I6* port adrs<.
3*U ,L,X9S2?WY . Copy And parameter to ,L ;discard bits 0-W<.
*'T $),,L . 7rite the data to the I6* port.
%9T . %eturn to caller
M&yteA2ort1
PUSH (-P $ Preser0e current contents of -P on stack
&' (-P*(SP $ (sta1lish a reference point in the stack
3*U $),X9&2?WY . Copy st parameter to $) ;the I6* port address<
3*U ,L,X9&2?AY . Copy And parameter to ,L ;discard bits @-W<
*'T $),,L . 7rite the data to the I6* port
PP (-P $ Restore old contents of -P from stack
%9T . %eturn to caller
SCO(E ,ESO*!TION O(E,&TO,:
Iou have defined the member functions and the constructors of a program within the class
specifier. These fuctions can also be defined outside the boundary of the class by using the scope
resolution operator;11< to ma-e the program more readable. The following program illustrates the
use of the scope resolution operator.
6N This program uses the scope resolution operator to define member functions outside the class
N6
#include<iostream.h
!lass calculator
"
#ri$ate%
&nt i'um1 ( i'um2 ( i'um3)
#u*lic)
!alculator())
+oid in,ut ())
+oid sum ())
+oid dis,())
-)
!alculator %% calculator ()
"
i'um1 . i'um2 . i'um3.0)
-
+oid calculator %% in,ut ()
"
!out<</enter the 0rst num*er %/)
!ini'um1)
!out << 1enter the second num*er% 1)
!ini'um2)
-
+oid calculator %% sum( )
"
i'um3 . i'um12'um2)
-
+oid calculator %% dis,( )
"
!out<</the sum o3 the t4o num*ers is 1<<i'um 3<<endl)
-
&nt main()
"
!alculator 51)
51.in,ut())
51.sum())
51.dis,())
6eturn 0)
-
In the program shown above,the member functions and the constructors of the class calculator
are defined outside the class declaration by using the scope resolution operator ;11<. +or
example ,the statement1
+oid.calculator %% in,ut()
'sed the scope esolution operator ;11< to define the function outside the boundary of the class. In
the given statement , the scope resolution operator informs the computer that the function input ;<
is a member of the calculator class. The other member functions of the class calculator are
defined in a similar manner , that is outside the specifier.
In the preceding statement , void is the return type of the function calculator is the class name ,
;11< is the scope resolution operator ,input is the function name , and inti(um and int i(umA are
the function parameters.
7he declaration%
+oid in,ut())
In the class ,informs the compiler that this function is a member of the class but will be defined
outside the class.
%'N&MIC &**OC&TION:
9mbedded applications contains different types of variable and they fall into any one of
the following storage types namely1 static, auto, global or constant data.
Certain category of embedded application deal with fixed number of variables with fixed length
and certain other applications deals with variable with fixed memory length as well as variable
with total storage si:e determined only at the runtime of application. If the number of variables
are fixed in an application and if it doesn>t re8uire a variable si:e at run time, the cross compiler
can determine the storage memory re8uired by the application well in advance at the run time
and can assign each variable an absolute address within the data memory. Vere the memory
register is fixed and allocation is done before the execution of application. This type of memory
allocation is referred as static memory allocation.
The static refers =fixed> and it is no way related to the storage class static. ,llocating
memory on demand and freeing the memory at run time is the most adviced method for handling
the storage of dynamic data and this memory allocation techni8ue is -nown as dynamic memory.
&llo)aton :
3emory allocation for the executable code, constant data and alterable data together
constitute the static storage memory ;fixed storage<
The storage memory available within memory segment excluding fixed memory is dynamic
storage memory. It is divided into two seperate entitiy.
• Stac-
• Veap
Stac- memory normally starts at the high memory area of the memory segment and
grows down. It is usually used for holding auto variable;variables local to a function<, function
parameters and function reture values.
If at any point of execution, the stac- memory exceeds the allocated maximum storage
si:e, the application may crash and this condition is called =stac! overflo%&.
The free memory region lying in the between the stac- and fixed memory area is called as
=eap>.
Veap is a memory pool where storage for data is done automatically;dynamically< as and
when the application demand. Veap is located immediately above the fixed memory area and it
grows upwards.
Library functions for dynamic allocation are malloc, calloc, realloc and free.
&alloc234
It allocates a bloc- of memory dynamically. It reserves a bloc- of memory of si:e
specified as parameters to the function in heap of memory and returns a point of type void.
2ointer G ;pointerMtypeN<malloc;no of bytes<.
3alloc;< only allocates re8uired byte of memory. The allocated memory contains random data.
Calloc23 4
It allocates multiple bloc-s of storage bytes and initiali:es each allocated byte to :ero.
2ointer G;pointerMtypeN< calloc;n, si:e of bloc-<.
It allocates continuous memory for =n> number of bloc-s per bloc- and returns a pointer of type.
5ree23 4
Iit is used for releasing or deallocating the memory allocated in the heap memory by
malloc;< or calloc;< functions.
+ree;ptr<.
=ptr> is the valid pointer returned by the calloc;< or malloc;< funtion on dynamic memory
allocation. The dynamic memory allocated using malloc;< or calloc;< functions should be
released using free;< function. If the parameter to free;< function is not a valid pointer, the
application behaviour may be unexpected.
Realloc23 4
It is used for changing the si:e of allocated bytes in a dynamically allocated memory
bloc-. It changes the si:e of the bloc- of memory pointed to, by the ptr paprameters to the
number of bytes specified by the modified si:e parameters and it returns a new pointer to the
bloc-.
It returns a pointer pointing to the first byte of the reallocated memory bloc-. It returns a
void pointer if there is sufficient memory available for allocation, else return a ('LL pointer.
%ealloc;pointer, modified si:e<.
7hen using dynamic memory allocation in C6C?? include the following1
• Sufficiency1 how can we be sure that we have provided sufficient memory, so that a
critical memory allocation will never be refused]
• 6ar1age management1 how can we be sure that memory that is no longer re8uired is
released to the memory manager at exactly the right time] If we release memory too
early, we will have dangling pointers or double-free errors. If we release memory too late,
we will have memory lea-s. These -inds of problem plague development of large C6C??
programs.
• 5ragmentation1 how can we avoid the situation in which we want to allocate ( bytes of
memory, but all the available memory is in fragments smaller than (, even though the
total available is much larger than (] 3emory fragmentation is a plague of long-running
C6C?? systems that use dynamic memory extensively.
• Timeliness1 when we need to allocate memory, what is the upper bound on the time that
the memory manager may ta-e to service the re8uest] 3emory managers for C6C??
typically search freelists or more complex structures for fragments of sufficient si:e,
therefore calls to alloc or ne7 typically exhibit a variable and sometimes long latency.
,lthough the four issues of sufficiency, garbage management, fragmentation and
timeliness are serious obstacles to using dynamic memory in C6C?? embedded systems, there
are a few strategies that can mitigate them. , few are1
. 'se dynamic memory allocation during the initiali:ation phase only
A. ,llocate memory, but never release it
0. 'se reference-counting garbage collection
,EENT,&NT F!NCTIONS:
+unction which can be shared safely with several processes concurrently are called
reentrant function. 7hen a reentrant function is executing, another process can interrupt the
execution and can execute the same reentrant function. The =another process> referred here can
be a thread in a multithreaded application or can be an IS%. %eentrant function is also referred as
=pure> function.
9mbedded applications extensively ma-e use of reentrant function. In embedded applications, a
function6subroutine is considered reentrant if it satisfies the following criteria.
. The function should not hold static data over successive calls or return a pointer to static
data.
A. ,ll shared variables within the function are used in an atomic way.
0. The function does not call any other reentrant functions within it.
K. The function does not ma-e use of any hardware in a non-atomic way.
,ule 45 :
This rule deals with variable usage and function return value for a reentrant function. In
an *S based embedded system, the embedded application is managed by the *S services and
the =memory manager> service of the *S -ernel is responsible for allocating and deallocating the
memory re8uired for an application for its execution.
The wor-ing memory re8uired by an application is divided into 0 groups namely1
• Stac- memory
• Veap memory
• $ata memory
The life time of static variables is same as that of life time of the application to which it
belongs and they are usually held in the data memory area of the memory space allocated for the
application. ,ll static variables of a function are allocated in the data memory area space of the
application and each instance of the function shares this, whereas local;auto< variables of a
function are stored in the stac- memory and each invocation of function creates independent
copies of these variables in stac- memory.
+or a function to be reentrant, it should not -eep any data over successive invocations. If
a function needs some data to be -ept over successive invocations, it should be provided through
the caller function instead of storing it int he functions in the form of static variables. If the
function in the form of static data, each invocations of the function ma-es use of this pointer for
returning the result. This can be tac-led by using caller function provided storage for passing the
data bac- to the caller function. The =caller> function needs to be modified accordingly to ma-e
use of the caller function provided storage for passing the data bac- to the caller.
,ule 46: this rule deals with =atomic>.
If an embedded application contains variables which are shared between variables thread
of a multitas-ing system or between the application and IS% and if the operation on the shared
variable is non-atomic, there is a possibility for corruption of the variable due to concurrent
access of the variable by multiple threads or threads and IS%.
,ule47 : this rule deals with self-explanatory.
If a reentrant function calls another function which is non-reentrant, it may create potential
changes;damages< due to the unexpected modification of shared variables if any.
,ule4 8 : this deals with the atomic way of accessing hardware devices.
The term =atomic> in the hardware access refers to the number of steps involved in accessing a
specific register of a hardware device.
%e/)e %r/ers:
In 'nix6Linux, each device is considered a file. The directory 6dev contains one entry for each
file. 7hen you do serial communication programming, you need to find out the corresponding
entry. Two special files are1
• 6dev6console for system console on which all error 6log messages will be displayed.
• 6dev6null which is a null device J output written to this device is discarded. It is li-e a
dustbin for the '(I).
$evice drivers are low J level interfaces to control the system hardware. The system call
open, read, write, and close are used to access the device drivers. 9ach file will have a file
descriptor in '(I). The standard file descriptor is1
B for stdin ;the -eyboard<
for stdout ;the monitor<
A for stderr ;the monitor<
The program illustrates the use of reading from stdin and writing to stdout using system calls.
Rinclude Hunistd.hL
Rinclude Hstdlib.hL
int main ;<
b
char lettersX@BY.
int input.
input G read;B,lettere,@B<.
write ;,letters , input<.
exit ;B<.
\
This program uses two system calls read ;< and write ;<.The system call read ;< will read from
the stdin which has a file descriptor of B. The system call write ;< will write to the stdout which
has a file descriptor of .
Instead of reading from and writing to stdin and stdout, you can read data from file or write
data to a file as illustrated1
Rinclude Hunistd.hL
RincludeHfcntl.hL
RincludeHstdlib.hL
int main;<
b
char c.
int fin,fout.
fin G open ;4inputfile5,*M%$*(LI<.
fout G open ;4outfile5,*M7%*(LI.
while;read;fin,Cc, GG <
write;fout,Cc,<.
exit;B<.
\
The standard I6* library provided by 'nix6Linux consists of a number of function calls such
as fopen ,fclose ,fread, fwrite, fsee-, fgetc ,getc,getchar ,fputc,putc, putchar, fgets ,gets,printf,
fprintf,sprintf,scanf,fscanf,sscanf. These functions facilitate input6output operatios for
different data types using formatted and unformatted input6output.
The program given illustrates the use of reading from a file and writing to a file. (ote that
code related to error chec-ing is not included here. If the file from which you have to read the
data is not available , you need to write additional code to print an error message.
Rinclude Hstdio.hL
Rinclude Hstdlib.hL
int main; <
b
int c.
+IL9 Nfpin ,Nfpout.
fpin G fopen ;4inputfile5,5r5<.
fpout G fopen ;4outputfile5,5w5<.
while;; cG fgetc ;fpin<< aG9*+<
fputc;c,fpout<.
fclose;fpin<.
fclose;fpout<.
\
(otes1
$evices are categori:ed as character devices and bloc- devices.Serial port is a character
device.Vard dis- is a bloc- device.The category of a device is decided by the way it transfers
the data J whether character by character or bloc- by bloc-.
TOO*S FO, %EVICE %,IVE, M&N&GEMENT:
7riting device drivers used to be a Verculean tas- due to the complexity involved in
accessing the hardware. Vere are the reasons1
• $evice driver software is not portable. Iou need to write device drivers for each
operating system separately.
• Iou need to -now the system calls of each operating system to write the device driver.
• Iou need to learn the details of the hardware for writing the device driver.
Things have changed recently. 7ith the introduction of embedded C extensions to
,(SI C, this will become much easier in future resulting in portability of device
driver software.
$evice driver wi:ards are available using which you can easily build the device drivers.
3ost of the operating system vendors also provide the $evice $river #its ;$$#s< to
facilitate easy development. These -its consist of header files, library routines, and sample
code using which you can write the code for your specific re8uirement. $$#s are available
for 7indows (T, Solaris, Linux as well as most of the embedded 6real-time operating
systems.
Some of the device driver wi:ards which help in fast device driver development are1
• c()>s $$# for graphics, input, printer, networ-ing cards and 'S& is available from
http18dn18nx.com6dd-s.
• &s8uare>s 7in$# provides the provides the drivers for 7indows !W639]
C96ABBB6(T ,Linux, Solaris ,Ux7or-s etc.
• Qungo>s 7in$river provides a 0B-day trial version for device driver development .
(,O%!CTIVIT' TOO*S:
'nix6Linux provides a number of tools that increase your productivity. These tools are very
important for developing software systematically.
M&"E FI*E
7hen a number of people are wor-ing on a proPect , each person will wor- on a module and
then all the modules are combined into a singlesoftware pac-age. 9ven if you are wor-ing
alone on a proPect , you may li-e to write the code by splitting into different files. 3a-efile is
an excellent utility to combine different proPect files and create the executable file.7e will
illustrate the use of ma-efile through an example. To start with , create a number of files as
given below1
1ma-efile
helloworld1 main.o hello.o world.o
main .o1 main.c
gcc Jc hello.c
world.o 1 world.c world.h
gcc Jc world.c
1hello.h
Char strlXY G b =V>, =e>, => ,>> ,>o> ,>dB>\.
1hello.c
Rinclude5hello.h5
CharN fun;<
b
%eturn CstrXBY.
\
6Nint main; <
b
printf;4es5,fun; <<.
return B.
\N6
1world.h
Char strAXY G b =w> ,>o> ,>r> , =l>,>d>,>dB>\.
1world.c
Rinclude 4world.h5
char N funA; <
b
return CstrAXBY.
\
char strA XY G b =w> ,> o> ,>r>,>l>,>d>,>6B>\.
6NcharN funA ; <
b
return CstrAXBY.
\N6
1main.c
extern charN fun; <.
extern charN funA;<.
int main ; <
b
printf ;4es es 4,fun;<,funA;<<.
return B.
\
There is one file containing the main ; < function ,two files containing two functions Jfun; <
and fun A;<,and two header files.The ma-efile is a file that describes the rules for creating the
obPect files and the interdependencies of these files. Iou can execute the ma-efile by giving the
command1
fma-e
The system will display the following lines1
gcc -c main.c
gcc -c hello.c
gcc -c world.c
gcc Jo helloworld main.o hello.o world.o
If you modify a file,say main.c , you can give the command1
ftouch hello.h
(ext time when you invo-e the ma-e command ,the compilation will be done using the latest
main.c.
If you create a file with name different from =ma-efile> ,you need to give the command1
fma-e -f filename
3a-efile has a large number of options which can be obtained from online manual pages.
$9&'TT9%
The utility 4gdb5 is the most widely used debugger for embedded systems. Iou need to write a
program which has some bugs and then you can try to debug using the gdb. To use the
debugger , you need to give the compilation command with the following options1
fgcc -g -o lousyprog lousyprog.c
Iou can invo-e gdb using the command
fgdb lousyprog
This prompt ;gdb< will be displayed. Iou can give a number of debugger commands as listed
below1
;gdb< help ;to obtain help<
;gdb< run ;to run the program<
;gdb<print i ;to print contents of variable i<
;gdb< list ;to see program listing<
;gdb<brea- AB ;to set brea-point at line AB<
;gdb<cont ;to continue<
gdb is used extensively in embedded systems.Iou can connect the target system to the host
system using an %SA0A lin-. If the %SA0A port on the host system is specified by 6dav6tty,the
command for debugging a program 4myprogram5 is
fgdbserver 6dev6ttyB6usr62rasad6myporgram
;gdb<target remote 6dev6ttyBB
2%*+IL9%
7hile developing embedded software on the host system, you need to chec- how much time it
ta-es to execute some of the functions6modules.This information is re8uired to find out the time
J consuming functions so that either you can optimi:e the code or you can write
computationally intensive portions of the code in assembly language for faster execution.
The command 4gprof5 gives the timing of different functions. To obtain the timings ,you need
to compile the program with profiling option as below1
fgcc -pg -oprogram program.c
(ow u can run the program using the command1
f.6program
, file with the name gmon.out is created.
The output will display the time ta-en by various functions.Iou can analy:e the timings to find
out which portions of the code are ta-ing longer time.
I($9(TI(T
7hen you write lengthy program indenting the code increases the readability and hence
maintainability of the code.The shell command 4indent5 provides the automatic indenting
feature1
To indent a C program ,say hello.c, the shell command is
findent hello.c
The following options are available1
-bad blan- lines after indentation
-bap blan- line after each function 6procedure body
-bbb blan- line before boxed comments
-sob remove uncessary blan- lines in the source code
-bl braces after if line
-bli brace indent
-bls braces after structure declaration line
-br braces on if line
-nbbo brea- after &oolean operator
-bbo brea- before &oolean operator
-clin case indentation
-cn comment indentation
-nsc do not star comments
%9UISI*( C*(T%*L
Software engineers develop different versions of a program. 9very time a program is revised , it
is a good practice to record what changes have been made. ,lso ,when many persons are
wor-ing on a proPect , only one person should be able to modify the file at a time. To control
the revisions to the source files ,source code control system and revision control system are
used extensively in 'nix6Linux.
Suppose you created a text file called 4schedule5 with the following lines1
B am meeting
am lecture
A noon lunch
A pm sleep
Iou need to give control of this file to %CS so that whenever you ma-e changes , the system
will force you to add the necessary comments.
7hen you give the following command , %CS will ta-e control over the file1
frcs -i schedule
The following message will be displayed ,giving a prompt to enter description. Iou can enter
the description as 43y schedule for the day5 as shown below1
%CS file 1schedule ,v
9nter description ,terminated with single =.> *r end of file1
(*T91this is (*T the log messagea
Lmy schedule for the day
L.
$one
f
7hen you see the directory listing , you will find that a new file with , v
;comma v< will be created1
fls -
Iou need to 4chec--in5 the file to give a version number to your file , using the command 1
fci schedule
Schedule , schedule
Initial version 1.
$one
f
(ow you can verify that the original file =schedule> is removed by using the command
fls -
To change the file , we must chec- J out using the command1
fco - schedule
Schedule ,v schedule
%evision .;loc-ed<
$one f
The file is loc-ed so that the file 4schedule 4 reappears by giving the command1
fls -
(ow you can see that the file =schedule> .Iou replace =sleep> by =seminar on linux>
(ow ,you need to chec- Jin the file using the command1
fci schedule
The system will prompt you to add a log message. Iou can type 4changed the schedule at A
pm5 and enter dot on the next line as shown below1
9nter log message
LLchanges the schedule at A pm
LL.
$one
f
(ow,again the file disappears ,as you can see by giving the command1
fls -
To see the summary of the changes ,you can give the command1
frlog schedule
The complete log information will be displayed including the summary of changes made.
To obtain the first version of the file bac- , give the command1
fco Jr. schedule
To specify the version number as version A. ,while chec-ing Jin ,you can give the command1
fci -rA schedule
Iou can find ou the difference between two versions of the file by giving the command1
frcsdiff Jr. Jr.A schedule
%CS file 1schedule ,v
%etrieving version .
%etrieving version .A
$iff Jr. Jr.A
KcK
HA pm sleep
LA pm seminar on linux

Sponsor Documents

Or use your account on DocShare.tips

Hide

Forgot your password?

Or register your new account on DocShare.tips

Hide

Lost your password? Please enter your email address. You will receive a link to create a new password.

Back to log-in

Close