Pass makefile variable to linker section

Viewed 2062

I have a bootloader and application in the same flash that are built separately. I always start in bootloader, and before I jump to application I want to use crc32 on the application to verify that it is not corrupted. Therefor I need to calculate and save the crc32 of the application to a known address when building the application in order to later reach it from the bootloader. In the makefile of the application I want to save the result of a shell command calculating the crc to a variable, and then save that variable at a specified address in memory. So I wonder if it is possible to pass a variable from the makefile to the linker-script in order to save the crc32 result to a specified memory section. What I'm thinking is something like:

Makefile:

CC = arm-none-eabi-gcc
CFLAGS = -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -std=c99
CRC_RESULT = '"$(shell get_crc...)"'

$(CC) $(CFLAGS) -T"LinkerScript.ld" -Wl,-Map=output.map -Wl,CRC_RESULT -Wl

Linker-script:

MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08002000, LENGTH = 64K - 0x2000 - 0x04
  CRC (rx)        : ORIGIN = 0x0800FFFC, LENGTH = 0x04
  RAM (xrw)       : ORIGIN = 0x200000c0, LENGTH = 8K
}

SECTIONS
{
....
    .CrcSection :
  {
    CrcSection = CRC_RESULT;
  } > CRC
}

What I've heard it should be possible to directly change the binary file with the crc result in the makefile (not sure of this), but this feels a bit like a hack. In my eyes it would be more straight forward to directly put the variable at the correct memory section. As you might see, I'm very new to both makefiles and linker-scripts.

2 Answers

The linker is not actually meant to generate/modify code. I'm not aware of a method for making it populate a particular section based on command-line parameters. You might be able to do something to the effect of:

crc.o: app_build_target
    echo "const char *APP_CRC=\"$(shell get_crc ...)\";" | $(CC) -c -o $@ -xc -

bootloader_build_target: crc.o $(BOOTLOADER_OBJS)
    $(LD) -o $@ $^ 

This compiles a file that just generates a single variable, and then links it in with all the other objects. You would need to declare extern const char * APP_CRC; in your bootloader code before you use it.

For the $(CC) command used:

  • -c specifies not to link (i.e. prevents the undefined reference to main())
  • -o $@ specifies the target
  • -xc tells the compiler what language it's parsing (required here...)
  • - tells the compiler to take input from stdin

This works for me:

CRC_RESULT = '"$(shell get_crc...)"'

a.out:    
    $(CC) $(CFLAGS) -T"LinkerScript.ld" -Wl,-Map=output.map -Wl,CRC_RESULT -Wl,'--defsym=CRC_RESULT=$(CRC_RESULT)'
Related