www.mikrocontroller.net

Forum: Compiler & IDEs Checkliste Softwarereset AVR


Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo !

Kennt jemand einen Link zu einer Checkliste, warum AVRs resetten ?

Ich bin mir 99.999%ig sicher, dass es ein Softwarefehler ist und nicht 
an der Hardware bzw. Beschaltung liegt.

Habe ein recht umfangreiches Programm, dass bei einigen Berechnungen 
(bin leider auf Fließkommazahlen angewiesen) und teilweise bei einer 
i2c-Slave-Zeichen-empfangen Funktion resettet.

Für einen Tipp bin ich sehr dankbar !

Schönen Abend (Nacht) noch !

Autor: John Small (linux_80)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Checkliste hab ich keine, aber was öfter vorkommt ist zB.
- ein nicht geplanter aber aktivierter IRQ, der dann als Reset endet, 
weil die ISR nicht vorhanden ist.
- es gibt keine Endlosschleife, dann läuft das Programm irgendwann bis 
ans Ende des Flashs, und fängt wieder von vorne an -> Reset
- es werden mehr Daten aus dem Stack geholt, als hineingestellt wurden, 
bei einem RET könnte das an der Adresse 0000 landen. Hab ich aber noch 
nicht selber nachgeprüft.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Danke für die Antworten!

Wie kann ich das mit den ISR überprüfen? Ich habe halt einen Timer 
laufen, sowie den IRQ für das TWI. Oft kommt ein Reset bei dem Aufruf 
der ISR der mir die über i2c empfangenen Zeichen speichert.

Das wäre diese Funktion: (AvrLib, Pascal Stang)
[c]

