Incorrect AVR sub-arch when linking in custom binary data

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Freaks,

A new hairy problem I've encountered in AVR-GCC.

Essentially, I'm trying to embed a file "InputEEData.bin" (raw binary) into the PROGMEM space of a custom application, so that I can read it out at runtime with the appropriate pgm_read_*() macros.

To do this, I'm following the avr-libc FAQ entry at http://www.nongnu.org/avr-libc/u... . So far so good, my makefile generates a nice InputEEData.o file from the input InputEEData.bin file with the appropriate renamed symbols:

InputEEData.o: InputEEData.bin $(MAKEFILE_LIST)
  avr-objcopy -I binary -O elf32-avr -B avr \
    --rename-section .data=.progmem.data,contents,alloc,load,readonly,data \
    --redefine-sym _binary_InputEEData_bin_start=InputEEData \
    --redefine-sym _binary_InputEEData_bin_end=InputEEData_end \
    --redefine-sym _binary_InputEEData_bin_size=InputEEData_size_sym \
    InputEEData.bin InputEEData.o

Now the problem. When I compile my application for the atmega48, everything works. However, when I rebuild for some other AVRs such as the at90usb162, linking fails with the message:

ld.exe: avr architecture of input file `InputEEData.o' is incompatible with avr:35 output

Or something similar, replacing "avr:35" with "avr:{some number}".

If I change the "-B avr" parameter of avr-objcopy to "-B avr35" linking works, however I'm looking for a more general solution that will allow me to compile with any input MCU model.

Any ideas?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like a good thing to do. Like LCD custom character images, for example. You might be able to do that by hand for 1 or 2 characters, but more becomes a pain.

No idea how to solve your problem. I had no idea even where to start, so you have provided more than I was previously able to do!

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying to make a workaround for my HID class bootloader - the protocol and size doesn't allow for EEPROM programming of the device. To fix that, I've made a shim application that copies out the embedded binary array from PROGMEM into EEPROM on startup. Calling the appropriate build module target extracts the user application EEP file containing the EEPROM data, converts it to a binary file, then embeds that into an object file before rebuilding the shim app and programming it into the target.

Or at least, that's the plan. The link failure when building for the specific AVR models I'm interested it is throwing a wrench into the works. Once it's fixed I'll post full details of how it all works on my blog so that others can use it.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

IIRC you need to supply particular architecture (i.e. avrN) as parameter of -B switch.

I encountered similar problems, see item 5 in https://www.avrfreaks.net/index.p... and subsequent discussion (especially my bogus bug report at binutils tracker).

The approach of binutils in this regard changes slightly in time so you might get plagued with varying behaviour across various versions.

As an ugly but working alternative, you can always go the "binary-to-C-source-then-compile" way, too; IIRC srecord supports this sort of conversion too.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

IIRC you need to supply particular architecture (i.e. avrN) as parameter of -B switch.

Yes, that does seem to be the key - I just don't know how to convert automatically between "MCU:x" and "avr:y".

Quote:

As an ugly but working alternative, you can always go the "binary-to-C-source-then-compile" way, too; IIRC srecord supports this sort of conversion too.

Not as sexy a solution, but I just need one that works. However, I'd prefer if possible to use nothing but the tools available in the WinAVR or Atmel Toolchain and MSys, so my users aren't stuck downloading a trillion tools to get the job done.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'd prefer if possible to use nothing but the tools available in the WinAVR or Atmel Toolchain and MSys, so my users aren't stuck downloading a trillion tools to get the job done.

What a shame WinAVR does not include xxd.exe ! Sadly the users would have to download the vim.zip to get access to that single .exe

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When in doubt, add more shell scripting. I've temporarily solved it with this abomination:

.PHONY: InputEEData.o
InputEEData.o: InputEEData.bin $(TARGET).o $(MAKEFILE_LIST)
	avr-objcopy -I binary -O elf32-avr -B avr$(shell avr-objdump -f $(TARGET).o | grep architecture | cut -d':' -f3 | cut -d',' -f1) \
	  --rename-section .data=.progmem.data,contents,alloc,readonly,data \
	  --redefine-sym _binary_InputEEData_bin_start=InputEEData \
	  --redefine-sym _binary_InputEEData_bin_end=InputEEData_end \
	  --redefine-sym _binary_InputEEData_bin_size=InputEEData_size_sym \
	  $< $@

Which works by specifying the object file of the main application C file as a prerequisite, forcing it to be built first. It then uses the above grep-cut-cut magic to parse out the information from avr-objdump into the correct AVR sub-architecture, and feeds that into avr-objcopy.

No, I'm not proud of this, no, I don't want this to be a permanent solution.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With hexdump and sed, I think that generating a .c file could be a little bit tidier.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:
Yes, that does seem to be the key - I just don't know how to convert automatically between "MCU:x" and "avr:y"
Process the string
`avr-gcc -print-multi-directory -mmcu=atmega8`

with a tool of your choice, sed or whatever: Map "/" and "tiny-stack" to "" and then "." and "" to "avr2".

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there an explanation and example for us mere mortals?

Thanks
jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks SprinterSB, I was afraid there wasn't an easier way to do this (I was hoping for a generic sub-arch, since the data isn't supposed to be executable). In that case, I might as well continue on with what I have.

I managed to simplify it a bit:

https://github.com/abcminiuser/l...

Which apparently works great - the use runs "make hid-ee" in their project, and it extracts out the EEPROM data, compiles the loader shim app, embeds the EEPROM image and then runs it on the target to update the EEPROM data.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a two process solution (if gawk is acceptable)

avr-objdump -f $(TARGET).o | gawk -F'[:,]' '/^architecture:/{print $3}'
=======================================================================
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is there an explanation and example for us mere mortals?

Jim

Did you see the link Dean gave in the first post:

http://www.nongnu.org/avr-libc/u...

For most of us working on just one model of AVR that is all you really need to know. The reason for this thread is that Dean wants to provide a binary built for one architecture of AVR that can be used with all and hence the reason to dynamically try and adapt it for the architecture of the current build target.

But us mere mortals don't need to worry about this. The key thing for us is that if we have a foo.bin with a table of data or soemthing that we want built into an AVR project the text at the link shows how to convert this int oa linkable .o and how to then access the data.

In the old days the alternative would have been to use a utility (such as xxd.exe) to convert the binary back to C source (an initialised array) and then add that as a source file to the project.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can't use AWK as it's not in WinAVR 2010 (yes, some people still use that, and I need to support both it and the newer AVR Toolchain + MSys/Cygwin) but "sed" is available:

avr-objdump -f $(TARGET).o | sed -e "/architecture: /!d" -e "s/.*avr:\(.\).*/avr\1/g"

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I can't use AWK as it's not in WinAVR 2010

Maybe not your copy but in mine:

E:\WinAVR-20100110\utils\bin>dir ga*
 Volume in drive E is VBOX_windows
 Volume Serial Number is 0000-0805

 Directory of E:\WinAVR-20100110\utils\bin

19/01/2010  19:10           149,504 gawk.exe

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dean,

while you have all the information above in hand and a fresh first-hand experience, may I suggest you to post a patch for the said doc chapter to the avr-libc tracker?

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:

Quote:

As an ugly but working alternative, you can always go the "binary-to-C-source-then-compile" way, too; IIRC srecord supports this sort of conversion too.

Not as sexy a solution, but I just need one that works. However, I'd prefer if possible to use nothing but the tools available in the WinAVR or Atmel Toolchain and MSys, so my users aren't stuck downloading a trillion tools to get the job done.

I am not pushing this solution, just want you to know that srecord is present in both in WinAVR and the "toolchain".

You might get confused by the fact that srecord is just name of the project and the three binaries of it are called srec_cat (that's the main one), srec_cmp and srec_info (*.exe where applicable); you can find the "srecord" name mentioned in the documentation.

JW