Hallo Zusammen,
ich bin auf der Suche nach einer Lösung um die IAR Compiler
int var @(0x01000)
beim GCC für ARM zu ersetzen.
Laut Dokumentation gibt es ja einige Möglichkeiten mittels
__attribute__:
int var __attribute__((at(0x01000)))
oder
int var __attribute__((io(0x01000)))
Leider werden beide nicht supported. Schade.
Die dritte Möglichkeit ist:
int var __attribute__((section("my_section_0x01000")))
und diese Section im ld File zu definieren.
Soweit so gut. Es geht auch. Leider bekomme ich keine Fehlermeldung wenn
die Section im ld File nicht definiert ist. Der gcc definiert dann
einfach eine eigene Section und legt diese in den RAM.
Wie kann ich das verhindern? Oder gibt es eine Möglichkeit die Variante
mit at zum laufen zu bringen?
Die Lösungen mit
#define var (*(*int)0x01000))
finede ich nicht sehr praktisch, da keine Überprüfung des freien
Speicherbereiches möglich ist. Und sollten da größere Strukturen
anstelle eines int verwendet werden, kommen unnötige MISRA Warnungen.
Eine weiteres Problem ist es, wenn der Sourcecode von beiden Compilern
genutzt werden soll.
Bis jetzt habe ich für MISRA Checker und anderen Compilern das @ mittels
eines Macros umdefiniert:
#define _IOC(x) @(x)
oder
#define _IOC(x)
Hat jemand eine Lösung für Macro Parameter, welche dann in "" genutzt
werden? Also aus int var _IOC(0x01000) soll das obige entstehen.
Danke für Eure Vorschläge,
Bernd
Bernd M. schrieb:> Der gcc definiert dann> einfach eine eigene Section und legt diese in den RAM.> Wie kann ich das verhindern?
Es gibt den Trick, im Linker Skript ein nicht-standard Symbol zu
definieren und dies als externe Referenz im C-Code zu prüfen. Dann
steigt der Linker bei flsaschem Skript mit einem "unresolved external"
aus.
Beispiel:
1
externunsignedlong_specialsymbol;
2
3
voidspecialTest(){
4
if(&_specialsymbol!=(unsignedlong*)SPECIAL_ADDR){
5
printf("Error!\n");
6
}
7
}
Die specialTest() Funktion muss dann auch aufgerufen werden sonst wird
wegoptimiert.
LD Skript:
Jup, das will ich machen. Aber wenn die Section nicht definiert ist, so
wird eine automatisch erstellt, welche im RAM liegt. Also ich erhalte
somit keine Fehlermeldung.
Für folgende C Zeile, die Section adsaccmramasdsa ist nicht im Linker
File definiert:
erhalte ich im MAP File, ohne Linker Fehlermeldung:
adsac
0x20000014 0x4 load address 0x08000e98
[!provide] PROVIDE (__start_adsac, .)
adsac
0x20000014 0x4 out/main.o
0x20000014 foo
[!provide] PROVIDE (__stop_adsac, .)
Für eine Section die auch definiert ist:
@Jim,
OK an sowas habe ich nicht gedacht. Aber wenn man so ca. 100 Variablen
hat, welche eine feste Addresse haben, will man keine 100 if Zweige
tippen. Die Gefahr da einen Fehler zu machen ist schon groß und erst zur
Laufzeit sichtbar.
Das ist es nicht, was ich machen würde.
@Clements,
das sieht ja gut und kurz aus. Leider geht es nicht. Da fehlt etwas in
den ASM Befehl. Ich kenne mich mit den gcc ASM noch nicht so gut aus.
Aber hier fehlt was, ich erhalte da folgende Fehlermeldung:
r:\temp\cc7OvZuC.s: Assembler messages:
r:\temp\cc7OvZuC.s:62: Error: junk at end of line, first unrecognized
character is `,'
r:\temp\cc7OvZuC.s:165: Error: junk at end of line, first unrecognized
character is `0'
Bernd M. schrieb:> @Clements
Wer?
> Da fehlt etwas in den ASM Befehl.
Die Zahl muss eine gültige Adresse für den Assembler sein; keine Ahnung,
wie das beim GNU-as für ARM aussieht.
Alternativ:
extern int var;
und dann
PROVIDE(var = 0x1000)
im Linker-Skript.
@Clemens,
sorry für das t :)
Das mit PROVIDE im Linker File gefällt mir am besten, da ich nur einen
Ort habe wo ich das tippen muss.
Danke für Eure Hilfe :))
Bernd
Hallo,
Ich habe ein ähnliches Problem wie Bernd, und zwar muss ich einen
bestimmten Bereich haben, in den zwei unterschiedliche Applikationen
schreiben und lesen können sollen (genauer ein Bootloader und die
nachzuladene Applikation).
Ich habe dazu einen volatile struct mit einem section attribute
angelegt:
Da Du mehrere Variablen fest im Speicher definieren willst, würde ich
das nicht über eine Section für alle Variablen machen, da dann die
Sortierung von der Reihenfolge des Linkers abhängt.
Ich empfehle Dir für jede Variable ein PROVIDE beim Linker zu
definieren.
Also h-File:
extern volatile sNonvolE_t sNonvolE;
und jetzt nur noch im Linker File:
PROVIDE (sNonvolE = 0x200001f0);
Willst du diese mit NONINIT definieren, damit diese nicht überschrieben
wird:
Achtung, in einer Section muss Du die Startadress der Section als Offset
für PROVIDE () sehen. Das (NOLOAD) habe ich noch nicht getestet ob es
auch funktioniert. Es kommt aber auch drauf an, wie der Startup Code
aussieht.
._nonvol_ram_area (NOLOAD) :
{
PROVIDE (sNonvolE = 0);
} > RAM2
Gruß,
Bernd
Bernd M. schrieb:> Jup, das will ich machen. Aber wenn die Section nicht definiert ist, so> wird eine automatisch erstellt, welche im RAM liegt.
Das istr ein Feature des Linkers und nennt sich "orphan section". Weil
der Linker nicht weiß, was er mit einer orphan section genau machen
soll, versucht er, die Ablage anhand der Section-Flags zu bestimmen.
Mit Attribut "section" können keine Flags angegeben werden; es gibt aber
GCC-Anbieter, die Attribute bereitstellen, die es erlauben,
Section-Flags und -Alignment anzugeben.
Wenn "mehrere 100" Variablen mit expliziter Adresse abzulegen sind dann
deutet das i.d.R. auf ein Design-Problem hin...
Die "Lösung" mit asm kannst du vergessen, das ist nicht solide und wird
dir mehr Probleme bringen als es löst.
Attribute wie "io" oder "address" sind i.d.R. auch keine Lösung, weil
die zwar erlauben, die Adresse festzulegen, sie aber keine
entsprechenden Speicher allokieren.