Hallo zusammen, mein Hinderniss ist folgendes: Ich hab in einer C-Datei eine Konstante definiert die ins Flash kommt. Etwa so: const unsigned int TotalCodeLength; Jetzt möchte ich diesen Wert mit dem Wert 'etext' aus dem Linker Script versehen so das ich im C-Code weiss wie weit quasi mein gesamter Flash befüllt ist. In assembler mache ich das wie gewohnt über eine PROVIDE derective im linker script und eine .global deklaration im assembler file. dann kann ich auf den wert 'etext' in der assembler datei zugreifen. ähnlich wie beim startup mit den 'data' und 'bss_start' werten etc. Nur wie komm ich in der c-datei an den wert dran? die anderen sachen funktionieren auch nicht: const unsigned int TotalCodeLength = _etext; oder: extern const unsigned int _etext; const unsigned int TotalCodeLength = _etext; kann man auf provided variablen des linker scripts überhaupt in c zugreifen? Grüße und danke für eure hilfe AVRuser
Beispielsweise im Linker-Script sowas: [....] .doTheWrapper 0x00000: { startOfRealWrapper = LOADADDR(.realWrapper) + 0xFFFF0000; endOfRealWrapper = LOADADDR(.realWrapper)+SIZEOF (.realWrapper) + 0xFFFF0000; } [....] Was da zugewiesen wird, ist erst mal egal. Im C-Text dann sowas: [...] extern unsigned char *startOfRealWrapper; extern unsigned char *endOfRealWrapper; [...] Hier gibst Du dann den Variablen eine Bedeutung. bei mir eben Zeiger, weil ich die Adressen darin (die dann vom Linker eingesetzt werden) zum Kopieren benutzen will. Und nicht wundern: Die gesamten C-Quellen enthalten nirgends ein "unsigned char *startOfRealWrapper;" (also ohne "extern"). Das funktioniert dann aber nur, wenn man am Ende mit dem Scrip-Schnipsel von oben binden läßt. Ansonsten meckert der Linker über die fehlenden Symbole. JB
Du kannst mit PROVIDE im Linkerskript ein Symbol exportieren. Der Haken ist, dass du ein eigenes, modifiziertes Linkerskript brauchst, die du ggf. bei Updates der offiziellen avr-libc updaten musst. Welches Linkerskript du ändern kannst, hängt von deinem AVR ab. Im folgenden habe ich es mit einem ATmega8 dargestellt, d.h. es ist das Linkerskript der avr4 Architektur zu ändern. Die Architektur bekommst du über die Doku raus oder über das Anzeigen der ausführlichen GCC Kommandozeile oder über einen Blick in die MAP-Datei. Nun gibt es für je eine Architektur fünf Linkerskripte. Das "normale", d.h. ohne spezielle Linkeroptionen, ist das avr4.x Wenn du die Sache im simulator/Debugger per Memory View, Watch und Single Step nachvollziehen willst, schau dir den folgenden Democode an. Zum Demonstrieren wird die Adresse ab _etext ermittelt und dann eine dort "geschickt" platzierte Stringvariable kopiert. Geschickt heisst, es ist die erste Variable im Programm und die ist extra einfach lesbar gestaltet.
1 | #include <avr/io.h> |
2 | #include <avr/pgmspace.h> |
3 | |
4 | extern char PROGMEM _etext; |
5 | char s_rom[] = "<-Ende von .text = Anfang von Romdata"; |
6 | char s_ram[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; |
7 | void * watch_me; |
8 | uint8_t i; |
9 | |
10 | int main(void) |
11 | {
|
12 | watch_me = &_etext; |
13 | |
14 | for (i = 0; s_ram[i]; i++) |
15 | s_ram[i] = pgm_read_byte(watch_me + i * sizeof(uint8_t)); |
16 | |
17 | return 42; |
18 | }
|
und der Ausschnitt aus avr4.x
1 | ... |
2 | KEEP (*(.fini1)) |
3 | *(.fini0) /* Infinite loop after program termination. */ |
4 | KEEP (*(.fini0)) |
5 | /* _etext = . ; */ |
6 | PROVIDE (_etext = .) ; /* <====================== */ |
7 | } > text |
8 | .data : AT (ADDR (.text) + SIZEOF (.text)) |
9 | { |
10 | PROVIDE (__data_start = .) ; |
11 | *(.data) |
12 | *(.data*) |
13 | *(.rodata) /* We need to include .rodata here if gcc is used */ |
14 | ... |
Ich hab nochmal das ganze genauer betrachtet. Ich glaub mein Basisproblem ist erst mal noch ein anderes. Das ganze ist für einen LPC2129 Controller mit WinARM. Ich habe eine Softwareaufteilung gemacht in einen Bootloader und die eigentliche Applikation. Im Flash gibt es einen Bereich in dem Firmware-Infos abelegt sind. Also Datum, Version etc. und die Länge der Firmware. Diese verwendet der Bootloader um einen CRC Check zu machen. In der Firmware habe ich eine Struktur etwa so: typedef struct { u8_t VersionMain; u8_t VersionSub; u16_t Build; u32_t CRCLength; } FirmwareInfo_t; In einer C-Datei meiner Firmware lege ich nun im Flash eine Instanz der Struktur an einer bestimmten Adresse an. So das auch der Bootloader die Version etc. der Firmware auslesen kann. Das ist etwa so: const FirmwareInfo_t FwInfo = { 1, 5, 12, 2520}; Das funktioniert auch so weit. Nun ersetze ich die manuell eingetragene Länge durch das Label _etext das er zur compilierzeit aber noch nicht kennt. Also so: const FirmwareInfo_t FwInfo = { 1, 5, 12, _etext}; Als Fehler bekomme ich erst mal noch den das der Compiler beim parsen des Codes sieht das die Struktur 'const' ist, jedoch das Symbol bzw. der Wert _etext zur Parse-Zeit nicht bekannt ist. Denn dieser ist ja erst zur Link-Zeit bekannt. Kann ich den Wert auch in einer anderen Art ins Flash an eine bestimmte Adresse bringen ?? Vielleicht im LinkerScript selbst ?
Sieh' Dir mal das Manual vom LD an. Die Rubrik "linker scripts" ist sehr umfangreich und - meiner Meinung nach - auch sehr verständlich. Wenn Du das im Linker-Script unterbringen willst, such' Dir die "schönste" Stelle raus und füge dort ein: BYTE(<zahl>); /* ver major */ BYTE(<zahl>); /* ver minor */ SHORT(<zahl>); /* build */ LONG( SIZEOF(<.text>) ); /* oder wovon die Groesse gebraucht wird */ Du mußt dabei nur beachten, daß es nicht möglich ist, hier Variablen zu verwenden. Der Linker will nur echte Zahlen. Allerdings könntest Du das Linkerscript vorher durch den Precompiler schieben, um das Script selber parametrisieren zu können, bevor es der Linker zu sehen bekommt.
hallo nochmal zusammen, also ich habs hinbekommen aber auf ne gemischte art. meine struktur im c-code enthält nun nur noch die daten zur firmware selbst quasi versionen, datum etc. dann hab ich im linker script die section in die die struktur rein soll etwas abgeändert zu: .... .FwInfo 0x3DF00 : { *(.FwInfo) LONG ( 0x2000); /* Begin of Firmware */ LONG ( _etext + SIZEOF ( .data) - 0x2000); /* Length of Firmware for CRC */ SHORT ( 0); /* Placeholder for CRC */ } .... danke für eure anregungen besonders mit den direktiven zum einfügen von daten ins image mit BYTE, LONG etc. ich hab in der doku bestimmt mehrmals die stelle überschlagen aber nie genau gelesen. hab mehr nach direktiven wie EXPORT oder der art gesucht. auch nach pragmas für den code. bin nur nie fündig geworden :-) grüße
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.