|
Sometimes it is useful to program some parts in assembly language while whole program is written in C. There are two methods how to inject assembler parts in C program. One of them is to write in-line ASM and another is to link existing assembler program. For instance some parts of program may require critical timings and you are not sure if C compiler can be as optimal as you expect. Other reasons according to avr-libc documentation may be as follows: Code for AVR's that have no RAM; Very timing critical applications; Special tweaks that cannot be done in C. As I mentioned all this can be also done using in-line assembler feature. For somebody in-line assembler may look too complicated because of special syntax requirements. Before starting to write assembler program first read (What Registers are used by the C compiler) to ensure you are using right registers in your assembler program and won't mess up the normal program flow by occupying registers that are storing values from other routines. In most cases push and pop may do the job.
OK lets have simple example to clear things out. Dont pay attention to fact that I am writing program which can be easily written in C. This is only for demonstration purposes how to relate C and ASM. Project consists of 3 parts: Note, that assembler file must have capital extension .S, otherwise program wont compile and maybe cleared during make clear command. Lets write program: <<<<<<<<<<<<,mainC.c>>>>>>>>>>>>>>> #include <avr/io.h> volatile uint8_t pinbits; //define poer pins extern void InitPort(void);//init port for output extern void sendpinbits(void);//send to port int main() { pinbits=1;//set pin 1 as output InitPort();//call subroutine from assembler file while(1)//repeat for ever { pinbits=1;//Pin High sendpinbits();//call subroutine from assembler file pinbits=0;//Pin Low sendpinbits();//call subroutine from assembler file } } Then assembler program: <<<<<<<<<<<<extasm.S>>>>>>>>>>> #include <avr/io.h> ;required for register definitions .extern pinbits ;external variable .global InitPort ;make accesible globally InitPort: ;function name push r18 ;save register value lds r18, pinbits ;load variable to r18 out _SFR_IO_ADDR(DDRD), r18 ;set pins as output pop r18 ;restore register ret ;return from subroutine .global sendpinbits ;make global sendpinbits: ;function name push r18 ;save register value lds r18, pinbits ;load variable to r18 out _SFR_IO_ADDR(PORTD), r18 ;pins to High pop r18 ;restore register ret ;return from subroutine Makefile is generated with Mfile which comes with WinAVR. You only have to change these parts: <<<<<<Makefile>>>>>>>> # MCU name MCU = atmega8 # Processor frequency. F_CPU = 8000000 # Output format. (can be srec, ihex, binary) FORMAT = ihex # Target file name (without extension). TARGET = mainC # List Assembler source files here. ASRC = extasm.S Other parts of Makefile leave as they are. Then call command make all (Programmers Notepad->Tools->Make All) and program should compile without errors. I have tested this example with AVRStudio debugger and it works properly. Good luck.
Related Items:
|