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!
Related
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.
I have a need to generate a few object files with different load addresses. I also have a make target for invoking objdump to show me the respective disassembly.
code0:
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE0_RELOC) $#.S -o $#.o
objcopy -O binary $#.o --only-section=.text $#.bin
code1:
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE1_RELOC) $#.S -o $#.o
objcopy -O binary $#.o --only-section=.text $#.bin
dump: dump_code0 dump_code1
dump_code0: code0.bin
objdump $< -D > $<.decomp
dump_code1: code1.bin
objdump $< -D > $<.decomp
This will fail because there is no target for code.bin, but target dump_code depends on code.bin being present. To prevent it from being confusing (i.e. using dependency code0 such that code0.bin is then produced) I thought it would be easier to create a %.bin target that will create the respective binary file associated with each object file (since there is also duplication of this code across all code* targets anyway. This target will then be a dependency for each code* target. However, this necessitates (or at least I think it does) the need for dynamically assigning dependencies. I tried something like this that did not work:
%.bin: $(basename $#)
objcopy -O binary $(basename $#).o --only-section=.text $#.bin
code0: code0.bin
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE0_RELOC) $#.S -o $#.o
With the logic being that a dependency such as code0.bin would cause this target to execute with the single effective dependency of code0 to first build the object file.
I may be misunderstanding how the % character may be used to wildcard make targets. The first usesof basename was evaluating as empty (the second worked), so the target had no dependencies. It does make sense that the dependency tree be evaluated once at invocation, but I was hoping for a more dynamic capability.
Can this be done in Make?
What you are looking for is probably Static Pattern Rules with which you could rework your first attempt:
code0:
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE0_RELOC) $#.S -o $#.o
objcopy -O binary $#.o --only-section=.text $#.bin
as:
code0.o code1.o: code%.o: code%.S
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE$*_RELOC) $< -o $#
code0.bin code1.bin: %.bin: %.o
objcopy -O binary $< --only-section=.text $#
See the principle? $* in the recipe of the first rule is substituted by the matching stem of the static pattern rule (the digit in our case). This works but pattern-specific variables would probably be easier to understand and maintain:
# Default code reloc option
CODE_RELOC := default_code_reloc_option
# code1-specific code reloc option, if different from default
code1.o: CODE_RELOC := code1_code_reloc_option
code0.o code1.o: %.o: %.S
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE_RELOC) $< -o $#
The last part of your first makefile could also use static pattern rules, plus phony targets. Something like:
.PHONY: dump dump_code0 dump_code1
dump: dump_code0 dump_code1
dump_code0 dump_code1: dump_%: %.bin.decomp
code0.bin.decomp code1.bin.decomp: %.bin.decomp: %.bin
objdump $< -D > $#
Finally, we can use some more make tricks (discovery of source files, pattern substitutions) to automate a bit further:
CODES := $(wildcard *.S)
OBJS := $(patsubst %.S,%.o,$(CODES))
BINS := $(patsubst %.S,%.bin,$(CODES))
DECS := $(patsubst %.S,%.bin.decomp,$(CODES))
DUMPS := $(patsubst %.S,dump_%,$(CODES))
# Default code reloc option
CODE_RELOC := default_code_reloc_option
# code1-specific code reloc option, if different from default
code1.o: CODE_RELOC := code1_code_reloc_option
.PHONY: dump $(DUMPS)
dump: $(DUMPS)
$(DUMPS): dump_%: %.bin.decomp
$(DECS): %.bin.decomp: %.bin
objdump $< -D > $#
$(BINS): %.bin: %.o
objcopy -O binary $< --only-section=.text $#
$(OBJS): %.o: %.S
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE_RELOC) $< -o $#
.PHONY: clean
clean:
rm -f $(OBJS) $(BINS) $(DECS)
The clean target is a bonus gift.
All this has a significant advantage over what you were trying to do with targets that were not real files. Here, files depend on other files, except the phony targets that are just a kind of shorthand for real target files. And this is 100% in line with make's philosophy: express inter-files dependences such that make compares files timestamps and decides what is up-to-date and what must be rebuilt. Significant savings when a lot of targets are already up-to-date.
A second advantage is that expressing all inter-files dependences is parallel safe. If you run make on this makefile with:
make -j 8
(assuming you have about 8 cores on your computer), you can expect a speed-up factor of 8. Not much if you have only two source files, but quite interesting if you have hundreds of them...
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.
I am trying to understand makefile.
I took atmega168 bootloader's makefile and simplified it to this:
CC = avr-gcc
override CFLAGS = -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600
atmega328: ATmegaBOOT_168_atmega328.hex
%.elf: ATmegaBOOT_168.o
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o $# $<
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
%.hex: %.elf
avr-objcopy -j .text -j .data -O ihex $< $#
When I ran $ make atmega328 I get:
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -c -o ATmegaBOOT_168.o ATmegaBOOT_168.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o
avr-objcopy -j .text -j .data -O ihex ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168_atmega328.hex
rm ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o
Why cannot I remove CC or CFLAGS?
I understand some basics of makefile. I read a lot on the internet, plus went through gnu manual, but I cannot understand the very first output with ATmegaBOOT_168.c. What/How has generated first command?
Was there used some second makefile? If yes, how to find its location?
UPDATE:
If I rename ATmegaBOOT_168.c to ATmegaBOOT_1681.c. Running $ make atmega328 gives:
make: *** No rule to make target 'ATmegaBOOT_168_atmega328.hex', needed by 'atmega328'. Stop.
but the rule is present.
CC and CFLAGS are variables used in the built in implicit rules of GNU make. When you run make, it reads your makefile a bit like:
No target given, so we'll make the first: atmega328. This requires a .hex file.
The .hex file can be generated from a .elf file per the last rule.
.elf files can be generated by the %.elf rule (which here looks like you've broken the pattern, as there's no % in the dependencies).
There's no rule for .o in this file, so the default recipe $(CC) $(CPPFLAGS) $(CFLAGS) -c is used. Since a .c file is found, this rule is applicable and generates the first command. The rule could have been written (as shown in suffix rules):
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
Backtrack up this list, now that the source has been found, and run the commands.
If the implicit rule variables are left unset, you will typically get programs built for your host system using cc.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have 3 files: MyLib.h MyLib.c Tester.c
I've been trying to create the makefile but it is proving difficult.
I can do it when it is only one file, like below where I am compiling Hello.c
I have seen some examples but they seem a lot more complicated than the one I am using below -- which sort of makes sense to me.
BINDIR = /usr/local/sbin
CC = gcc
CFLAGS = -O
all: Hello
Hello: Hello.o
${CC} ${CFLAGS} Hello.o ${LDFLAGS} -o Hello
Hello.o: Hello.c
${CC} ${CFLAGS} -c Hello.c
install: all
rm -f ${BINDIR}/Hello
cp Hello ${BINDIR}/Hello
clean:
rm -f Hello *.o core core.* *.core
Please help.
I been typing this every time I turn on my computer, kind of annoying by now.
gcc MyLib.c Tester.c -o Tester
Presuming MyLib.h is a dependency for both of your C files, you should have something like this:
# Variables
CC := gcc
CFLAGS := -O
# Link executable
Tester: MyLib.o Tester.o
${CC} MyLib.o Tester.o ${LDFLAGS} -o Tester
# Compile object files
MyLib.o: MyLib.c MyLib.h
${CC} ${CFLAGS} -c -o MyLib.o MyLib.c
Tester.o: Tester.c MyLib.h
${CC} ${CFLAGS} -c -o Tester.o Tester.c
and, once you've got the hang of how things work, you can use the automatic variables as your second step in reducing code duplication:
# Variables
CC := gcc
CFLAGS := -O
# Link executable
Tester: MyLib.o Tester.o
${CC} $^ ${LDFLAGS} -o $#
# Compile object files
MyLib.o: MyLib.c MyLib.h
${CC} ${CFLAGS} -c -o $# $<
Tester.o: Tester.c MyLib.h
${CC} ${CFLAGS} -c -o $# $<
where $# is the replaced by the name of the target for the current rule, $< is replaced by the first (i.e. leftmost) dependency, and $^ is replaced by the full list of dependencies.
In the above, the bits after the : are dependencies, i.e. the target to the left of the : will be made/remade if any of the dependencies are more recent than the target. For each of the dependencies, make will look for a target for it. So, for the first section, it sees that MyLib.o and Tester.o are dependencies for your overall executable, and it looks for targets for them, which are provided. Finding the targets, it builds them (if necessary) and then proceeds to build Tester.
Note that CFLAGS conventionally represents compilation flags, so you don't need to pass them when you're only linking since no compilation is being done at that point.
Also, if you're struggling with this kind of thing, then simplify, and remove all the additional targets (such as clean and install and all) until you've got the hang of what's going on.
Crude but effective:
Tester:
gcc MyLib.c Tester.c -o Tester
Better:
CC = gcc
Tester: MyLib.o Tester.o
$(CC) $^ -o $#
And I'll just make a guess about dependency:
MyLib.o Tester.o : MyLib.h
More sophisticated makefiles are possible, but this should do for now.