cgccstm32bootloaderhex-file

Contiguous Hex file generation using GCC


I have a Hex file for STM32F427 that was built using GCC(gcc-arm-none-eabi) version 4.6 that had contiguous memory addresses. I wrote boot loader for loading that hex file and also added checksum capability to make sure Hex file is correct before starting the application. Snippet of Hex file:

:1005C80018460AF02FFE07F5A64202F1D00207F5F9 :1005D8008E4303F1A803104640F6C821C2F2000179 :1005E8001A460BF053F907F5A64303F1D003184652 :1005F8000BF068F907F5A64303F1E80340F6FC1091 :10060800C2F2000019463BF087FF07F5A64303F145 :10061800E80318464FF47A710EF092FC07F5A643EA :1006280003F1E80318460EF03DFC034607F5A64221 :1006380002F1E0021046194601F0F2FC07F56A5390

As you can see all the addresses are sequential. Then we changed the compiler to version 4.8 and i got the same type of Hex file.

But now we used compiler version 6.2 and the Hex file generated is not contiguous. It is somewhat like this:

:10016000B9BC0C08B9BC0C08B9BC0C08B9BC0C086B
:10017000B9BC0C08B9BC0C08B9BC0C08B9BC0C085B
:08018000B9BC0C08B9BC0C0865
:1001900081F0004102E000BF83F0004330B54FEA38
:1001A00041044FEA430594EA050F08BF90EA020FA5

As you can see after 0188 it is starting at 0190 means rest of 8 bytes(0189 to 018F) are 0xFF as they are not flashed.

Now boot loader is kind of dumb where we just pass the starting address and no of bytes to calculate the checksum.

Is there a way to make hex file in contiguous way as compiler 4.6 and compiler 4.8? the code is same in all the three times.


Solution

  • If post-processing the hex file is an option, you can consider using the IntelHex python library. This lets you manipulate hex file data (i.e. ignoring the 'markup'; record type, address, checksum etc) rather than as lines, will for instance create output with the correct line checksum.

    A fast way to get this up and running could be to use the bundled convenience scripts hex2bin.py and bin2hex.py:

    python hex2bin.py --pad=FF noncontiguous.hex tmp.bin
    python bin2hex.py tmp.bin contiguous.hex
    

    The first line converts the input file noncontiguous.hex to a binary file, padding it with FF where there is no data. The second line converts it the binary file back to a hex file.

    The result would be

    :08018000B9BC0C08B9BC0C0865
    

    becomes

    :10018000B9BC0C08B9BC0C08FFFFFFFFFFFFFFFF65
    

    As you can see, padding bytes are added where the input doesn't have any data, equivalent to writing the input file to the device and reading it back out. Bytes that are in the input file are kept the same - and at the same address. The checksum is also correct as changing the length byte from 0x08 to 0x10 compensates for the extra 0xFF bytes. If you padded with something else, IntelHex would output the correct checksum

    You can skip the the creation of a temporary file by piping these: omit tmp.bin in the first line and replacing it with - in the second line:

    python hex2bin.py --pad=FF noncontiguous.hex | python bin2hex.py - contiguous.hex
    

    An alternative way could be to have a base file with all FF and use the hexmerge.py convenience script to merge gcc's output onto it with --overlap=replace

    The longer, more flexible way, would be to implement your own tool using the IntelHex API. I've used this to good effect in situations similar to yours - tweak hex files to satisfy tools that are costly to change, but only handle hex files the way they were when the tool was written.