The GNU linker avr-ld cannot handle binary data directly. However, there's a companion tool called avr-objcopy. This is already known from the output side: it's used to extract the contents of the linked ELF file into an Intel Hex load file.

avr-objcopy can create a relocatable object file from arbitrary binary input, like

avr-objcopy -I binary -O elf32-avr foo.bin foo.o

This will create a file named foo.o, with the contents of foo.bin. The contents will default to section .data, and two symbols will be created named _binary_foo_bin_start and _binary_foo_bin_end. These symbols can be referred to inside a C source to access these data.

If the goal is to have those data go to flash ROM (similar to having used the PROGMEM attribute in C source code), the sections have to be renamed while copying, and it's also useful to set the section flags:

avr-objcopy --rename-section .data=.progmem.data,contents,alloc,load,readonly,data -I binary -O elf32-avr foo.bin foo.o

Note that all this could be conveniently wired into a Makefile, so whenever foo.bin changes, it will trigger the recreation of foo.o, and a subsequent relink of the final ELF file.

Below are two Makefile fragments that provide rules to convert a .txt file to an object file, and to convert a .bin file to an object file:

$(OBJDIR)/%.o : %.txt
        @echo Converting $<
        @cp $(<) $(*).tmp
        @echo -n 0 | tr 0 '\000' >> $(*).tmp
        @$(OBJCOPY) -I binary -O elf32-avr \
        --rename-section .data=.progmem.data,contents,alloc,load,readonly,data \
        --redefine-sym _binary_$*_tmp_start=$* \
        --redefine-sym _binary_$*_tmp_end=$*_end \
        --redefine-sym _binary_$*_tmp_size=$*_size_sym \
        $(*).tmp $(@)
        @echo "extern const char" $(*)"[] PROGMEM;" > $(*).h
        @echo "extern const char" $(*)_end"[] PROGMEM;" >> $(*).h
        @echo "extern const char" $(*)_size_sym"[];" >> $(*).h
        @echo "#define $(*)_size ((int)$(*)_size_sym)" >> $(*).h
        @rm $(*).tmp

$(OBJDIR)/%.o : %.bin
        @echo Converting $<
        @$(OBJCOPY) -I binary -O elf32-avr \
        --rename-section .data=.progmem.data,contents,alloc,load,readonly,data \
        --redefine-sym _binary_$*_bin_start=$* \
        --redefine-sym _binary_$*_bin_end=$*_end \
        --redefine-sym _binary_$*_bin_size=$*_size_sym \
        $(<) $(@)
        @echo "extern const char" $(*)"[] PROGMEM;" > $(*).h
        @echo "extern const char" $(*)_end"[] PROGMEM;" >> $(*).h
        @echo "extern const char" $(*)_size_sym"[];" >> $(*).h
        @echo "#define $(*)_size ((int)$(*)_size_sym)" >> $(*).h

Back to FAQ Index.