1
Mixing C and Assembly Code with IAR
Embedded Workbench for FPSLIC
Features
Passing Variables between C and
Assembly Code Functions
Calling Assembly Code Functions
from C
Calling C Functions from
Assembly Code
Writing Interrupt Functions in
Assembly Code
Accessing Global Variables in
Assembly Code
Introduction
This application note describes how to
use C to control the program flow and
main program and assembly modules to
control time-critical I/O functions.
The application note also describes how
to set up and use the IAR C-compiler for
the FPSLIC controller in projects includ-
ing both C and assembly code. By mix-
ing C and assembly, designers can
combine the powerful C language
instructions with the effective hardware-
near assembly code instructions.
Table 1. The Pluses and Minuses of C and Assembly
Assembly C
+ Full control of resource usage
+ Compact/fast code in small applications
- Inefficient code in larger applications
- Cryptic code
- Hard to maintain
- Non-portable
+ Efficient code in larger applications
+ Structured code
+ Easy to maintain
+ Portable
- Limited control of resource usage
- Larger/slower code in small applications
Mixing C and
Assembly
Application
Note
Rev. 1976A–11/00
FPSLIC
2
Passing Variables between C and
Assembly Code Functions
When the IAR C-compiler is used for the FPSLIC, the reg-
ister file is segmented as shown in Figure 1.
Scratch registers are not preserved across function calls.
Local registers are preserved across function calls. The Y
register (R28:R29) is used as a data stack pointer to
SRAM. The scratch registers are used for passing parame-
ters and return values between functions.
When a function is called, the parameters to be passed to
the function are placed in the register file (registers
R16 - R23). When a function is returning a value, this value
is placed in the register file (registers R16 - R19), depend-
ing on the size of the parameters and the returned value.
Table 2 shows example placement of parameters when
calling a function.
Figure 1. Segments in the Register File
For a complete reference of the supported data types and
corresponding sizes, see the AVR® IAR Compiler
Reference Guide from IAR Systems, Data Representation
section.
Example C function call:
int get_port(unsigned char temp, int num)
When calling this C function, the 1-byte parameter temp is
placed in R16 and the 2-byte parameter num is placed in
R20:R21. The function returns a 2-byte value, which is
placed in R16:R17 after return from the function.
If a function is called with more than two parameters, the
first two parameters are passed to the function as shown
above. The remaining parameters are passed to the func-
tion on the data stack. If a function is called with a struct or
union as a parameter, a pointer to the structure is passed
on to the function on the data stack.
If a function needs to use any local registers, it first pushes
the registers on the data stack. Then the return value from
the function is placed at addresses R16 - R19, depending
on the size of the returned value.
Scratch Register R0 - R3
Local Register R4 - R15
Scratch Register R16 - R23
Local Register R24 - R27
Data Stack Pointers (Y) R28 - R29
Scratch Register R30 - R31
Table 2. Placement and Parameters of C Functions
Function Parameter 1 Registers Parameter 2 Registers
func (char, char) R16 R20
func (char, int) R16 R20, R21
func (int, long) R16, R17 R20, R21, R22, R23
func (long, long) R16, R17, R18, R19 R20, R21, R22, R23
FPSLIC
3
Example 1
Calling Assembly Code Functions from a C Program – with No Parameters and No
Return Value
Example C Code for Calling Assembly Code Function
#include "ioat94k.h"
extern void get_port(void);/* Function prototype for asm function */
void main(void)
{
DDRD = 0x00; /* Initialization of the I/O ports */
DDRE = 0xFF;
while(1) /* Infinite loop */
{
get_port(); /* Call the assembler function */
}
}
The Called Assembly Code Function
NAME get_port
#include "ioat94k.h" ; The #include file must be within the module
PUBLIC get_port ; Declare symbols to be exported to C function
RSEG CODE ; This code is relocatable, RSEG
get_port; ; Label, start execution here
in R16,PIND ; Read in the pind value
swap R16 ; Swap the upper and lower nibble
out PORTE,R16 ; Output the data to the port register
ret ; Return to the main function
END
FPSLIC
4
Calling Assembly Code Functions from a C Function – Passing Parameters and
Returning Values
This example C function is calling an assembler function.
The 1-byte mask is passed as a parameter to the assem-
bly function; mask is placed in R16 before the function call.
The assembly function is returning a value in R16 to the C
variable value.
#include "ioat94k.h"
char get_port(char mask); /*Function prototype for asm function */
void C_task main(void)
{
DDRE=0xFF
while(1) /* Infinite loop*/
{
char value, temp; /* Decalre local variables*/
temp = 0x0F;
value = get_port(temp); /* Call the assembler function */
if(value==0x01)
{
/* Do something if value is 0x01 */
PORTE=~(PORTE); /* Invert value on Port E */
}
}
}
The Called Assembly Code Function
NAME get_port
#include "ioat94k.h" ; The #include file must be within the module
PUBLIC get_port ; Symbols to be exported to C function
RSEG CODE ; This code is relocatable, RSEG
get_port: ; Label, start execution here
in R17,PIND ; Read in the pind value
eor R16,R17 ; XOR value with mask(in R16) from main()
swap R16 ; Swap the upper and lower nibble
rol R16 ; Rotate R16 to the left
brcc ret0 ; Jump if the carry flag is cleared
ldi r16,0x01 ; Load 1 into R16, return value
ret ; Return
ret0: clr R16 ; Load 0 into R16, return value
ret ; Return
END
FPSLIC
5
Calling C Functions from Assembly Code
Assuming that the assembly function calls the standard C
library routine rand() to get a random number to output
to the port. The rand() routine returns an integer value
(16 bits). This example writes only the lower byte/8 bits to
aport.
NAME get_port
#include "ioat94k.h" ; The #include file must be within the module
EXTERN rand, max_val ; External symbols used in the function
PUBLIC get_port ; Symbols to be exported to C function
RSEG CODE ; This code is relocatable, RSEG
get_port: ; Label, start execution here
clr R16 ; Clear R16
sbis PIND,0 ; Test if PIND0 is 0
rcall rand ; Call RAND() if PIND0 = 0
out PORTE,R16 ; Output random value to PORTE
lds R17,max_val ; Load the global variable max_val
cp R17,R16 ; Check if number higher than max_val
brlt nostore ; Skip if not
sts max_val,R16 ; Store the new number if it is higher
nostore:
ret ; Return
END
FPSLIC
6
Writing Interrupt Functions in Assembly
Interrupt functions can be written in assembly. Interrupt
functions cannot have any parameters or return any value.
Because an interrupt can occur anywhere in the program
execution, it needs to store all used registers on the stack.
Care must be taken to avoid problems with the interrupt
functions in C when assembler code is placed at the inter-
rupt vector addresses.
Example Code Placed at Interrupt Vector
NAME EXT_INT1
#include "ioat94k.h"
extern c_int1
COMMON INTVEC(1) ; Code in interrupt vector segment
ORG INT1_vect ; Place code at interrupt vector
RJMP c_int1 ; Jump to assembler interrupt function
ENDMOD
;The interrupt vector code performs a jump to the function c_int1:
NAME c_int1
#include "ioat94k.h"
PUBLIC c_int1 ; Symbols to be exported to C function
RSEG CODE ; This code is relocatable, RSEG
c_int1:
st -Y,R16 ; Push used registers on stack
in R16,SREG ; Read status register
st -Y,R16 ; Push Status register
in R16,PIND ; Load in value from port D
com R16 ; Invert it
out PORTE,R16 ; Output inverted value to port E
ld R16,Y+ ; Pop status register
out SREG,R16 ; Store status register
ld R16,Y+ ; Pop Register R16
reti
END
FPSLIC
7
Accessing Global Variables in Assembly
The main program introduces a global variable called
max_val. To access this variable in assembly, the variable
must be declared as EXTERN max_val. To access the
variable, the assembly function uses LDS (Load Direct
from SRAM) and STS (STore Direct to SRAM) instructions.
#include "ioat94k.h"
char max_val;
void get_port(void); /* Function prototype for assembler function */
void C_task main(void)
{
DDRE = 0xFF; /* Set port E as output */
while(1) /* Infinite loop */
{
get_port(); /* Call assembly code function */
}
}
NAME get_port
#include "ioat94k.h" ; The #include file must be within the module
EXTERN rand, max_val ; External symbols used in the function
PUBLIC get_port ; Symbols to be exported to C function
RSEG CODE ; This code is relocatable, RSEG
get_port: ; Label, start execution here
clr R16 ; Clear R16
sbis PIND,0 ; Test if PIND0 is 0
rcall rand ; Call RAND() if PIND0 = 0
out PORTE,R16 ; Output random value to PORTE
lds R17,max_val ; Load the global variable max_val
cp R17,R16 ; Check if number higher than max_val
brlt nostore ; Skip if not
sts max_val,R16 ; Store the new number if it is higher
nostore:
ret ; Return
END
References
AVR® IAR Compiler Reference Guide from IAR Systems
© Atmel Corporation 2000.
Atmel Corporation makes no warranty for the use of its products, other than those expressly contained in the Company’s standard war-
ranty which is detailed in Atmel’s Terms and Conditions located on the Company’s web site. The Company assumes no responsibility for
any errors which may appear in this document, reserves the right to change devices or specifications detailed herein at any time without
notice, and does not make any commitment to update the information contained herein. No licenses to patents or other intellectual prop-
erty of Atmel are granted by the Company in connection with the sale of Atmel products, expressly or by implication. Atmel’s products are
not authorized for use as critical components in life support devices or systems.
Atmel Headquarters Atmel Operations
Corporate Headquarters
2325 Orchard Parkway
San Jose, CA 95131
TEL (408) 441-0311
FAX (408) 487-2600
Europe
Atmel SarL
Route des Arsenaux 41
Casa Postale 80
CH-1705 Fribourg
Switzerland
TEL (41) 26-426-5555
FAX (41) 26-426-5500
Asia
Atmel Asia, Ltd.
Room 1219
Chinachem Golden Plaza
77 Mody Road Tsimhatsui
East Kowloon
Hong Kong
TEL (852) 2721-9778
FAX (852) 2722-1369
Japan
Atmel Japan K.K.
9F, Tonetsu Shinkawa Bldg.
1-24-8 Shinkawa
Chuo-ku, Tokyo 104-0033
Japan
TEL (81) 3-3523-3551
FAX (81) 3-3523-7581
Atmel Colorado Springs
1150 E. Cheyenne Mtn. Blvd.
Colorado Springs, CO 80906
TEL (719) 576-3300
FAX (719) 540-1759
Atmel Rousset
Zone Industrielle
13106 Rousset Cedex
France
TEL (33) 4-4253-6000
FAX (33) 4-4253-6001
Atmel Smart Card ICs
Scottish Enterprise Technology Park
East Kilbride, Scotland G75 0QR
TEL (44) 1355-803-000
FAX (44) 1355-242-743
Atmel Grenoble
Avenue de Rochepleine
BP 123
38521 Saint-Egreve Cedex
France
TEL (33) 4-7658-3000
FAX (33) 4-7658-3480
Atmel FPSLIC Hotline
1-(408) 436-4119
Atmel FPSLIC e-mail
fpslic@atmel.com
FAQ
Available from Website
Fax-on-Demand
North America:
1-(800) 292-8635
International:
1-(408) 441-0732
e-mail
literature@atmel.com
Web Site
http://www.atmel.com
BBS
1-(408) 436-4309
Printed on recycled paper.
1976A–11/00/xM
Marks bearing ® and/or are registered trademarks and trademarks of Atmel Corporation.
Terms and product names in this document may be trademarks of others.