Use Arduino Libraries in AVR program - makefile

I am attempting to make the transition from using a development board like the Arduino uno to programming straight to an AVR. However, the Arduino libraries as well as some 3rd party Arduino Libraries are very useful and I'd like to be able to use them but I'm having trouble adjusting the makefile to include them. Currently I'm just trying to include the "TimerOne" library I downloaded. It simply provides convenience methods for using the AVR timers and ISR's. My very simple test application just attempts to toggle the LEDs every second.
My makefile looks like this:
# Name: Makefile
#
# A simple program for the ATMEGA32A-PU that blinks an LED.
#
DEVICE = atmega32
CLOCK = 1000000
PROGRAMMER = -c avrisp
OBJECTS = main.o
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS = -IC:\WinAVR-20100110\avr\include\Timer1
# for ATTiny85 - unset CKDIV8
FUSES = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
# Tune the lines below only if you know what you are doing:
AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)
COMPILE = avr-g++ $(EXTRAINCDIRS) -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)
# symbolic targets:
all: main.hex
.c.o:
$(COMPILE) -c $< -o $#
.cpp.o:
$(COMPILE) -c $< -o $#
.S.o:
$(COMPILE) -x assembler-with-cpp -c $< -o $#
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
.c.s:
$(COMPILE) -S $< -o $#
.cpp.s:
$(COMPILE) -S $< -o $#
flash: all
$(AVRDUDE) -U flash:w:main.hex:i
fuse:
$(AVRDUDE) $(FUSES)
# Xcode uses the Makefile targets "", "clean" and "install"
install: flash fuse
# if you use a bootloader, change the command below appropriately:
load: all
bootloadHID main.hex
clean:
rm -f main.hex main.elf $(OBJECTS)
# file targets:
main.elf: $(OBJECTS)
$(COMPILE) -o main.elf $(OBJECTS)
main.hex: main.elf
rm -f main.hex
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size --format=avr --mcu=$(DEVICE) main.elf
# If you have an EEPROM section, you must also create a hex file for the
# EEPROM and add it to the "flash" target.
# Targets for code debugging and analysis:
disasm: main.elf
avr-objdump -d main.elf
cpp:
$(COMPILE) -E main.c
main.c
#include "TimerOne.h"
#include <avr/io.h>
void refresh();
int main(void)
{
DDRD |= 0xff; //Set PortD Pins as an output
PORTD |= 0xff; //Set PortD Pins high to turn on LEDs
Timer1.initialize(1000000); // 1000000us = 1s
Timer1.attachInterrupt(refresh);
while(1) { } //Loop forever, interrupts do the rest
}
void refresh()
{
PORTD ^= 0XFF;
}
The Error I get when I run make is:
avr-g++ -IC:\WinAVR-20100110\avr\include\Timer1 -Wall -Os -DF_CPU=1000000 -mmcu=atmega32 -c main.c -o main.o
avr-g++ -IC:\WinAVR-20100110\avr\include\Timer1 -Wall -Os -DF_CPU=1000000 -mmcu=atmega32 -o main.elf main.o
main.o: In function `main':
main.c:(.text+0x12): undefined reference to `Timer1'
main.c:(.text+0x14): undefined reference to `Timer1'
main.c:(.text+0x1e): undefined reference to `TimerOne::initialize(long)'
main.c:(.text+0x22): undefined reference to `Timer1'
main.c:(.text+0x24): undefined reference to `Timer1'
main.c:(.text+0x32): undefined reference to `TimerOne::attachInterrupt(void (*)(), long)'
make: *** [main.elf] Error 1
From the looks of it it seems like I haven't properly told the compiler to build the TimerOne library. What am I missing?
I'm running Windows10 x64.

Related

Makefile for AVR

I have folder "I2C AtMega32":
and I have my simply Makefile:
all: main.hex program clean
main.o: main.cpp BMP280_driver-master\bmp280.c
avr-gcc -Wall -Os -mmcu=atmega32 -c $< -o $#
main.elf: main.o
avr-gcc -Wall -Os -mmcu=atmega32 -o main.elf main.o
main.hex: main.elf
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size --format=avr --mcu=atmega32 main.elf
program:
#program uC
.PHONY: clean
clean:
rm main.o main.elf
During the makefile working there is some errors:
Why it is no working?
The main issue is it looks like you are trying to compile two different compilation units into one object file. I would be surprised if GCC supports that, since I've never seen it before. Compile an object with gcc for each C source file, then compile an object with g++ for each C++ source file, then link them all together.
Also note that $< is just the name of the first prerequisite (main.cpp) so you never even attempted to compile the bmp280 code. Pay attention carefully to the commands your Makefile is running when you want to debug your build.
By the way, the all target should just build your HEX file. You can run make program or make clean separately to perform those tasks, and the program target should of course depend on main.hex.

How to compile avr c and c++ source code with make

I was trying to compile some code written in c and c++ for an atmega32u4.
I wrote a makefile from information gathered from the internet, but it fails for some reason.
If I run the commands separately from the command line, they all work. However running the make command gives the following error:
main.cpp:3:10: fatal error: avr/io.h: No such file or directory
The contents of the main.cpp file are not really relevant, it's just a blink code.
The makefile looks like this:
all: init clean $(patsubst %.cpp, %.hex, $(wildcard *.cpp))
avr-size -A $(BUILDPATH)/*.elf
%.c.o: %.c
#mkdir -p $(BUILDPATH)
avr-gcc -c -g -Os -w -mmcu=$(CHIP) $^ -o $(BUILDPATH)/$#
%.cpp.o: %.cpp
#mkdir -p $(BUILDPATH)
avr-g++ -c -g -Os -w -mmcu=$(CHIP) $^ -o $(BUILDPATH)/$#
%.elf: %.o
avr-gcc -g -Os -w -mmcu=$(CHIP) $(BUILDPATH)/$^ -o $(BUILDPATH)/$#
%.hex: %.elf
avr-objcopy -R .eeprom --change-section-lma .eeprom=0 -O ihex $(BUILDPATH)/$^ $(BUILDPATH)/$#
So what am I doing wrong? Do I have to set up some environment variables or is the structure of the makefile incorrect?

GCC for ARM is linking in extra data

I'm currently trying to upload some code onto an LPC810, which is a Cortex-M0+ microcontroller. I have a simple progam I'm trying to use, which just blinks an LED on and off.
typedef unsigned int volatile * vp;
int main()
{
*(vp) 0x4000C1C0 = 0xFFFFFFBFUL;
*(vp) 0xA0002000 |= 1 << 2;
for(;;) {
*(vp) 0xA0002300 |= 1 << 2;
volatile long wait = 240000;
while (wait > 0) --wait;
}
return 0;
}
Edit: This file is called main.c.
I didn't write this code, but I know that it works. The problem is that when I compile this into a binary file to upload, it turns out to be on the order of 75 kiB! That's way too large for my microcontroller.
After running size on the elf file, there seems to be a bunch of extra functions and data being linked in. I'm using newlib.
Below is my Makefile. I'm sure that its probably something to do with my compiling/linking flags, but I've been unable to figure it out.
PROGRAM=hello
ARCH=arm-none-eabi
CC=$(ARCH)-gcc
CXX=$(ARCH)-g++
OBJCOPY=$(ARCH)-objcopy
OBJDUMP=$(ARCH)-objdump
NM=$(ARCH)-nm
SIZE=$(ARCH)-size
FLAGS=-pedantic-errors -Wall -Wextra -Werror -Wfatal-errors -O3 \
-fdiagnostics-color -mcpu=cortex-m0plus -mthumb
CFLAGS=-std=c11 $(FLAGS)
CXXFLAGS=-std=c++14 $(FLAGS)
LDFLAGS=
OBJECTS=./obj/main.o
all: ./$(PROGRAM).hex
run: ./$(PROGRAM).hex
sudo lpc21isp -wipe -verify -bin ./$(PROGRAM).hex /dev/ttyUSB0 115200 12000
make clean
./$(PROGRAM).hex: ./$(PROGRAM).elf
$(OBJCOPY) ./$(PROGRAM).elf -O binary ./$(PROGRAM).hex
$(OBJDUMP) -D $< > $(PROGRAM).disasm
$(NM) -n $(PROGRAM).elf > $(PROGRAM).sym
$(SIZE) $(PROGRAM).elf
./$(PROGRAM).elf: $(OBJECTS)
$(CC) $(FLAGS) $(LDFLAGS) $^ -o $#
./obj/%.o: ./src/%.s
$(CC) $(FLAGS) -c $^ -o $#
./obj/%.o: ./src/%.c
$(CC) $(CFLAGS) -c $^ -o $#
./obj/%.o: ./src/%.cpp
$(CXX) $(CXXFLAGS) -c $^ -o $#
clean:
rm $(OBJECTS) ./$(PROGRAM)*
I'm generating a binary file with a hex extension with this, so sorry about any confusion.
Any thoughts on how to fix this? Thanks for any help!
I'd like to suggest to link with linker option --gc-sections. This should strip all unused library stuff.
Thus, add -Wl,--gc-sections to your LDFLAGS.
However I am pretty sure that your compiler's output is not that big as you think. I assume that your binary file contains lots of zeros. Actually I assume you have less than 265 Bytes of payload and the rest is zero.
This is because your output is linked not to address zero. Check your ELF file with arm-none-eabi -e hello.elf. (You're application code is there in section .text)
To fix this I am pretty sure you have to learn how linker scripts work. Checkout the manual "The GNU linker" for this.
Optimize binaries for space with -Os, not -O3, strip symbols with -s, and get rid of the stdc++ libraries you are linking in (std=c++14), that's not even a C++ program!

makefile for ARM: cannot specify -o with -c or -S and mult compilations

I'm modifying this makefile to use with another project and I get a gcc error saying I cannot specify -o with -c.
The line near the bottom that says:
.c.o:
$(CC) $(CC_FLAGS) ... -o $# &<
has the -o
but CC_FLAGS = $(MCU_CC_FLAGS) -c ...
I don't see how this makefile worked in the first place.

Can't compile simple code with SDCC for pic on debian

I'm trying to compile the following code with SDCC, in Debian using only VIM and a Makefile:
void main(void) {
}
Yes, that simple, it's not working yet. I'm using a Makefile like this :
# GNU/Linux specific Make directives.
# Declare tools.
SHELL = /bin/sh
CC = sdcc
LD = gplink
ECHO = #echo
MCU = 16f88
ARCH = pic14
CFLAGS = -m$(ARCH) -p$(MCU)
LDFLAGS = -c -r -w -m I /usr/share/sdcc/lib/$(ARCH)/
EXECUTABLE = t1
SOURCES = test2.c
OBJECTS = $(SOURCES:.c=.o)
CLEANFILES = test2.o test2.asm test2.map test2.lst
.SUFFIXES: .c .o
.PHONY: clean
# Compile
all: $(EXECUTABLE)
.c.o:
$(AT) $(CC) $(CFLAGS) -o $*.o -c $<
$(EXECUTABLE): $(OBJECTS)
$(AT) $(LD) $(LDFLAGS) $(OBJECTS) -o $(EXECUTABLE)
clean:
$(AT) rm -rf $(CLEANFILES)
After all of this the output after running the makefile is:
sdcc -mpic14 -p16f88 -o test2.o -c test2.c
gplink -c -r -w -m I /usr/share/sdcc/lib/pic14/ test2.o -o t1
make: *** [t1] Segmentation fault
I have tried more complex code with the same result,
I can't see what's wrong, anyone ?
I see several things that can be causing you problems:
When you compile for PICs using SDCC, you need the option --use-non-free because some PIC header files have a special Microchip Licence which is not GPL compatible. Furthermore, --use-non-free might not be available on Debian because of their freedom policy if you installed SDCC from repositories. You would need to install the latest SDCC from the official website.
On the linking stage, you should include the PIC libraries needed to run. Try executing sdcc -mpic14 -p16f88 --use-non-free -V test2.c. This way, SDCC links automatically and With -V (verbose) you can see the calls to assembler and linker and can see the libraries that are added on linkage.

Resources