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 !
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.
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];
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.
Soooorry... habe vor lauter Müdigkeit zu früh abgesendet... vernünftiger Code kommt gleich....
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.
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 !
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?
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 !
Hallo! Belegter Speicher: Device: atmega16 Program: 11954 bytes (73.0% Full) Data: 799 bytes (78.0% Full)
Hans wrote:
> Woran kann das liegen? LocalBuffer ist global definiert.
Genialer Name.
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.
Mach ich. Haben wir noch rumliegen.. langsam werd ich verrückt. Muss man speziell aufpassen mit Division durch Null oder Ähnliches?
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.
Hastu vll. Watchdog losgelassen und verrennst dich in lange Berechnungen ohne ihn zurückzupfeifen? (mit "wdr")
Hans wrote: > Muss man > speziell aufpassen mit Division durch Null oder Ähnliches? Nein, Traps kennt ein AVR nicht.
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
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.....
> 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.
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 | }
|
Was ich oben schon mal anregte: Kann es sein, dass localBuffer zu klein ist, d.h. mehr reingeschrieben wird als darin Platz hat?
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 !
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.