GCC Linker per Linker Script oder über Kommandozeile Parameter zum Setzen einer Konstante mitgeben

OP #7451610
Lesenswert?

Hallo,

besteht eine Möglichkeit dem Linker einen uint32 Wert mitzugeben und damit eine Konstante zu initialisieren.

1
const uint32_t app_checksum __attribute__((section(".appdata"), used)) = 0xAABBCCDD;
2
const uint32_t app_numpages __attribute__((section(".appdata"), used)) = 100;   // num of 2kB pages
1
  /* Constant data into "FLASH" Rom type memory */
2
  .rodata :
3
  {
4
    . = ALIGN(4);
5
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
6
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
7
    KEEP(*(.appdata))   /* checksum and length of the app */
8
    . = ALIGN(4);
9
  } >FLASH
1
$ arm-none-eabi-objdump.exe -s -j .rodata const_var.elf
2
const_var.elf:     file format elf32-littlearm
3
Contents of section .rodata:
4
 8002bc0 00000000 00000000 01020304 06070809  ................
5
 8002bd0 02030405 06070809 0a0b0c0d 0e0f1010  ................
6
 8002be0 01020304 05060708 090a0b0c 0d0e0f10  ................
7
 8002bf0 ddccbbaa 64000000                    ....d...
8
 ^addr   ^value

Erste Idee war mit einem Binary Editor den Wert auszutauschen und dann HEX daraus zu machen. Diese Vorgehensweise lässt sich nicht robust per Makefile umsetzen, da die Variablenaddressen sich ändern.

Zweite Idee war die GCC Toolchain dafür einzusetzen. Hat jemand ein Beispiel wie man mit objcopy einen Wert in einer Sektion austauschen kann? Am besten mit Referenz auf Symbol und nicht eine Adresse. Hat jemand vielleicht ein Beispiel wie man mit ld das machen kann? Kann man da nicht mit

1
_vorher = .;
2
KEEP(*(.appdata))   /* checksum and length of the app */
3
_nacher = .;

die Adresse herausfinden und diese zum Setzen neuer Werte benutzen?

ChatGPT hat mir elftools aufschwatzen wollen. Die elf Datei ist danach vom 2Meg auf 200Meg gegangen. Warum ist mir noch nicht klar. Wird da beim Schreiben auf eine Adresse der ganze Adressraum ausgerollt?

Bisher habe ich zum Ablegen der Checksumme srec_cat benutzt. srec_cat in.hex -intel -crop 0x08000000 0x0803EFFC -STM32 0x0803EFFC -o out.hex -intel Allerdings wird hier ganze Page für 32bit Checksumme verbraucht. Und damit die Checksumme passt, sind -fill 0xFF und -unfill 0xFF Aufrufe notwendig.

Viele Grüße

(Firma: RUB) #7451614
Lesenswert?

Du suchst die Option -D https://www.rapidtables.com/code/linux/gcc/gcc-d.html

https://www.man7.org/linux/man-pages/man1/gcc.1.html

1
       -D name
2
           Predefine name as a macro, with definition 1.
3

4
       -D name=definition
5
           The contents of definition are tokenized and processed as if
6
           they appeared during translation phase three in a #define
7
           directive.  In particular, the definition is truncated by
8
           embedded newline characters.
9

10
           If you are invoking the preprocessor from a shell or shell-
11
           like program you may need to use the shell's quoting syntax
12
           to protect characters such as spaces that have a meaning in
13
           the shell syntax.
14

15
           If you wish to define a function-like macro on the command
16
           line, write its argument list with surrounding parentheses
17
           before the equals sign (if any).  Parentheses are meaningful
18
           to most shells, so you should quote the option.  With sh and
19
           csh, -D'name(args...)=definition' works.
20

21
           -D and -U options are processed in the order they are given
22
           on the command line.  All -imacros file and -include file
23
           options are processed after all -D and -U options.
#7451644
Lesenswert?

Daniel -. schrieb:

Erste Idee war mit einem Binary Editor den Wert auszutauschen und dann HEX daraus zu machen. Diese Vorgehensweise lässt sich nicht robust per Makefile umsetzen, da die Variablenaddressen sich ändern.

Müssen sie sich ändern? Kann man sie nicht in eine eigene section packen, z.B. direkt hinter der vectortable? Weil, die erste Idee ist manchmal die beste.

Kaj G. schrieb:

-D name Predefine name as a macro, with definition 1.

Das geht doch nur auf dem "Umweg" über Präprozessor und Compiler? Eigentlich kein Problem, aber manchmal muss es der Linker alleine machen. Ich hatte sowas mal für einen Zeitstempel benutzt, aber es sieht hässlich aus:

1
# Makefile
2
UTC := $(shell date +%s)
3
CFLAGS = -Wall -Wl,-defsym=BUILD_TIME=$(UTC)
1
extern int  BUILD_TIME;
2
time_t build_time = (time_t)&BUILD_TIME;
#7451645
Lesenswert?

Daniel -. schrieb:

Hat jemand ein Beispiel wie man mit objcopy einen Wert in einer Sektion austauschen kann? Am besten mit Referenz auf Symbol und nicht eine Adresse.

Ich hatte mal vor vielen Jahren sowas für den Micronucleus zusammengehackt und dazu "objcopy" verwendet.

https://github.com/micronucleus/micronucleus/commit/b9b7e85ce887c3ff4f0b38273dcd32e9d9810f8f

Nachdem es funktionierte habe ich nicht mehr daran gedreht. Es ging darum, den neuen Bootloader (raw binary) zusammen mit den Routinen zum Nachflashen zu linken. Die passenden Zeilen finden sich im aktuellen Makefile vom Firmware-Repo, vielleicht kannst Du es ja als Anregung nehmen.

https://github.com/ArminJo/micronucleus-firmware/blob/18ad3420ccdfb3f21638cd06be99a5e6574ccb0d/firmware/Makefile#L151-L158

1
bootloader.o: bootloader.raw
2
        @avr-objcopy -I binary -O elf32-avr \
3
        --rename-section .data=.text \
4
        --redefine-sym _binary_$*_raw_start=$* \
5
        --redefine-sym _binary_$*_raw_end=$*_end \
6
        --redefine-sym _binary_$*_raw_size=$*_size_sym \
7
        $(AVR_ARCHITECTURE_PARAMETER) \
8
        $< $@
OP #7451656
Lesenswert?

Bauform B. schrieb:

Müssen sie sich ändern? Kann man sie nicht in eine eigene section packen, z.B. direkt hinter der vectortable? Weil, die erste Idee ist manchmal die beste.

ich werde es wohl so machen müssen. Auch im Linker Skript eigene Output Sektion machen, weil die Checksumme auch über rodata gehen soll und diese wird nach Platzierung der Checksumme die Checksummenberechnung ändern. War Gedankenfehler meinerseits.

Danke für das Beispiel mit Buildtime und LONG(454656). Damit sollte es über Makefile automatisierbar sein.

Gruß

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren