mikrocontroller.net

Forum: Compiler & IDEs AVR-gcc und Bitfelder


Autor: Andreas Klafft (lowrider)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leutz,

bin ein purer Einsteiger und versuche gerade einen Atmega168 mit dem 
AVR-gcc zu programmieren. Ziel ist es, Die TN AVR447, die ja in IAR-C 
geschrieben ist, auf einen 'Standard'-C-Compiler zu portieren. 
Anscheinend machen die Compiler aber unterschiedliches aus einem 
Bitfeld:

Teil aus der Headerdatei:
typedef struct PMSMflags
{
  unsigned motorStopped : 1;
  unsigned motorSynchronized: 1;
  unsigned actualDirection : 2;
  unsigned desiredDirection : 1;
  unsigned driveWaveform : 2;
} PMSMflags_t;

Normalerweise sollte das in ein Byte reinpassen (AVR-GCC-Tutorial). Bei 
Atmel ist das nur eine temporäre Variable, die die Struktur an andere 
Variablen mit den gleichen Bitnamen übergibt. So z.B. in main.c:
PMSMflags_t fastFlags;

Dummerweise weist Atmel der Variable fastFlags das Register GPIOR0 zu. 
Das scheint in IAR-C ganz einfach zu gehen:
__io volatile PMSMflags_t fastFlags                               @0x1e;

Mir fällt blos nichts dazu in GCC ein. Laut Herold/Arndt entsteht dabei 
auch eine Variable mit der Länge von 5 Bytes; dass die nicht in ein 
Register passen war mir dann auch klar. Was anscheinend funktioniert hat 
war ein:
#define fastFlags GPIOR0

direkt danach. Ich habe fastFlags damit aber anscheinend umdefiniert. 
Ich bekomme jedenfalls folgende Fehlermeldungen:
error: incompatible types in assignment  // wenn ich die Variable als ganzes anspreche

oder auch
error: request for member 'motorSynchronized' in something not a structure or union // wenn ich die einzelnen Bits der Variable anspreche

Da ich unter SUSE Linux arbeite, möchte ich mir auch kein WinAVR 
installieren. Ich weiss, ich mache was falsch. Ist einer so nett und 
kann mir das mal erklären?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das kommt halt davon, wenn man sich vom C Standard wegbewegt, aber IAR 
wird übr Portierungsprobleme weg von IAR nicht wirklich unglücklich 
sein.

#define fastFlags (*(PMSMflags_t *)&GPIOR0)
oder
#define fastFlags (*(volatile PMSMflags_t *)&GPIOR0)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übersetzst du beim AVR mit -Os ?

Autor: möööp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der GCC is da etwas eigen ..

versuch mal
typedef union 
{
 unsigned char  register; 
 struct PMSMflags
 {
   unsigned char motorStopped : 1;
   unsigned char motorSynchronized: 1;
   unsigned char actualDirection : 2;
   unsigned char desiredDirection : 1;
   unsigned char driveWaveform : 2;
 };
} PMSMflags_t;


Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
möööp schrieb:
> versuch mal
>
>
> typedef union
> {
>  unsigned char  register;
>  struct PMSMflags
>  {
>    unsigned char motorStopped : 1;
>    unsigned char motorSynchronized: 1;
>    unsigned char actualDirection : 2;
>    unsigned char desiredDirection : 1;
>    unsigned char driveWaveform : 2;
>  };
> } PMSMflags_t;
> 
> 

Nö. Register ist ein Schlüsselwort in C.

Klaus Wachtler schrieb:
> Übersetzst du beim AVR mit -Os ?

Typelayout hängt nicht von Optimierung ab.

Autor: manoh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Klafft schrieb:
> Da ich unter SUSE Linux arbeite, möchte ich mir auch kein WinAVR
> installieren.

WinAVR ist doch AVR-GCC, das ändert doch nix...

