www.mikrocontroller.net

Forum: Compiler & IDEs Problem mit atomic Funktionen


Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal versucht, die neuen atomic Funktionen des WINAVR zu 
benutzen.
Der Code wird auch korrekt compiliert, aber es gibt leider eine 
Fehlermeldung:

ATOMIC.C: In function 'test':
ATOMIC.C:10: warning: control reaches end of non-void function

Hier der Code:

#include <util\atomic.h>

volatile int var;

int test( void )
{
  ATOMIC_BLOCK(ATOMIC_FORCEON){
    return var;
  }
}


Peter

Autor: Nico (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur mal als Anmerkung:
#include <util\atomic.h>

Das nutzen eines Backslash hier ist wirklich eine üble Unsitte, die sich 
unter Windows-Programmierern leider eingebürgert hat. Der Backslash 
dient in C (und auch im PreProcessor) eigentlich als Escape.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe zwar keine ahnung was das atomic auf einem Atmel macht aber die 
Warnung kommt weil die Funktion ein ende ohne return hat.

int test( void )
{
  ATOMIC_BLOCK(ATOMIC_FORCEON){
    return var;
  }
  return 0;
}


jetzt sollte die Warnung weg sein.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter wrote:
> ich habe zwar keine ahnung was das atomic auf einem Atmel macht

Du hast also bisher noch nie Interrupts benutzt?

Atomic macht die notwendige CLI/SEI-Klammerung für den Zugriff auf 
Interruptvariablen im Main.


> jetzt sollte die Warnung weg sein.

Sieht zwar etwas irritierend aus, aber die Warnung ist weg.
Das "return 0;" wird auch wieder wegoptimiert.


Peter

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>aber die Warnung kommt weil die Funktion ein ende ohne return hat.

Genaugenommen kommt die Warnung wohl, weil der Compiler nicht versteht, 
daß return(var) immer erreicht wird.

Oliver

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> > ich habe zwar keine ahnung was das atomic auf einem Atmel macht
> Du hast also bisher noch nie Interrupts benutzt?
Doch habe ich, aber ich ziehe es bisher vor, selber zu entscheiden wenn 
ich die Interrupts abschalte und wann nicht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter wrote:
> Doch habe ich, aber ich ziehe es bisher vor, selber zu entscheiden wenn
> ich die Interrupts abschalte und wann nicht.

Eigentlich wollte ich mit den atomic Funktionen die Lesbarkeit 
verbessern.

Aber das "return 0;" ist kontraproduktiv, weil es suggeriert, es könnte 
0 statt val zurückgegeben werden.


Peter

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann mach es mit

int test( void )
{
  int tmp;
  ATOMIC_BLOCK(ATOMIC_FORCEON){
    tmp=var;
  }
  return tmp;
}

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh da kommt bestimmt die Warnung das eine nicht initalisierte Variable 
genutzt wird. Also 2. Versuch
int test( void )
{
  int tmp = 0;
  ATOMIC_BLOCK(ATOMIC_FORCEON){
    tmp=var;
  }
  return tmp;
}

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrob:

>
> int test( void )
> {
>   ATOMIC_BLOCK(ATOMIC_FORCEON){
>     return var;
>   }
> }
> 

Ist das denn überhaupt sinnvoll?

Wenn zB der Block vor dem return ein CLI und danach ein SEI einfügt, 
dann wird das SEI nie mehr ausgeführt (bzw, Restaurierung des I-Flags).

BTW dürften das keine Funktionen sein sondern Makros, also einfach mal 
anschauen was der Präprozessor draus macht bzw. ein Blick in die Doku 
wagen.

Das Atomic-Zeug ist wohl für blöcke gedacht, die die schliessende } auch 
erreichen und nicht per goto oder return oder sonstwas den atomic block 
verlassen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. wrote:

> Wenn zB der Block vor dem return ein CLI und danach ein SEI einfügt,
> dann wird das SEI nie mehr ausgeführt (bzw, Restaurierung des I-Flags).
>
> BTW dürften das keine Funktionen sein sondern Makros, also einfach mal
> anschauen was der Präprozessor draus macht bzw. ein Blick in die Doku
> wagen.
>
> Das Atomic-Zeug ist wohl für blöcke gedacht, die die schliessende } auch
> erreichen und nicht per goto oder return oder sonstwas den atomic block
> verlassen.

Nicht nach der Dokumentation:
These macros operate via automatic manipulation of the Global Interrupt 
Status (I) bit of the SREG register. Exit paths from both block types 
are all managed automatically without the need for special 
considerations, i. e. the interrupt status will be restored to the same 
value it has been when entering the respective block.

Man beachte hier das
> Exit paths from both block types are all managed automatically

Wie das genau erreicht wird, habe ich mir aber noch nicht angeschaut.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrob:
> Nicht nach der Dokumentation:
> These macros operate via automatic manipulation of the Global Interrupt
> Status (I) bit of the SREG register. Exit paths from both block types
> are all managed automatically without the need for special
> considerations, i. e. the interrupt status will be restored to the same
> value it has been when entering the respective block.
>
> Man beachte hier das
>> Exit paths from both block types are all managed automatically
>
> Wie das genau erreicht wird, habe ich mir aber noch nicht angeschaut.

Stimmt, wird recht geschickt über __attribute__((_cleanup_)) gemacht, 
sehr interessant das. Kannte ich noch garnicht.
static __inline__ uint8_t __iSeiRetVal(void)
{
    __asm__ __volatile__ ("sei" ::);
    return 1;
}

static __inline__ uint8_t __iCliRetVal(void)
{
    __asm__ __volatile__ ("cli" ::);
    return 1;
}

static __inline__ void __iSeiParam(const uint8_t *__s)
{
    __asm__ __volatile__ ("sei" ::);
    __asm__ volatile ("" ::: "memory");
    (void)__s;
}

static __inline__ void __iCliParam(const uint8_t *__s)
{
    __asm__ __volatile__ ("cli" ::);
    __asm__ volatile ("" ::: "memory");
    (void)__s;
}

static __inline__ void __iRestore(const uint8_t *__s)
{
    (*(volatile uint8_t *)((0x3F) + 0x20)) = *__s;
    __asm__ volatile ("" ::: "memory");
}
# 2 "main.c" 2

volatile int var;

int test( void )
{
  for ( uint8_t sreg_save __attribute__((__cleanup__(__iSeiParam))) = 0, __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0 ){
    return var;
  }
}

Jedenfalls wird korrekter Code erzeugt, und IMHO kommt die Warnung hier 
fälschlicher Weise, wenn es auch nichst einfach sein dürfte das im 
Compiler zu fixen; dazu müsste die Warnung in einem späteres Pass kommen 
als sie es jetzt tut.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Stimmt, wird recht geschickt über __attribute__((cleanup)) gemacht,
> sehr interessant das. Kannte ich noch garnicht.

Ist an sich das RAII-Prinzip, wie es in C++ gerne eingesetzt wird. In C 
(mit gcc) muß man sich halt mit dem cleanup-Attribut helfen, weil es da 
keine Destruktoren gibt.


> int test( void )
> {
>   for ( uint8_t sreg_save __attribute__((__cleanup__(__iSeiParam))) = 0, > 
__ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0 ){
>     return var;
>   }
> }
>
> Jedenfalls wird korrekter Code erzeugt, und IMHO kommt die Warnung
>  hierfälschlicher Weise,

Ich schätze, er erkennt nicht, daß die for-Schleife immer genau einmal 
ausgeführt wird.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woher bekommt man denn die atomic.h Datei?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert

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.