void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
{
newVal_flag = 1;

u08 i;
//Daten speichern...
for(i=0; i<receiveDataLength; i++)
{
localBuffer[i] = *receiveData++;
}
localBufferLength = receiveDataLength;
//Buffer analysieren... (Regelgrößen)
switch(localBuffer[0])
{
case 'A':
//p_1_soll_i2c = localBuffer[3];
x_soll_i2c  =localBuffer[1];
//c_soll =localBuffer[2];
//p_1_soll_i2c =localBuffer[1];
//p_2_soll_i2c =localBuffer[2];

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erst mal rauskriegen, woher der Reset kam. Also beim Start MCUSR 
anzeigen und auf 0 setzen. Dann ist schonmal klar, ob es überhaupt ein 
Reset war, oder eher doch ein Sprung nach 0.

Sprung nach 0 beispielsweise:
- Interrupt A eingschaltet und ISR(B) definiert,
- Stacküberlauf,
- Buffer overflow bei lokaler Variable.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Soooorry... habe vor lauter Müdigkeit zu früh abgesendet... vernünftiger 
Code kommt gleich....

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn localBuffer das ist wonach es klingt, dann ist receiveDataLength 
möglicherweise manchmal grösser als localBuffer.

ISR kontrollieren:
ISR(__vector_default)
{
    ...Fehlermeldung...
}
definieren. Wenn dort was aufläuft, fehlt eine ISR.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Danke für die Antworten!

Wie kann ich das mit den ISR überprüfen? Ich habe halt einen Timer
laufen, sowie den IRQ für das TWI. Oft kommt ein Reset bei dem Aufruf
der ISR der mir die über i2c empfangenen Zeichen speichert.

Das wäre diese Funktion: (AvrLib, Pascal Stang)

void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
{
  newVal_flag = 1;

  u08 i;
  //Daten speichern...
  for(i=0; i<receiveDataLength; i++)
  {
    localBuffer[i] = *receiveData++;
  }
  localBufferLength = receiveDataLength;
  //Buffer analysieren... (Regelgrößen)
  switch(localBuffer[0])
  {
  case 'A':
  //p_1_soll_i2c = localBuffer[3];
  x_soll_i2c  =localBuffer[1];
  //c_soll =localBuffer[2];
 //p_1_soll_i2c =localBuffer[1];
  //p_2_soll_i2c =localBuffer[2];
}

Bei gesetztem Flag wir nun folgendes in main() freigegeben:
      if(newVal_flag)
      {  
        
        //  Umrechnung von 8 bit Zahl in double Werte in mm
        
        x_soll =  Weg_Umrechnung_i2c(x_soll_i2c);

        F_vorspann =  Vor_Spann_Kraft_Berechnung(c_soll, x_ist);

        //Solldruck 1        

        p_1_soll = 0.3333 * F_vorspann + C_3 ;
      
        p_1_soll = p_1_soll * pow(  (C_1*pow( (1-C_2*x_soll),2)) ,-1 ) ;

        //Solldruck 2

        p_2_soll = 0.3333 * F_vorspann + C_3 ;
      
        p_2_soll * pow(  (C_1*pow( (1-C_2*(-x_soll)),2)) ,-1 ) ;

        p_2_soll_i2c = 255 / 8 * p_2_soll; 

        p_1_soll_i2c = 255 / 8 * p_1_soll;

        newVal_flag = 0;
      }

      OCR1AL=  PID_Druckregler_p_1();
      OCR1BL= PID_Druckregler_p_2();


leider ziemlich viel Fließkommazeugs.... bin aber auf diese Funktionen 
angewiesen...Weiß jemand Rat?

Viele Grüße !

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit diesen Code-Fragmenten kann man nichts anfangen. Wichtiger wäre 
beispielsweise die Steuerung der Interrupt-Flags und die entsprechenden 
Routinen, und der ganze Kram vom I2C, inklusive Pufferdefinitionen.

Wieviel RAM von wieviel ist denn belegt?

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Während ich geschrieben habe kamen ja schon einige Antworten! Danke 
dafür! Ich werds mal probieren und berichten.

Ach ja eins noch:

Wenn ich den localBuffer per USART sende, bleibt er erhalten, mache ich 
dies nicht, wird er auf Anfangswert gesetzt. Ich hielt das bis dato für 
einen Reset...

Woran kann das liegen? LocalBuffer ist global definiert.

Grüße !

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Belegter Speicher:

Device: atmega16

Program:   11954 bytes (73.0% Full)
Data:        799 bytes (78.0% Full)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:

> Woran kann das liegen? LocalBuffer ist global definiert.

Genialer Name.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mhh.... da hast du wohl recht. Ziemlich bescheuert von mir....

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:

> Program:   11954 bytes (73.0% Full)
> Data:        799 bytes (78.0% Full)

200 Bytes Stack kann grad bei vielen lokalen Variablen und komplettem 
printf oben drauf schon knapp werden. Wenn du hast, probier mal einen 
Mega32 aus, der hat 2KB.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
..und von Pascal Stang.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach ich. Haben wir noch rumliegen.. langsam werd ich verrückt. Muss man 
speziell aufpassen mit Division durch Null oder Ähnliches?

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:

> Mach ich. Haben wir noch rumliegen.. langsam werd ich verrückt. Muss man
> speziell aufpassen mit Division durch Null oder Ähnliches?

Keine Ahnung. Bei sowas ist ratsam, defensiv vorzugehen, und es garnicht 
erst nicht darauf ankommen zu lassen.

Autor: Compy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hastu vll. Watchdog losgelassen und verrennst dich in lange Berechnungen 
ohne ihn zurückzupfeifen? (mit "wdr")

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

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:

> Muss man
> speziell aufpassen mit Division durch Null oder Ähnliches?

Nein, Traps kennt ein AVR nicht.

Autor: Frank B_. (frank_b) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Data:        799 bytes (78.0% Full)

Bei dem vielen "Fliesskommazeugs" könnte es ein wenig eng auf dem Stack 
werden. Das ist leider ein Stack-Fresser.

Frank

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ! Erstmal Danke für die Antworten! Also der Watchdog ist definitiv 
aus. Also ich werde mal einen Mega32 probieren. Grad wegen dem Stack.

Was mir am komischten vorkommt ist das, was ich oben schrieb:

Wenn ich den localBuffer in main() immer wieder per USART sende, bleibt 
er erhalten, mache ich
dies nicht, wird er auf Anfangswert gesetzt. Ich hielt das bis dato für
einen Reset...

Naja... weiter probieren. Das blöde ist nur, wenn man nicht wirklich 
Ahnung von den Hardwareabläufen an sich hat ist diese Probiererei ein 
Fass ohne Boden.....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich den localBuffer per USART sende, bleibt er erhalten, mache ich
> dies nicht, wird er auf Anfangswert gesetzt. Ich hielt das bis dato für
> einen Reset...

Was denn nun?
Passiert ein Reset oder passiert keiner?

Das wäre mal das erste was es herauszufinden gilt.
Du musst es dir zur Regel machen bei der Fehlersuche
nichts, aber auch gar nichts, als gesichert anzunehmen
(OK. Man kann mal davon ausgehen, dass der Compiler
keinen Fehler gemacht hat und dass die Systemlibrary
funktionieren wird).

Zweifle alles und jeden an, bis du durch Tests ausschliessen
kannst, dass da ein Fehler drinnen steckt. Man sollte nicht
für möglich halten, wieviele Leute Fehler in Berechnungen
suchen und sich nach Stunden herausstellt, dass schon
die Eingangswerte in diese Berechnung fehlerhaft sind und
die Berechnung an sich völlig in Ordnung ist.
Garbage in - Garbage out.

Das meine ich mit: Zweifle alles und jeden an und mag es noch
so banal sein. Keine Vermutungen, nur harte Fakten zählen.
Ich finde es irgendwo schon sträflichen Leichtsinn, dass
du bis jetzt nur vermutest, dass ein Reset gemacht wird
und das noch nicht abgetestet hast. Am Programmanfang eine
LED einschalten, die nur mit einem Tastendruck ausgeschaltet
werden kann und dann die Schaltung einfach mal Laufen lassen.
LED abschalten und warten. Wenn dein Fehler auftritt und die
LED brennt, dann war das ein Reset. Brennt die LED nicht, dann
ist auch kein Reset vorgekommen.

Oft sind solch seltsame Fehler wie deiner ein Zeichen dafür,
dass du zuviel Code auf einmal geschrieben hast ohne zwischen-
durch immer wieder extensive Tests durchzuführen. Man steht
dann mit einem Haufen Code da und weiss nicht wo man zu Suchen
anfangen soll.
Daraus ergibt sich unter Umständen aber auch folgende Strategie:
Code auskommentieren und zurückschrauben bis man in einem
funkionierenden Zustand ist. Dann nach und nach sukzessive
den auskommentierten Code wieder freigeben und jeweils umfangreiche
Tests machen, ob irgendetwas auffällt. Das geht am Besten, wenn
dein Code nicht Kraut und Rüben ist, sondern sauber in Module
aufgeteilt ist. Modulare Programmierung hat auch beim Testen
so seine Vorteile.

Das allerwichtigste beim Debuggen ist aber: Den Fehler
reproduzierbar machen. Du musst exakt wissen was du tun
musst um den Fehler zu forcieren. Solange du das nicht weist
ist alles andere ein Stochern im Nebel. Nur mit der Kenntnis
der Schrittfolge, die zum Fehler führt, hat man eine Chance
zielgerichtet nach einem Codeproblem zu suchen.

Ein bischen Glück und Intuition braucht man aber dann trotzdem.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl-Heinz!

Ersmal Danke für die umfangreiche Antwort!

Definitives kann ich nun sagen: Es handelte sich un Resets.

Plötzliche Resets wurden durch Senken der Baudrate von 34800 auf 9600 
behoben.

Der Fehler mit diesem doofen localBuffer bleibt aber auch, nach 
Auskommentieren von allem, außer den nötigen Grundfunktionen, um den 
Fehler hervorzurufen. localBuffer als volatile hilft nicht! Vielleicht 
weiß noch jemand etwas? das senden der Zeichen nervt und macht das 
Programm unnötig langsamer...

Viele Grüße!


Das (rudimentäre)Programm:
//Includes
#inlcude.... Standardfunktionen, i2c.h, uart.h
//globale Variablen...
u08 p_1_soll_i2c = 0;
//usw....

u08 localBuffer[] = "Ich bin hier definiert!";
void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData);
int main(void)
{
   PWMInit();
   uartInit();
   i2cInit();
   //Festlegen der Lokalen Slave-Adresse
   i2cSetLocalDeviceAddr(120, TRUE);
   //IR Service bei Aufforderung zum Empfangen
   i2cSetSlaveReceiveHandler(i2cSlaveReceiveService);
   //IR Service bei Aufforderung zum Senden
   i2cSetSlaveTransmitHandler(i2cSlaveTransmitService);
      
  for(;;)
  {
     "Werden die folgenden 2 Zeilen auskommentiert, reagiert die PWM nicht mehr ! Sonst wohl."
     uartPutChar(localBuffer[1]);//oder:uartPutChar(p_1_soll_i2c)
     uartPutChar(localBuffer[1]);//oder:uartPutChar(x_soll_i2c)
     
     
     OCR1AL = p_1_soll_i2c;
  }
return 0;
}
void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
{ 
  //Daten speichern...
   for(i=0; i<receiveDataLength; i++) 
   { 
      localBuffer[i] = *receiveData++; 
   } 
   localBufferLength = receiveDataLength; 
   //Buffer analysieren... (Regelgrößen)
  switch(localBuffer[0])
  {  
    case 'A':
      p_1_soll_i2c = localBuffer[3];        
      x_soll_i2c  = localBuffer[1];
  //  c_soll =localBuffer[2];
  //  p_1_soll_i2c =localBuffer[1];
  //  p_2_soll_i2c =localBuffer[2];
  
    break;
  }
}

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ich oben schon mal anregte: Kann es sein, dass localBuffer zu klein 
ist, d.h. mehr reingeschrieben wird als darin Platz hat?

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andreas !

Nein, momentan kommt nur : 'Abc$' über den Bus. Und das nur auf 
Knopfdruck über eine MATLAB GUI.

Also kleiner als definiert.....

Viele Grüße !

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

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:

> Definitives kann ich nun sagen: Es handelte sich un Resets.

Wenn du das so definitiv sagen kannst, dann kannst du uns ja an Hand
von MCUCSR auch noch sagen, welcher Reset es denn war.  Vergiss
bitte nicht, die Bits dort nach dem Auswerten zu löschen, die
akkumulieren andernfalls bis in alle Ewigkeit.

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.