Hallo zusammen,
ich arbeite nun seit 3 Tagen an meiner Schaltung, die ab und zu einen
RESET auslöst.
Hintergrund: Schaltung besteht aus 7805, ATmega644, 20MHz und einem
Onbord-Diagnose-Chip ELM327 1.3. Ich nutze AvrStudio 4 und den
aktuellsten GCC-Compiler.
Ich lasse den ATmega und den ELM327 über UART und 19200 Baud
kommunizieren. Laut Datenblatt ergibt sich dabei eine Fehlerrate von
0,2%. Allerdings kann ich nicht einschätzen, ob das nun schlecht oder
noch akzeptabel ist.
Es werden vom Atmega644 Befehle in Form von 3 bis 5 Byte übertragen und
empfängt Daten in Form von 4 bis 12 Bytes.
Das alles funktioniert erstmal einwandfrei und irgendwann unregelmäßig
alle 5 Sekunden bis 3 Minuten gibts einen RESET.
Ich habe mir nach dem Reset mal die Resetquelle im Register MCUSR
angeschaut.
Im letzten Durchlauf gab es 3 Resets, davon 1x JTAG-Reset-Flag und 2x
WATCHDOG-Reset-Flag.
Komisch, dass ich weder JTAG nutze, noch den WATCHDOG aktiviert habe.
Wenn ich allerdings die wdt_disable() einbinde, dann bleibt er bei einem
Reset völlig hängen, was darauf schließt, dass der Watchdog doch
eingeschaltet ist. Das tue ich aber nicht selber im Sourcecode.
Der Uart nutzt einen Rx-Interrupt. Ich nutze einen 1ms-zyklischen
TimerCompare-Interrupt fürs Zeitmanagement. Kann das sich gegenseitig
stören?
Ich hoffe es findet sich ein pfifiger Helfer.
Danke und Gruß,
Danilo
Wenn Du alles so gemacht hast, wie Du beschreibst, kann das Problem
garnicht auftauchen.
Um das zu beurteilen, musst Du uns aber zumindest den Schaltplan sowie
das Programm zeigen.
Sind alle Interrupt-Vektoren mit reti belegt? Wenn nein, wäre das mal
ein Anfang.
Hallo,
> Laut Datenblatt ergibt sich dabei eine Fehlerrate von> 0,2%. Allerdings kann ich nicht einschätzen, ob das nun schlecht oder> noch akzeptabel ist.
In Summe dürfen bei 10-11 Bit Sender und Empfänger ca 3-4%
auseinanderlaufen bevor Übertragungsfehler auftreten.
Zu den Resets: Ich würde versuchen die Ursache herauszufinden.
Vielleicht hilft ja mal mit dem "nassen Daumen" oder einem Metallstift
an den Pins entlangfahren wo die empfindliche Stelle ist.
Falls es der Reset-Pin ist hilft ein 1nF bis 10nF Kondensator direkt an
den Gnd-Pin des Prozessors.
Die anderen üblichen verdächtigen sind:
- lange Anschlußleitungen zum Abblockkondensator.
- Quarzanschlüsse zu lang.
- Quarz-Kondensatoren nicht auf kürzestem Weg mit einzelner Leitung an
Prozessor-Massepin.
- Evtl hilft auch das Quarz-Gehäuse auf Gnd zu löten.
die Reti-Codes werden doch automatisch eingefügt.
Laut Listfile sind sie allen Ende eines Interrupts als letzer Opcode.
Schaltplan habe ich leider nur im Kopf.
Manchmal wird auch eine RESET ausgelöst und es ist kein einziges
Resetquellen-Flag gesetzt. Laut anderen Beiträgen kann das nur ein
Sprung auf den Nullvektor sein.
Ich verwende String.h-Funktionen wie strstr(), die ich allerdings immer
auf Null-Pointer überprüfe.
Welche Bedingungen müssen erfüllt sein, dass ein Sprung auf NULL
geschieht oder dass JTAG-Reset-Flag kommt, obwohl ich nix mit JTAG
mache.
Auch der Watchdog ärgert ungewollt.
Gruß, Danilo
Danke für die Tips.
Der Reset Pin ist über 10k an 5V.
und zwischen 5V und GND sind 100nF.
Aber wenns der Reset-PIN wäre, würde ich ja eine EXTernes Reset-Flag
sehen und das sehe ich nie.
Danilo schrieb:
> [X] Brownout detection disble (BODLEVEL = 111)
Das ist allerdings eher ungünstig. Wenn der µC bei einem
Spannungseinbruch unkontrolliert abschmiert, kann alles mögliche
passieren. Ich würde das mal aktivieren. Würde mich nicht wundern, wenn
dann die Reset-Quelle immer BORF wäre.
Es sind nicht die RETI am Ende der ISRs gefragt, sondern die RETI in der
Vektortabelle am Anfang des FLASH. D.h. an den Positionen für die es
keine ISR gibt.
Schaltplan im Kopf ist nicht gut.
Seltsame Sprünge können auch passieren, wenn der Stack mit den
Rücksprungadressen zerschossen wird.
Wieviel des RAM wird benutzt? Es interessiert der von .data, .bss und
.noinit benutzte Bereich und noch stärker die zur Laufzeit von
Funktionen benötigte Bereich. Fummelst du im Programm mit Zeigern rum?
Mit dynamischer Speicherallokation? Mit Kopieraktionen zwischen Puffern?
Viele lokale Daten in den Funktionen? strstr() kann ein Kandidat sein;
Die Funktion lebt davon, dass sie sauber abgeschlossene Strings
vorfindet. Wenn nicht, kann die nett in der Pampa rumpoken.
Da Schaltplan und Sourcecode fehlen, musst du deinen Kopf martern und
dich dich durch den hochgeheimen Sourcecode alleine durchbeissen ;-)
Also ich habe nie Brownount ResetFlag BORF gesehen.
Fuses:
HighFreq gewählt: ja
CKOPT find ich grad nicht als Option ín den Fuses. Wo finde ich das?
Ich nutze Avr-OsII als Programmer.
ok, ich gebe zu, dass ich Strings kopiere und mit Pointern rummache ;)
Gibt es da angewandte Techniken im Fehlerfall (also String beim Suchen
nicht gefunden oder String kopieren fehlerhaft) um solche ungewollten
Sprünge zu verhindern?
Den NULL-Pointer bei String-im-String-suchen-nicht-gefunden, verhindere
ich bereits.
Da ich nicht an meiner Elektronik-Schrank sitze sondern daheim, hab ich
auch keinen 10nF zu Hand. Ich werde es mir merken und bei gelegenheit
anlöten.
RETI:
Wo muss ich da nachschlagen, um die Vektortabelle zu sehen?
RAM/Stack:
Es sind 30% 1250/4096 Bytes verbraucht.
Ich hab das Problem auch mal im Simulator durchlaufen und da ist der
Stackverbrauch gerade mal 18 Bytes.
Auch eine Stack-Prüfung, die gestern gefunden habe, ergab ausreichen
viel Stack-Resourcen.
Weitere Vorschläge?
Uwe ... schrieb:
> Prüf mal die WDTON-Fuse, und füg nen>> ISR(BADISR_vect)>> {>> // Hier irgendwie ne Meldung ausgeben>> }>> im Programm ein.
Diese ISR wird anscheinend nicht ausgeführt.
Würde sie aufgerufen werden, wenn der Watchdog aus ist?
Das Resetflag signalisiert ja einen Watchdog reset ab und zu.
Danilo schrieb:
> Also ich habe nie Brownount ResetFlag BORF gesehen.
Wie auch, wenn der Brown-Out deaktiviert ist.
Wie bereits gesagt, dadurch stürzt der µC bei einem Spannungseinbruch
unkontrolliert ab. Und zu dem "dann kann alles mögliche passieren"
gehört auch ein irreführender Inhalt in MCUSR.
Du musst dafür sorgen, dass deine Strings immer mit einem '\0'
abgeschlossen sind und bei der Übergabe von berechneten Stringadressen
dieses Nullbyte nicht übersprungen wird.
Die Vektorsprungtabelle findest du im Disassembler am Programmanfang. Es
müssen dort keine RETI stehen. Ich habe gerade in einem Projekt von mir
nachgesehen und RJMP PC+... gefunden (Attiny2313). Ich meine auch
bereits JMP ... gesehen zu haben. RETI ist möglicherweise nur in
Assemblerprogrammen zu finden; ich weiss nicht, ob der GCC im
Startupcode RETI benutzt.
Die Daten zu RAM/Stack hören sich eigentlich gesund an.
Vektortabelle ist mit JMP gefüllt.
Bevor ich Daten empfange beschreibe ich schon den ganzen Buffer mit
Nullen.
Somit ist jeder eingetragene String mit \0 abgeschlossen.
Zu Zeit gibts alle 30 bis 300 UART-Botschaften (ca. 5s bis 1 min) einen
Reset.
Dazu habe ich mir einen Zähler (datentyp: unsigned short) pro
Uart-Message aufs LCD geschmissen.
Aufgefallen ist, dass dieser Zähler ab und zu genullt wird, obwohl nur
Inkrement-Anweisungen (++) ihn verändern können.
Hast du das mit dem Brown-Out aktivieren wenigstens mal ausprobiert?
Wenn ich hier eh nur gegen eine Wand rede, kann ich mir auch jeden
weiteren Kommentar sparen.
Sorry für die späte antwort. war noch am tüffteln...
BrownOut Flag kommt nicht auch wenn BOD-Fusebit gesetzt
Ich steh irgendwie auf dem schlauch.
ich habe nun alles auskommentiert, so dass keine string-sachen
ausgeführt werden.
wenn ich allerdings folgende zeile drin lass, gibt eben diese
sporadischen resets.
Danilo schrieb:
> wenn ich allerdings folgende zeile drin lass, gibt eben diese> sporadischen resets.>
1
strcpy(SearchCmd,"AT");
>> Datentyp: char SearchCmd[8];>> Ideen?
Der strcpy da oben ist es nicht.
Allerdings gehe ich trotzdem eine Wette ein, dass du irgendwo einen
Buffer überläufst.
> Dazu habe ich mir einen Zähler (datentyp: unsigned short) pro> Uart-Message aufs LCD geschmissen.> Aufgefallen ist, dass dieser Zähler ab und zu genullt wird, obwohl> nur Inkrement-Anweisungen (++) ihn verändern können.
Und das bestätigt mich in meiner Meinung.
Wenn Variablen 'eigenständig' auf seltsame Weise ihren Wert ändern, dann
ist das meistens ein Indiz für einen Bufferüberlauf irgendwo.
Lasse ein grep alle Zeilen ausgeben, in denen SearchCmd vorkommt.
Achte auf direktes Erhöhen/Erniedrigen von SearchCmd, ob lokale
Variablen oder Funktionsargumente mit gleichem Namen vorkommen und an
welche Funktionen du SearchCmd übergibst.
Stefan B. schrieb:
> Lasse ein grep alle Zeilen ausgeben, in denen SearchCmd vorkommt.
Ein einfaches "Suche Nach" reicht völlig. Da muss man nämlich nicht erst
sämtliche Manuals nach der Syntax wälzen.
Hallo,
das problem ist noch nicht gelöst. aber es gibt neue indizien.
ich bekomme zwar unregelmäßig nen reset, aber diesmal ist keine
resetquelle verwicklelt. das deutet doch auf ein sprung auf den
NULL-vektor hin?
meine Senderoutine:
1
voidDiag_SendCmd(unsignedcharpCmd)
2
{
3
charUartBuffer[10];
4
strcpy(UartBuffer,"ATRV");
5
uart_puts(UartBuffer);
6
}
char UartBuffer[10] ist eine lokale Variable in der Sendefunktion.
hier meine main():
> char UartBuffer[10] ist eine lokale Variable in der Sendefunktion.>> hier meine main():>
1
>do
2
>{
3
>Diag_SendCmd(SEND_SIGNAL);
4
>WaitInMs(50);
5
>}
6
>while(1);
7
>
Das ist alles?
Mehr ist nicht in deinem Programm?
(ok, dass da noch uart Funktionen existieren ist schon klar. Aber von
denen gehe ich mal aus, dass sie ausreichend getestet wurden. Obwohl ...
beim debuggen soll man sich auf nichts verlassen. Vor allen Dingen nicht
bei mysteriösen Fehlern)
Hmm. Wenn da tatsächlich nicht mehr vorhanden ist, ist ein
Softwarefehler tatsächlich unwahrscheinlicher geworden.
uart_puts() stammt doch aus der Fleury UART-Library, hast du
geschrieben?
Der gezeigte Code macht für mich keinen Sinn.
pCmd bzw. SEND_SIGNAL wird nicht benutzt. Der Zwischenpuffer
UartBuffer und das strcpy() wird technisch betrachtet nicht benötigt,
weil die uart_puts() eine Kopie des Strings im TX-Ringpuffer der Library
ablegt.
Doku zu uart_puts() bei Fleury:
http://homepage.hispeed.ch/peterfleury/group__pfleury__uart.html#ga3
Hallo Leute,
erstmal vielen Dank für euren Hilfestellungen und Vorschläge.
Das Problem scheint gelöst zu sein! :))
Ich hatte mehrere strchr()- und strstr()-Funktionen.
Da diese im Fehlerfall den NULL-Pointer zurückgeben, habe ich die
Return-Werte immer abgefragt, bevor ich weiter gemacht habe.
...außer an einer Stelle. Da kamm es dann zum Pointer-Salat. :(
Also an alle: Achtung bei Funktionen, die einen Pointer zurückgeben!
Dieser kann NULL sein und das muss abgefangen werden!!
gruß und vielen Dank nochmal,
Danilo
Hallo wieder mal,
ich habe nun seit einiger Zeit wieder mein Bordcomputer
weiterentwickelt.
Dieser hatte zu beginn unvorhersehbar resettet.
Grund schien die fehlende Abfrage auf NULL bei strchr() und strstr().
da alles problemlos lief, hab ich die Baudrate von 19200 auf 38400
erhöht.
Nun treten in einem unregelmäßigen abstand von 10 bis 60 sekunden Resets
auf.
da ich auch das MCUSR auslese, komme ich auf folgende Resetquellen:
10 Resets: davon 2x JTAG, 5x Watchdog.
das heißt ab und zu auch Sprung auf NULL ?!
WEnn ich wieder auf 19200 Baud wechsle kommt kein Reset.
In einem anderen Thread namens "UART verursacht Reset(?)" wurde ein 100
nF Kondensator gegen Masse an den RXD platziert und dann war Ruhe.
Ich habe keinen Kondensator zur Hand, kann mir auch nicht vorstellen,
dass solch ein InterruptPin so beschalten werden darf.
Was meint ihr dazu?
Danilo schrieb:
> ich dachte eher an Störsignale, die meine Rx-Leitung stören. und bei> einer geringeren Baudrate ist die anfälligkeit geringer bzw. weg :-/
Unwahrscheinlich.
Wahrscheinlicher: Bei geringen Baudraten kommt dein Programm noch mit.
Bei hohen Baudraten überläufst du den Prozessor (eigentlich dein
Programm) und das kommt dann mit der Datenflut nicht mehr klar.
Aber solange du den Code geheim hältst, ist das alles nur
Kristallkugellesen :-)
Warum machst du dir nicht einfach ein möglichst simples Testprogramm?
Zeichen von der UART lesen und gleich wieder zurücksenden. Dann lässt du
das bei hohen Baudraten laufen. Wenn dann immer noch Resets kommen und
dein Programm keinen Fehler aufweist, dann kann man Störungen ins Auge
fassen. Aber vorher ist ein Softwarefehler einfach viel
wahrscheinlicher.
Nachdem ich gerade ein ähnliches Problem hatte - sporadische Resets:
CKOPT Fuse setzen, bzw. im Datenblatt nachsehen wenn es diese Fuse nicht
gibt - am 644p kann ich "Full Swing Oscillator" auswählen, seitdem
crasht der avr nicht mehr - vorher mit "ext. crystal" immer wieder...
lG,Martin.