How to combine C program with external ASM
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:
-
mainC.c – C program;
-
extasm.S – ASM program;
-
Makefile – makefileneeded to make a project.
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.
Comments
Didn't work
After i followed the above step by step the code didn't work and i got the following message:
-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Compiling C: mainC.c
avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./mainC.lst -std=gnu99 -Wundef -MMD -MP -MF .dep/mainC.o.d mainC.c -o mainC.o
mainC.c:34: warning: function declaration isn't a prototype
Linking: mainC.elf
avr-gcc -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=mainC.o -std=gnu99 -Wundef -MMD -MP -MF .dep/mainC.elf.d mainC.o --output mainC.elf -Wl,-Map=mainC.map,--cref -lm
mainC.o: In function `main':
F:\Microcontrollers\projects\MakeFile\ASSEMBLY&C/mainC.c:38: undefined reference to `InitPort'
F:\Microcontrollers\projects\MakeFile\ASSEMBLY&C/mainC.c:46: undefined reference to `sendpinbits'
F:\Microcontrollers\projects\MakeFile\ASSEMBLY&C/mainC.c:50: undefined reference to `sendpinbits'
make: *** [Clock+.elf] Error 1
Add new comment