Is it possible to use non-absolute address range in SRecord and paste some data on the last bytes of binary file?

1

I'm making project for ARM Cortex-M4 microcontroller using STM32CubeIDE (Eclipse based IDE with gcc compiler) and want to embed CRC of whole firmware in the end of binary file. I have already modified linker script to create some variables placed in the end of compiled binary file. Here is my modifications of linker script:

... linker script ...
  /* My section (it is the last section in linker script) */
  .end_of_code :
  {
    . = ALIGN(4);
    KEEP (*(.end_of_code.fwSize)) /* Force memory allocation even if variable is unused */
    KEPP (*(.end_of_code.fwCrc)) /* Force memory allocation even if variable is unused */

    _end_of_code = .; /* Get current address */
    _size_of_code = ABSOLUTE (_end_of_code - ORIGIN(FLASH)); /* Subtruct current address from start of image */
  } >FLASH

And here is declaration of above variables in C:

// Some C file

extern uint32_t _size_of_code; // Linker variable

const __attribute__((section(".end_of_code.fwSize"))) uint32_t fwSize = (uint32_t) &_size_of_code;
const __attribute__((section(".end_of_code.fwCrc"))) uint32_t fwCrc = 0xFFFFFFFF;

The last variable created with linker script should store CRC32 of whole firmware. I want to use SRecord script to calculate CRC value and want to be able refer to it value like to normal variable in C code.

My goal is to make SRecord script which will open the file using -binary format, replace last 4 bytes with CRC32 calculated by SRecord and make output with replaced CRC value. But I don't understand how to put non-absolute address-range to -crop or -exclude filters. I want to do something like this:

# SRecord script
fw.bin -binary
-CRC32 -maximum-addr fw.bin -binary -4
-o fw_with_CRC.bin -binary

My question is: Is it possible and how to use relative addresses with SRecord? Or is it possible and how to overwrite some data in the end of binary file with SRecord?

About alternative solutions: I know that I can delete fwCrc variable from linker and create something like this:

#define FW_CRC_ADDR    ( ((uint32_t) &fwSize) + 0x04 )
#define GET_FW_CRC()   ( *(uint32_t *) FW_CRC_ADDR )

but such solution not accaptable for me. I want to have variable which stores CRC value. Solutions which instert some data/variables instead of unused interrupt vector elements not accaptable too.

Maybe I can accept solution where fwCrc variable doesn't allocate any memory and append CRC to the end of binary file with SRecord, but I don't know how to force linker does not allocate memory for variable used in C code.

c
binary
microcontroller
crc
srecord
asked on Stack Overflow Sep 26, 2020 by Maksym Samborskyy • edited Sep 26, 2020 by Maksym Samborskyy

1 Answer

0

I found solution which can be helpful for someone, but it's does not directly answer to my question about relative adressing in SRecord. This solution describe how to append CRC to firmware image and have access to CRC value in C like to noramal variable.

Solution was tested with GCC compiler and linker script genereted by STM32CubeIDE.

  1. Type of linker section which store CRC value should be changed to (NOLOAD). It forces linker does NOT allocate memory for variables assigned to this section in binary image. More information about (NOLOAD) can be found here.
... linker script ...

  /* Last section in linker script */
  .end_of_code :
  {
    . = ALIGN(4);
    KEEP (*(.end_of_code.fwSize)) /* Last variable in flash memory */

    _end_of_code = .; /* Get current address */
    _size_of_code = ABSOLUTE (_end_of_code - ORIGIN(FLASH)); /* Subtruct current address from start of image */
  } >FLASH

  /* New section for CRC */
  .crc (NOLOAD) :
  {
    . = ALIGN(4);
    
    *(.crc.fwCrc))
    
    . = ALIGN(4);
  } >FLASH

... /DISCARD/ ...

} /* SECTIONS */
  1. Append CRC to firmware to it max address, for example during post build command execution:
srec_cat infile.bin -binary -STM32 -maximum-addr infile.bin -binary -o outfile.bin -binary
  1. Declare C variable with right __attribute__:
const __attribute__((section(".crc.fwCrc"))) uint32_t fwCrc;

Above manipulations will create firmware image with CRC appended to it. CRC value can be accessed like normal C variable using fwCrc variable. const qualifier was used, because value of this variable stored in FLASH memory and can not be changed directly with assignment operators like =.

answered on Stack Overflow Oct 10, 2020 by Maksym Samborskyy • edited Oct 10, 2020 by Maksym Samborskyy

User contributions licensed under CC BY-SA 3.0