avr-gcc vergisst volatile variable in isr neu zu lesen

Gast #466411
Lesenswert?
• ▲
▼
globale.h
volatile unsigned short adc_ergebnis[8];
volatile unsigned char  adc_kanal[8];
volatile unsigned short kanal_index;


Separate datei

SIGNAL(SIG_OVERFLOW0)
{

    //pos = adc_ergebnis[2];
        f2 = f1;
        f1 = f0;
        f0 = (float)(pos-des_pos)/(float)1024.0;
        Ua = Ua + (Kp+Ki*T_cnt0+Kd/T_cnt0) * f0 + (-Kp-Kd/T_cnt0) * f1 + 
(Kd/T_cnt0) * f2;


        if((pos-des_pos)<max_fehler || (des_pos-pos)<max_fehler)
        {
            //pwm_stop();
            //return;
        }
        PORTD |= _BV(PD7);


/*         if(pos-des_pos>0) */
            init_pwm_oc1a();

        /* else  */
/*             init_pwm_oc1b() */;

        Te = ((float)Ua/(float)Vcc);            /*  Tein des PWM Signals 
*/

        int c = ((float)Te * (float)TOP);
        setze_tastverhaeltnis(adc_ergebnis[2]);
        //setze_tastverhaeltnis(Te * TOP / T_pwm);
        PORTD &= ~_BV(PD7);
}

Separate Datei:


SIGNAL(SIG_ADC)                      //interrupte sind in ISR 
automatisch ausgeschaltet
{
    adc_ergebnis[kanal_index]   = ADCL;     //erst ADCL dann ADCH um 
sicherzustellen
                                            //           das Werte aus 
einer Wandlung stammen;
    adc_ergebnis[kanal_index]  += (ADCH<<8);

    kanal_index++;
    if(kanal_index==3)
        kanal_index=0;

    ADMUX = adc_kanal[kanal_index]; /* ca. 100 Zyklen seit der Interrup 
ausgelöst wurde */
                                    /*wir können also den mux neu muxen 
*/
    ADCSRA |= _BV(ADSC);
}




Es geht um adc_ergebnis[x]
Gast #466427
Lesenswert?
• ▲
▼
Ahh hallo,

nichts für ungut. Ich bin ja kein Baby mehr. Abgesehen davon dürfte das 
wohl einige arbeit werden das ins avrstudio zu bringen. Aber bitte im 
anhang ist das projekt. Ich dachte nur ob jemand etwas in dem Zusammen 
hang weiss. Ich habe es jetzt anders gemacht. Und zwar habe ich noch 
einen zeiger auf adc_ergebnis erstellt. diesen benutze ich jetzt in der 
ISR.

Ich habs mal angehangen. Es ist ein PWM Servotreiber.
fall jemand interesse an der Elektronik hat, ich bin unter 
florian.hillen@web.de zu erreichen oder gleich hier.

Frohes neues Jahr!
Angehängte Dateien:
#466449
Lesenswert?
• ▲
▼
Das einzige was ich bis jetzt im Debugger gesehen habe ist,
dass dein Overflow Interrupt zuviel Zeit braucht. Der Prozessor
arbeitet praktisch nur da drinnen. Sobald die ISR fertig ist,
beginnt auch schon der nächste ISR, weil der Timer in der
Zwischenzeit den nächsten Überlauf produziert hat.
Setzt mal den Vorteiler etwas höher.
Gast #466456
Lesenswert?
• ▲
▼
aha das werde ich einmal Probieren.
Ich habe festgestellt das da was nicht stimmt weil ich an meiner 
Leistungselektronik einen Motor habe und der immer nur nach dem ersten 
ADC Wert ging.
Ich probies direkt mal aus und meld mich nochmal. Vielen dank auch!
Florian
#466460
Lesenswert?
• ▲
▼
Also wars doch ganz gut das vollständige Projekt zu posten :-)

Merke: Wenn jemand glaubt dass er einen Compilerfehler entdeckt
hat, dann hat er zu 99% ein anderes Problem im Programm. Natürlich
haben auch Compiler so ihre Fehler. Aber nicht bei einem
simplen Variablenzugriff.
Gast #466497
Lesenswert?
• ▲
▼
> auf AVRs zwar 999 von 1000 mal wunderbar funktionieren wird,
> aber ab und zu Schrott rauskommt.

Nun, der Schrott macht aber nicht der Compiler, sondern der 
Programmierer, wie üblich. Die Lösung des Problems lautet:


  volatile unsigned short x;

  ISR(suchesdiraus)
  {
    x = irgendwas;
  }

  main()
  {
    unsigned short x_copy;
    while(1)
    {
      cli();
      x_copy = x;
      sei();
      tu_irgendwas_mit(x_copy);
    }
  }


Gast #466501
Lesenswert?
• ▲
▼
Sollte die Funktion von cli(); und sei(); nicht der Grund sein, warum 
man die Variable als volatile deklariert (mehr als 1 Byte zum Lesen)? 
Sollte eigentlich automatisch vom Compiler erledigt werden.
Gast #466504
Lesenswert?
• ▲
▼
Nein.

"volatile" sorgt dafür, dass die tatsächlich durchgeführten Zugriffe 
denen im Quelltext entsprechen, d.h. dass da nichts wegoptimiert oder 
umsortiert wird. Atomar werden die Zugriffe mit "volatile" jedoch nicht.
Gast #466510
Lesenswert?
• ▲
▼
"Nun, der Schrott macht aber nicht der Compiler"

Wollte ich damit auch nicht ausdrücken. Ich hatte bei Florians Code 
jedoch gleich den Verdacht, dass unabhängig vom eigentlichen Problem 
jemand, der in Interrupts Floating-Point-Rechnungen durchführt, diese 
Feinheit im Umgang mit globalen Variablen auch übersehen hatte - und 
genau so ist es.
Gast #466515
Lesenswert?
• ▲
▼
Hmm.. so wie ich das verstanden habe dient volatile (!beim AVR!) dazu, 
Variablen, die außerhalb der Funktion 'main' behandelt werden, neu 
einzulesen und während des Einlesens den globalen INT zu sperren, um 
teilweises Lesen zu vermeiden, falls währenddessen ein INT auftritt. 
Hatte auch noch nie Probleme in der Richtung.
Aber, falls das anders ist, wieder was gelernt.
Gast #466518
Lesenswert?
• ▲
▼
Bei Ports und Steuerregistern muss er das ja auch nicht, da die 
Byteorientiert sind. Dachte, nötig ist es nur bei Variablen >8 Bit, da 
es mehrerer Leseoperationen für diese Typen bedarf. Lasse mich aber 
gerne eines Anderen belehren.
Gast #466537
Lesenswert?
• ▲
▼
Ist auch nur bei >8bit nötig, allerdings sind manche I/O-Register >8 
breit (z.B. bei Timer, ADC). Aber das Philosophieren lässt sich ganz 
einfach abkürzen: Guck in den Code und vertrau darauf, dass GCC sich 
korrekt verhält. Stimmt fast immer.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.