Electronic – Why is this hex file different than the code programmed onto the device

firmwaremicrocontrollerprogrammingstm32stm32f10x

I have a design using an STM32F105. My application written in C; using Eclipse and gcc. I have been using Eclipse (with OpenOCD and an ST-LINK/V2 programmer) to write the firmware to the devices. Now I need to program many devices and am looking for a faster method.

The ST-LINK Utility software seems to be a fine choice. You can point it to a .hex file and set it into "automatic mode". It then detects when a device is connected to the programmer and writes to it. Then you connect another device which will get automatically written. Very smooth.

So here's the problem: It appears that the firmware written to the device by Eclipse is actually different than the Eclipse-generated hex file.

This is what I'm seeing:

  1. I program Device#1 via Eclipse. I remove the programmer, reset the device, and it works fine.
  2. I find the Eclipse-generated .hex file (…/Debug/application.hex).
  3. I program Device#2 using the ST_LINK Utility and this file. I remove the programmer. The code doesn't run, even after a device reset.
  4. I use the ST-LINK Utility to read the (working) code directly from Device#1.
  5. I use the ST-LINK Utility to program this code onto Device#2. Now, Device#2 works correctly.

OK, so the generated .hex file must be wrong. I can use the ST-LINK utility to compare the two hex files (from steps 2 and 4). It shows that the files are identical until the end:

(click to zoom if you need to)

hexcomp


Finally, my questions:

Why is the generated .hex file incorrect? Perhaps Eclipse uses gcc to create the hex, and then modifies it en route to the device? How can I make Eclipse output a hex file that matches the code that it programs to an actual device?


Note that I am building the "Debug" configuration. When Eclipse connects to the target device it programs the code and allows me to debug. If I remove the debugger hardware, the device still functions. That is, the code works fine without the debugger attached.

Best Answer

Perhaps Eclipse uses gcc to create the hex, and then modifies it en route to the device?

No, it's the other way round. When you compile a project in Eclipse,

  1. individual files are compiled into .o object files
  2. object files and libraries are linked into an .elf file
  3. objcopy generates a .hex file from .elf
  4. and finally the size is printed by size, but this last step is purely informational.

The debugger however works with the .elf from step 2, because it has symbols and other debugging aids in it, which are lost when converting to .hex. Therefore, I'd take a very close look at step 3, and perhaps at the .elf file too.

This is how step 3 should look like in the eclipse build console window

Finished building target: app.elf

Invoking: Cross ARM GNU Create Flash Image
arm-none-eabi-objcopy -O ihex "app.elf"  "app.hex"
Finished building: app.hex

Invoking: Cross ARM GNU Print Size

First, check if there are any warnings or other suspicious signs. Is it regenerated when you remove it, and build the project? And when you remove the .elf? Are the file timestamps correct? Try to repeat it from the command line. For that to work, you'll have to specify the full path to arm-none-eabi-objcopy in your toolchain, or include it in your PATH. Make sure that the toolchain path is properly set in eclipse, and there are no other versions of objcopy lying around, especially in your PATH.

You can examine the .elf with arm-none-eabi-objdump. List the "directory" with -h, it looks like this

app.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .isr_vector   0000013c  08008000  08008000  00008000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         0000b4cc  08008140  08008140  00008140  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       0000b1c0  08013610  08013610  00013610  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .ARM          00000008  0801e7d0  0801e7d0  0001e7d0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .init_array   00000008  0801e7d8  0801e7d8  0001e7d8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .fini_array   00000004  0801e7e0  0801e7e0  0001e7e0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  6 .data         00000a60  20000000  0801e7e4  00020000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  7 .noinit       00000004  20000a60  0801f244  00020a60  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  8 .bss          0000cbf8  20000a68  0801f248  00020a68  2**3
                  ALLOC

Check the LMA and Size fields for each section. Is there an overlap? Dump the contents with -s and examine it around the problem address.