Verstehe ich das eigentlich richtig, Du möchtes PMSMflags_t fastFlags 
ständig in einem Register stehen haben?

Autor: Andreas Klafft (lowrider)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow, das ist mal 'ne schnelle Reaktion hier.
Ich werde die verschiedenen Tips mal austesten. Am sinnvollsten scheint 
mir die Version von A.K. (hallo Initialienvetter) zu sein. Ich werde 
darüber berichten. Hier noch ein paar Einzelantworten:

@Klaus:
Ja, ich übersetze mit der Optimierung -Os. Allerdings habe ich auch -O2 
schon ausprobiert, was scheinbar nicht wirklich was bringt.

@manoh:
Auch hier ein ja, ich möchte die Variable fastFlags mit der Struktur von 
PMSMflags_t im Register GPIOR0 fest unterbringen.
Leider lassen sich die GPIORx Register nur sehr umständlich in AVR-gcc 
ansprechen. Ich frage mich nur, wozu die sonst da sind? General Purpose 
heißt für mich 'Allgemeine Verwendung'. Der Vorteil ist ein recht 
schneller Zugriff und einfache Bitmanipulation mit nur wenigen 
Taktzüklen.

Autor: manoh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn mit GPIOR0 r0 gemeimt ist, geht das dann überhaupt?

aus nongnu avr libc: 
http://www.nongnu.org/avr-libc/user-manual/porting.html

Locking Registers

The IAR compiler allows a user to lock general registers from r15 and 
down by using compiler options and this keyword syntax:
__regvar __no_init volatile unsigned int filteredTimeSinceCommutation @14;

This line locks r14 for use only when explicitly referenced in your code 
thorugh the var name "filteredTimeSinceCommutation". This means that the 
compiler cannot dispose of it at its own will.

To do this in AVR GCC, do this:
register unsigned char counter asm("r3");

Typically, it should be possible to use r2 through r15 that way.

Note:
Do not reserve r0 or r1 as these are used internally by the compiler for 
a temporary register and for a zero value.
Locking registers is not recommended in AVR GCC as it removes this 
register from the control of the compiler, which may make code 
generation worse. Use at your own risk.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
manoh schrieb:

> wenn mit GPIOR0 r0 gemeimt ist, geht das dann überhaupt?

GPIOR0/1/2 sind freie Register im bitadressierbaren I/O-Bereich einiger 
AVRs. Ideal geeignet für Flag-Bits.

Autor: Andreas Klafft (lowrider)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo manoh,

GPIOR0 ist nicht r0. GPIOR0 hat die Registeradresse 0x1e. Ich bin aber 
noch nicht dahintergestiegen welche Adresse r0-r32 haben?!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Klafft schrieb:

> Ich bin aber
> noch nicht dahintergestiegen welche Adresse r0-r32 haben?!

0..31, es sei denn man hat einen XMega oder einen 6-Pin Tiny.

Es ist aber dringend davon abzuraten, die Register per RAM-Adressen zu 
nutzen, jedenfalls wenn ein C Compiler mitmischt.

Autor: Andreas Klafft (lowrider)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leutz,

habe da mal ein Bischen rumprobiert. Der Hinweis von A.K. scheint die 
Lösung zu sein:
#define fastFlags (*(volatile PMSMflags_t *)&GPIOR0)

Ich habe mir danach mal den *.lst - File angesehen. Es geschieht genau 
das, was ich erwartet habe: ein Zugriff auf GPIOR0 mit SBI und CBI:
    fastFlags = fastFlagsInitial;
 59e:  8e bb         out  0x1e, r24  ; 30

oder:
    fastFlags.desiredDirection = DIRECTION_FORWARD;
 5a8:  f4 98         cbi  0x1e, 4  ; 30

Wenn ich das richtig sehe, wird das Register mit der Adresse 0x1e 
angesprochen, das ist genau das GPIOR0.
Danke an alle, werd mich wieder melden.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.