Portierung von IAR Code auf GCC: Variable an eine feste Adresse

#4517283
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
#4517324
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
#4517328
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
#4517336
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.
#4517355
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'
Gast #4542964
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
Gast #4543049
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
Persönliche Seite #4544062
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.

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