www.mikrocontroller.net

Forum: Compiler & IDEs Attribute und pointer-type


Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Ich habe da ein kleines Verständnisproblem mit den GCC-Attributen für 
Typen.
Ich möchte eine Callbackfunktion auf einem AT91SAM7S64 ins RAM 
verlagern, wobei ich folgendes Makro verwende:
#define __ramfunc __attribute__ ((long_call, section (".fastrun")))

Das "Event" wird in die Timeoutqueue eines kleinen, aber sehr 
nützlichen, Tools von Jörg Wunsch (das Bier hast Du Dir wirklich 
verdient ;) wie folgt eingelassen:
  /* Enable displayclock: */
  timeout(1000, showclock, (union timeoutarg) NULL);

Die Implementation der Callbackfunktion sieht so aus:
/* Callback function for the clock: */
__ramfunc void
showclock(union timeoutarg targ)
{
        time_t timer;
        struct tm *ltime;

        /* retrigger displayclock: */
        timeout(1000, showclock, (union timeoutarg)NULL);

        timer = lt_copy + (clock()/1000);
        ltime = localtime(&timer);

        /* fancy clock - this should get a prompt one day ;-) */
        rprintf(" [%02d:%02d:%02d] %u:/>\r", ltime->tm_hour, ltime->tm_min, ltime->tm_sec, dmxStartAddress);
}       

Die Warnung des Compilers dann so:
main.c:325: warning: passing argument 2 of 'timeout' from incompatible pointer type

Meine Fragen:

  1. Wo gehört "__attribute__" hin?
     - vor den Prototypen
     - hinter den Prototypen
     - vor den Funktionsrumpf
     - hinter die schliessende Klammer der Argumentliste
     - vor/hinter Prototyp und Funktionsrumpf
  2. Warum verändert es den Pointertypen?
  3. Wäre ein Cast hier richtig?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick Dohmen wrote:

>   1. Wo gehört "__attribute__" hin?
>      - vor den Prototypen
>      - hinter den Prototypen
>      - vor den Funktionsrumpf
>      - hinter die schliessende Klammer der Argumentliste
>      - vor/hinter Prototyp und Funktionsrumpf

Hmm, ich mache es immer so:
rettype myfunc(arglist) __attribute__((...));
rettype
myfunc(arglist)
{
  /* implementation */
}
Ich bin mich nicht sicher, welche Wege es noch gäbe.

>   2. Warum verändert es den Pointertypen?

"Das ist eben so." :-)

Naja, auch derjenige, der die Callback-Funktion ruft, muss ja
u. U. darüber etwas wissen.  Wenn ich das richtig sehe (kenne mich mit
ARM nicht aus), verlässt du ja damit den normalen Weg, wie der
Compiler einen indirekten Funktionsaufruf zusammenbasteln würde.
Damit muss er natürlich auch innerhalb des Timeout-Handlers wissen,
dass er anderen Code generieren soll.

>   3. Wäre ein Cast hier richtig?

Erst einmal nicht.  Richtig wäre es, die Attribute auch in der
Timerqueue sauber mitzuführen.  Ob der Cast tolerierbar wäre, hängt
letztlich davon ab, ob meine bei 2. genannten Ausführungen tatsächlich
Auswirkungen auf den generierten Code haben oder nicht.

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, Deine Vorgehensweise ergibt folgenden Fehler:
void showclock(union timeoutarg targ) __ramfunc;

[..]

void
showclock(union timeoutarg targ)
{

[..]

}
main.c:320: error: conflicting types for 'showclock'
main.c:22: error: previous declaration of 'showclock' was here

Irgendwie blick ich das nicht...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Seltensam.  Genau auf diese Weise werden aber beispielsweise die
ISRs bei avr-libc deklariert.

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:

>>   3. Wäre ein Cast hier richtig?
>
> Erst einmal nicht.  Richtig wäre es, die Attribute auch in der
> Timerqueue sauber mitzuführen.  Ob der Cast tolerierbar wäre, hängt
> letztlich davon ab, ob meine bei 2. genannten Ausführungen tatsächlich
> Auswirkungen auf den generierten Code haben oder nicht.

Das heist also, ich müsste den Funktionsprototypen aus "timer.h" 
umbauen...
/* the action function itself */
typedef void (*timeout_t)(union timeoutarg);

...wird zu:
/* the action function itself */
typedef void (*timeout_t)(union timeoutarg) __ramfunc;

Ich werd's mal ausprobieren!

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heh, denkste! :-)
timer.h:24: error: section attribute not allowed for 'timeout_t'

Naja, ich such mich mal schlau...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick Dohmen wrote:

> Heh, denkste! :-)

>
> timer.h:24: error: section attribute not allowed for 'timeout_t'
> 

Naja, die section ist nicht so wichtig (die wird ja nur für den Linker
gebraucht, damit er den Code der Funktion an die passende Stelle
packen kann), aber was ist mit dem long_call?

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na hups!
Ich wollte nicht unhöflich sein, ich hab den Beitrag irgendwie aus den 
Augen verloren.

Das mit dem 'long_call' als einziges Attribut werde ich nachher mal 
ausprobieren, danke für den Hinweis!

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So funktioniert es:

1. Funktionspointer
/* the action function itself */
typedef __attribute__ ((long_call)) void (*timeout_t)(union timeoutarg);

2. Funktionsprototyp für callback Implementation
/* callback functions */
__ramfunc void showclock(union timeoutarg targ);

3. Funktionsdeklaration
__ramfunc void
showclock(union timeoutarg targ)
{
    [...]
}

Stelle ich die Attribute ans Ende, wird immer wieder 'redeclaration' 
bemängelt.
Seltsame Sache...

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.