Hallo zusammen, ich möchte im Flash meines ATMEGA88 Start- und Endadresse eines Bereiches ablegen, über den eine CRC berechnet werden soll. Die Adressinformation erzeuge ich über das Linkerskript mit __CHECKSUM_START = .; und __CHKSUM_END = .; Nun deklariere ich diese Symbole entsprechend mit extern const uint32 __CHECKSUM_START; extern const uint32 __CHKSUM_END; Definieren möchte ich dann eine Variable mit const uint32 PROGMEM ChksumStartAddr = &__CHECKSUM_START; Aber der Compiler macht mir einen Strich durch die Rechnung: error: initializer element is not computable at load time Kann mir jemand sagen, was ich verkehrt mache? Danke und viele Grüße
Jap, da steigt der GCC dann aber gleich aus mit: error: initializer element is not constant
Jay K. schrieb: > const uint32 PROGMEM ChksumStartAddr = &__CHECKSUM_START Welchen Sinn hat das überhaupt? Kannst du nicht einfach __CHECKSUM_START statt ChksumStartAddr nutzen? Ist ja eh konstant. Kann übrigens sein dass das in C++ geht. Probier es mal aus...
Dr. Sommer schrieb: > Welchen Sinn hat das überhaupt? Der Sinn ist, dass diese Werte während des Builds vom Hauptprogramm eben im Flash abgelegt werden und dann zur Laufzeit von einer anderen Instanz (z.B. dem Bootloader) ausgelesen und zur CRC Berechnung genutzt werden können
Eigentlich müsste es gehen. Zum Vergleich, in meinem Code (ist zwar ARM-GCC, aber dafür spielt das ja keine Rolle) sieht das so aus:
1 | // first address that follows the rom space used by the linker
|
2 | extern uint32_t _usedromend; |
3 | // first address that is used for the .text section by the linker
|
4 | extern uint32_t _usedromstart; |
5 | |
6 | uint32_t sysComputeFlashCRC() |
7 | {
|
8 | uint32_t *dp; |
9 | |
10 | dp = &_usedromstart; |
11 | sysCRCReset(); |
12 | while (dp != &_usedromend) sysCRCAdd(*dp++); |
13 | return sysCRCGet(); |
14 | }
|
und im Linkerscript:
1 | SECTIONS |
2 | { |
3 | .text : |
4 | { |
5 | _usedromstart = .; |
6 | KEEP(*(.isr_vector)) |
7 | *(.text*) |
8 | *(.rodata*) |
9 | } > rom |
10 | |
11 | .ARM.exidx : |
12 | { |
13 | __exidx_start = .; |
14 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) |
15 | __exidx_end = .; |
16 | } > rom |
17 | |
18 | __etext = .; |
19 | /* _sidata is used in startup code */ |
20 | _sidata = __etext; |
21 | .data : AT (__etext) |
22 | { |
23 | __data_start__ = .; |
24 | /* _sdata is used in startup code */ |
25 | _sdata = __data_start__; |
26 | |
27 | *(vtable) |
28 | *(.data*) |
29 | . = ALIGN(4); |
30 | /* All data end */ |
31 | __data_end__ = .; |
32 | /* _edata is used in startup code */ |
33 | _edata = __data_end__; |
34 | } > ram |
35 | /* _siccmdata is used in startup code to init vars in ccm */ |
36 | _siccmdata = __etext + SIZEOF (.data); |
37 | .ccmdata : AT ( _siccmdata ) |
38 | { |
39 | __ccmdata_start__ = .; |
40 | _sccmdata = __ccmdata_start__; |
41 | *(.ccmdata*) |
42 | . = ALIGN(4); |
43 | /* All data end */ |
44 | __ccmdata_end__ = .; |
45 | _eccmdata = __ccmdata_end__; |
46 | } > ccm |
47 | _usedromend = _siccmdata + SIZEOF (.ccmdata); |
48 | .bss : |
49 | { |
50 | ... |
Vielleicht hilft das ja... PS: Gerade ausprobiert:
1 | const uint32_t *rompointer = &_usedromstart; |
im Code compiliert einwandfrei. Also sollte dein Beispiel eigentlich auch gehen... Muss wohl eine AVR-Spezialität sein. Kannst du denn eine nicht-PROGMEM-Variable damit initialisieren?
:
Bearbeitet durch User
Hallo Tassilo, danke für das Beispiel. So wie ich das sehe ist es nicht ganz das Gleiche. Du arbeitest hier mit dem Linkersymbol nach der Definition der (lokalen) Variablen. Zudem ist der ARM keine Harvard-Architektur...vielleicht ist da auch ein Problem?
Habe gerade nochmal probiert: Eine globale variable:
1 | const uint32_t romstartadr = (uint32_t)&_usedromstart; |
2 | |
3 | // uses the built in CRC engine to compute
|
4 | // the CRC of the FLash
|
5 | uint32_t sysComputeFlashCRC() |
6 | {
|
7 | uint32_t *dp; |
8 | |
9 | //dp = &_usedromstart;
|
10 | dp = (void*)romstartadr; |
11 | sysCRCReset(); |
12 | while (dp != &_usedromend) sysCRCAdd(*dp++); |
13 | return sysCRCGet(); |
14 | }
|
funktioniert auch. Die liegt auch im Flash und nicht im RAM, da const. Wenn der GCC das beim ARM zur Linkzeit eintragen kann, müsste das doch beim AVR auch gehen?!
Also mit einer "nicht-progmem" Variablen geht es auch nicht. Ich habe nun folgendes probiert: const uint32_t startaddr = __CHKSUM_START; Funktioniert auch nicht. Fehlermeldung ist wieder error: initializer element is not computable at load time Ich denke wirklich, es ist hier eine AVR-GCC Spezialität Edit: Brauch ich noch ein spezielles Compiler-Flag oder einen zusätzlichen Link-Run oder so etwas?
:
Bearbeitet durch User
Jay K. schrieb: > Ich denke wirklich, es ist hier eine AVR-GCC Spezialität Das ist keine Limitation des Compilers, sondern des Linkers. Ich glaube ich hatte mit const auch schon ähnliche Probleme. Interessanter weise scheint das hier bei mir zu gehen:
1 | #include <stdio.h> |
2 | |
3 | int x __attribute__((section("testsec"))); |
4 | int y __attribute__((section("testsec"))); |
5 | |
6 | extern char __start_testsec[]; |
7 | extern char __stop_testsec[]; |
8 | |
9 | struct my_structure { |
10 | void* start; |
11 | void* end; |
12 | };
|
13 | |
14 | const struct my_structure testsec_info = { |
15 | .start = __start_testsec, |
16 | .end = __stop_testsec |
17 | };
|
18 | |
19 | int main(){ |
20 | printf("%p %p\n",testsec_info.start, testsec_info.end); |
21 | }
|
:
Bearbeitet durch User
Hallo Daniel, vielen Dank, damit läuft es jetzt bei mir auch durch! Geholfen hat der void* als Typ und bei der extern Deklaration das uint8 / char Array. extern uint8_t __CHECKSUM_START[]; const void* ptrStartAddr = __CHECKSUM_START;
Daniel A. schrieb: > Interessanter weise scheint das hier bei mir zu gehen: Na sowas... Eine andere Möglichkeit wäre, es folgendermaßen komplett übers Linkerscript zu machen:
1 | .text : { |
2 | LONG(__CHECKSUM_START) |
3 | LONG(__CHECKSUM_END) |
4 | . = ALIGN(4); |
5 | __CHECKSUM_START = .; |
6 | ... |
7 | . = ALIGN(4); |
8 | __CHKSUM_END = .; |
9 | } |
Im C-Code braucht man gar nichts mehr zu schreiben. Wenn man die Adressen auslesen will kann man wie gehabt extern benutzen:
1 | extern const uint32_t __CHECKSUM_START; |
2 | extern const uint32_t __CHKSUM_END; |
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.