Search code examples
c++ccmakezephyr-rtos

Building multiple binaries in CMake from Zephyr RTOS project, each with different device address


I have a project that consists of nodes in a mesh, that will communicate between each other wirelessly and will identify each other with a use of addresses.

Nodes will be equivalent in their responsibilities so the source code for each them will be identical, except for address which I would like to be specific and unique for each.

This project will be a kind of demo, or technology demonstration so for simplicity I do not want to introduce some address negotiations or anything complex like that.

I was researching and found some suggestions to use target_compile_definitions in CMake but I am not really sure how to apply it to generic Zephyr CMakeLists.txt:

set(BOARD qemu_x86)

find_package(Zephyr)
project(my_zephyr_app)

target_sources(app PRIVATE src/main.c)

So I was wondering what is the best way to do that? Is there a way to do that in CMake (I am quite a noob yet when it comes to CMake)? Or should I tinker with some Python script?

EDIT: And I was thinking if maybe doing something like #define <device_addr> from level of CMake is possible, and then repeating that X times for the rest of the devices. So in the end I would have X binaries that will differ only in regard to that #define <device_addr>.

Thank You for responses in advance.


Solution

  • Create a custom ELF section in your project with the address. Use compiler specific syntax. This is for GCC compiler:

    // volatile, so that optimizer does not bite us
    __attribute__((__section__("myaddress")))
    __attribute__((__used__))
    volatile const uint8_t _address[20] = {0};
    
    # external API - fetch the address
    # remove volatile for usage for optimizations
    uint8_t *get_address(uint8_t buffer[20]) {
          memcpy(buffer, _address, sizeof(_address));
          return address;
    }
    

    At best create a linker file so that your section will be placed in .rodata read only memory.

    Build one ELF file.

    Create a short script. This script will replace the content of the section in the generated ELF file with your custom data - the actual address. Use objcopy --update-section myaddress=filename to update the section, where filename has the binary content of the section. Repeat objcopy for every address. The best would be to write that script in CMake - research CMakeFindBinUtils and add_custom_command + add_custom_target and generator expression with $<TARGET_FILE:app>.

    Then use objcopy on generated ELF files to generate bin files.

    Overall, this sounds like an odd approach, because every device has some "identification number", "manufacturer number" etc. stored in some read-only device specific memory. Strongly consider reading that number and just using it as an address.