Using Application Headers

Hi There,

I am trying to utilize the application header feature and am running into a few strange issues. I notice there is no real information on how to use the application header information in the bootloader in any of the documentation I have read so this is how I am going about it:

In the boot loader I am defining the following struct:

typedef struct {
    uint32_t headerVersion;
    uint64_t firmwareVersion;
    uint64_t firmwareSize;
    uint32_t firmwareCRC;
    uint32_t headerCRC;
}__attribute__((__packed__)) app_metadata_v1_t; 

and then in the main function I am casting it to the memory address:
app_metadata_v1_t *active_app_metadata = (app_metadata_v1_t*) HEADER_ADDR;

My mbed_app.json is setup as follows:

		"target.header_format": [
            ["headerVersion", "const", "32le", "2"],
            ["firmwareVersion", "timestamp", "64le", null],
            ["firmwareSize", "size", "64le", ["application"]],
            ["firmwareCRC", "digest", "CRCITT32le", "application"],
            ["headerCRC", "digest", "CRCITT32le", "header"]
        ]

And so, I am getting the following results when I print out the values of the struct:

Header Version = 2
FirmwareVersion = 301989888
FirmwareSize = 301989888

I am not sure why I am getting the exact same value for both Firmware Size and Version as the Header version is coming through correctly. It appears to me that on compile the firmware version and size values are not being populated correctly.

However here is the app_header.hex file generated by the main app:
:020000040002F8
:1000000002000000ED92295F0000000018DD0200F0
:0C0010000000000006AE16E41A6831DBA8
:00000001FF

Line 1 gives me the Header Version number 2 just fine:

:02 0000 04 0002 F8

Line 2 gives me both 64 byte values

:10 0000 00 02000000ED92295F 0000000018DD0200 F0

Line 3 gives me both 32 byte values
:0C 0010 00 00000000 06AE16E4 1A6831DBA8

I would love to hear from anyone who has tried this and had some success! Thanks

1 Like

Continuing the discussion from Using Application Headers:

For anyone who is curious I have managed to find the problem.

I was trying to print a 64bit integer using the ‘0x%016x’ formatter which is incorrect. Instead I used PRIx64 and all is working fine now.

1 Like

Hi Zanev!

Where do you put "target.header_format": [...]? In the mbed_app.json of the firmware application or bootloader? Do you need to set some "target.app_offset": "0x10400", "target.header_offset": "0x10000", also?

So, basically, what can I do with this headers?

Hi @phlegx ,

I actually ditched the target.header_format feature completely as I couldn’t get the flexibility I wanted. There seemed to be an easier way which is what it was try to achieve anyway. But yes I believe you put it in the firmware application mbed.app. You will need to define some offsets there as well but again but unfortunately I can’t remember.

Here is one example of how to handle metadata

  1. Set aside a metadata region of memory, it could be between the Bootloader and the Application. Or at the end of the memory region after the Application.
  2. Define that region of memory as a packed struct.
  3. Create a packed struct in a header file that is shared by both the bootloader and the firmware application that defines the metadata region. (this is similar to what the target.header_format is doing).
  4. In the bootloader and firmware application cast this region of memory to the packed struct.
  5. Compile both the bootloader and the firmware application into binary files and use a small python script to combine them into one binary file, the python script also populates the metadata region.

So, basically, what can I do with this headers?

Well you will start to want them naturally when developing firmware for production… what information is needed by both the firmware application and the bootloader. You will probably want a CRC or hash of some kind to check for corruption of your application code every time your application boots? In this case there is no way to compile your application with a hash because the hash is of the application an therefore impossible so it needs to be calculated after you compile. So then, where do you store it? A good place is the metadata region. This region can then travel with new firmware releases for error checking. Anyway this is just one reason why.

1 Like

Thank you for the reply. :clap: There are many things that are unclear and not well documented. In my case, I have a program bootloader and a program firmware. The code used for the bootloader is from here: GitHub - ARMmbed/mbed-os-example-bootloader: DEPRECATED: example

But…

  1. Do I need to put "target.header_format": [...] on both programs mbed_app.json?
  2. On program bootloader I also define "target.restrict_size": "0x20000", in mbed_app.json. In firmware program I define "target.bootloader_img": "bootloader/my-bootloader.bin". Where do I define app_offset and header_offset?
  3. Where can I found the values for app_offset and header_offset?
  4. In both programs I have defined app_metadata_v1_t struct. But who and when are this values set?

So, there are many questions and I cannot find anything in the docs.

  1. Do I need to put "target.header_format": [...] on both programs mbed_app.json ?

Yes, it says so in the linked bootloader tutorial:

  1. On program bootloader I also define "target.restrict_size": "0x20000", in mbed_app.json . In firmware program I define "target.bootloader_img": "bootloader/my-bootloader.bin" . Where do I define app_offset and header_offset ?

You don’t define app_offset and header_offset in this case - when using the standard mbed bootloader format it works it out for you. It says so in the bootloader tutorial as it is only used in Prebuilt bootloaders which you don’t appear to be using.

  1. Where can I found the values for app_offset and header_offset ?

Calling APPLICATION_ADDR and HEADER_ADDR

  1. In both programs I have defined app_metadata_v1_t struct. But who and when are this values set?

Sorry where is app_metadata_v1_t defined or referenced?

  1. So, there are many questions and I cannot find anything in the docs.

Its all here: Creating and using a bootloader - Program setup | Mbed OS 6 Documentation … it just takes reading about 1000 times before it makes sense or so it did for me. But primarily because it requires a good understanding of how programs are compiled and joined and how variables are referenced in memory.

1 Like

For anyone else reading this in future, this is a great resource for how to create your own metadata header:

https://interrupt.memfault.com/blog/device-firmware-update-cookbook