Forum: Compiler & IDEs Portierung von IAR Code auf GCC: Variable an eine feste Adresse


von Bernd M. (berndmoe)


Lesenswert?

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

von user (Gast)


Lesenswert?

kannst du nicht die Variablen in eine besondere Section legen und dem 
linker sagen wo er es hintun soll.

von Clemens L. (c_l)


Lesenswert?

int var asm("0x01000");

Allerdings kann der Compiler bei (*(int*)0x01000)) die Zugriffe besser 
optimieren, weil er die Adresse kennt.

von Jim M. (turboj)


Lesenswert?

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
extern unsigned long _specialsymbol;
2
3
void specialTest(){
4
 if (&_specialsymbol != (unsigned long *) SPECIAL_ADDR) {
5
    printf("Error!\n");
6
  }
7
}

Die specialTest() Funktion muss dann auch aufgerufen werden sonst wird 
wegoptimiert.


LD Skript:
1
 .special : {
2
  _specialsymbol = . ;
3
  [...]
4
} > SPECIAL_MEMORY

: Bearbeitet durch User
von Bernd M. (berndmoe)


Lesenswert?

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:
1
int foo __attribute__((section("adsaccmramasdsa")));

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:
1
int foo __attribute__((section(".ccmram")));
erhalte ich:
 .ccmram        0x10000000        0x4 out/main.o
                0x10000000                foo
 fill         0x10000004        0x4

von Bernd M. (berndmoe)


Lesenswert?

@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.

von Bernd M. (berndmoe)


Lesenswert?

@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'

von Clemens L. (c_l)


Lesenswert?

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.

von Bernd M. (berndmoe)


Lesenswert?

@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

: Bearbeitet durch User
von Ich (Gast)


Lesenswert?

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:
1
volatile sNonvolE_t sNonvolE __attribute__((section ("_nonvol_ram_area")));

Im Linkerfile habe ich einen speperaten Memorybereich angelegt:
1
RAM2  (rw)       : ORIGIN = 0x20007F00, LENGTH = 0x00000100 /* nonvolatile area */

und
1
/************************************************************************************
2
 *
3
 *  non volatile memory area
4
 *  must not be erased!
5
 ************************************************************************************/
6
  ._nonvol_ram_area :
7
  {
8
    . = ALIGN(4);
9
    NonVolArea = .;
10
  } >RAM2


im Mapfile taucht die Section zwar korrekt auf:
1
._nonvol_ram_area
2
                0x20007f00        0x0
3
                0x20007f00                . = ALIGN (0x4)
4
                0x20007f00                NonVolArea = .


aber die Variable wird einfach nur ans Ende des "normalen" RAM gelegt:
1
                0x200001f0                sNonvolE
2
                0x20000200                PROVIDE (__stop__nonvol_ram_area, .)



Kann mir da jemand sagen, was da falsch läuft? Danke im Voraus

von Ich (Gast)


Lesenswert?

Noch ganz vergessen, sorry:

Ist ein STM32L152 mit GCC 4.7.3 Toolchain

von Dr. Sommer (Gast)


Lesenswert?

Ich schrieb:
> Kann mir da jemand sagen, was da falsch läuft?

Der Name der Section beginnt mit einem Punkt, den hast du im C Code 
vergessen.

von Bernd (Gast)


Lesenswert?

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

von Ich (Gast)


Lesenswert?

Es wr der Punkt, danke Dr.Sommer. Jetzt legt er alles dahin, wo ich es 
brauche. :-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.