Forum: Compiler & IDEs Checkliste Softwarereset AVR


von Hans (Gast)


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 !

von John S. (linux_80)


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.

von Hans (Gast)


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];

von Andreas K. (a-k)


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.

von Hans (Gast)


Lesenswert?

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

von Andreas K. (a-k)


Lesenswert?

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

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

von Hans (Gast)


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)
1
void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
2
{
3
  newVal_flag = 1;
4
5
  u08 i;
6
  //Daten speichern...
7
  for(i=0; i<receiveDataLength; i++)
8
  {
9
    localBuffer[i] = *receiveData++;
10
  }
11
  localBufferLength = receiveDataLength;
12
  //Buffer analysieren... (Regelgrößen)
13
  switch(localBuffer[0])
14
  {
15
  case 'A':
16
  //p_1_soll_i2c = localBuffer[3];
17
  x_soll_i2c  =localBuffer[1];
18
  //c_soll =localBuffer[2];
19
 //p_1_soll_i2c =localBuffer[1];
20
  //p_2_soll_i2c =localBuffer[2];
21
}

Bei gesetztem Flag wir nun folgendes in main() freigegeben:
1
      if(newVal_flag)
2
      {  
3
        
4
        //  Umrechnung von 8 bit Zahl in double Werte in mm
5
        
6
        x_soll =  Weg_Umrechnung_i2c(x_soll_i2c);
7
8
        F_vorspann =  Vor_Spann_Kraft_Berechnung(c_soll, x_ist);
9
10
        //Solldruck 1        
11
12
        p_1_soll = 0.3333 * F_vorspann + C_3 ;
13
      
14
        p_1_soll = p_1_soll * pow(  (C_1*pow( (1-C_2*x_soll),2)) ,-1 ) ;
15
16
        //Solldruck 2
17
18
        p_2_soll = 0.3333 * F_vorspann + C_3 ;
19
      
20
        p_2_soll * pow(  (C_1*pow( (1-C_2*(-x_soll)),2)) ,-1 ) ;
21
22
        p_2_soll_i2c = 255 / 8 * p_2_soll; 
23
24
        p_1_soll_i2c = 255 / 8 * p_1_soll;
25
26
        newVal_flag = 0;
27
      }
28
29
      OCR1AL=  PID_Druckregler_p_1();
30
      OCR1BL= PID_Druckregler_p_2();

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

Viele Grüße !

von Andreas K. (a-k)


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?

von Hans (Gast)


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 !

von Hans (Gast)


Lesenswert?

Hallo!

Belegter Speicher:

Device: atmega16

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

von Andreas K. (a-k)


Lesenswert?

Hans wrote:

> Woran kann das liegen? LocalBuffer ist global definiert.

Genialer Name.

von Hans (Gast)


Lesenswert?

Mhh.... da hast du wohl recht. Ziemlich bescheuert von mir....

von Andreas K. (a-k)


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.

von Hans (Gast)


Lesenswert?

..und von Pascal Stang.

von Hans (Gast)


Lesenswert?

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

von Andreas K. (a-k)


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.

von Compy (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hans wrote:

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

Nein, Traps kennt ein AVR nicht.

von Frank B. (frank_b) Benutzerseite


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

von Hans (Gast)


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.....

von Karl H. (kbuchegg)


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.

von Hans (Gast)


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:
1
//Includes
2
#inlcude.... Standardfunktionen, i2c.h, uart.h
3
//globale Variablen...
4
u08 p_1_soll_i2c = 0;
5
//usw....
6
7
u08 localBuffer[] = "Ich bin hier definiert!";
8
void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData);
9
int main(void)
10
{
11
   PWMInit();
12
   uartInit();
13
   i2cInit();
14
   //Festlegen der Lokalen Slave-Adresse
15
   i2cSetLocalDeviceAddr(120, TRUE);
16
   //IR Service bei Aufforderung zum Empfangen
17
   i2cSetSlaveReceiveHandler(i2cSlaveReceiveService);
18
   //IR Service bei Aufforderung zum Senden
19
   i2cSetSlaveTransmitHandler(i2cSlaveTransmitService);
20
      
21
  for(;;)
22
  {
23
     "Werden die folgenden 2 Zeilen auskommentiert, reagiert die PWM nicht mehr ! Sonst wohl."
24
     uartPutChar(localBuffer[1]);//oder:uartPutChar(p_1_soll_i2c)
25
     uartPutChar(localBuffer[1]);//oder:uartPutChar(x_soll_i2c)
26
     
27
     
28
     OCR1AL = p_1_soll_i2c;
29
  }
30
return 0;
31
}
32
void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
33
{ 
34
  //Daten speichern...
35
   for(i=0; i<receiveDataLength; i++) 
36
   { 
37
      localBuffer[i] = *receiveData++; 
38
   } 
39
   localBufferLength = receiveDataLength; 
40
   //Buffer analysieren... (Regelgrößen)
41
  switch(localBuffer[0])
42
  {  
43
    case 'A':
44
      p_1_soll_i2c = localBuffer[3];        
45
      x_soll_i2c  = localBuffer[1];
46
  //  c_soll =localBuffer[2];
47
  //  p_1_soll_i2c =localBuffer[1];
48
  //  p_2_soll_i2c =localBuffer[2];
49
  
50
    break;
51
  }
52
}

von Andreas K. (a-k)


Lesenswert?

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

von Hans (Gast)


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 !

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.