Forum: Mikrocontroller und Digitale Elektronik Reset-Problem: Uart dran schuld?


von Danilo (Gast)


Lesenswert?

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

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

Hi

>Ich hoffe es findet sich ein pfifiger Helfer.

Da das hier ein Hellseher-Forum ist, bestimmt.

MfG Spess

von Stefan E. (sternst)


Lesenswert?

Danilo schrieb:

> Komisch, dass ich weder JTAG nutze, noch den WATCHDOG aktiviert habe.

Sicher? Fuses kontrolliert?

von Uwe .. (uwegw)


Lesenswert?

Prüf mal die WDTON-Fuse, und füg nen
ISR(BADISR_vect)
{
    // Hier irgendwie ne Meldung ausgeben
}
im Programm ein.

von Anja (Gast)


Lesenswert?

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.

von Danilo (Gast)


Lesenswert?

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

von Danilo (Gast)


Lesenswert?

FUSES:
[ ] Watchdog Timer always on (WDTON = 0)
[ ] JTAG Inteface Enabled (JTAGEN = 0)
[X] SPI enable (SPIEN = 1)
[X] Brownout detection disble (BODLEVEL = 111)

von Danilo (Gast)


Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

High Freq. Quarz als Taktgeber dran aber CKOPT nicht gesetzt?

von Anja (Gast)


Lesenswert?

Was hindert dich denn daran mal kurz einen Kondensator an den Reset-Pin 
zu löten?

von Stefan B. (Gast)


Lesenswert?

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

von Danilo (Gast)


Lesenswert?

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.

von Danilo (Gast)


Lesenswert?

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?

von Danilo (Gast)


Lesenswert?

Welche Uart-Bibliothek verwendet ihr?

ich habe die von Peter Fleury.

von Danilo (Gast)


Lesenswert?

manchmal werden auch für einen RESET 2 Resetquellen angezeigt.
Darf das sein?
WEnn nicht, dann wars vielleicht weder der eine noch der andere...

von Danilo (Gast)


Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

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.

von Stefan B. (Gast)


Lesenswert?

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.

von Danilo (Gast)


Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

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.

von Danilo (Gast)


Lesenswert?

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.
1
strcpy(SearchCmd,"AT");

Datentyp: char  SearchCmd[8];

Ideen?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Stefan B. (Gast)


Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Stefan B. (Gast)


Lesenswert?

Ich bin einfach zu alt und mit anderen Spielzeugen aufgewachsen ;)

von Danilo (Gast)


Lesenswert?

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
void Diag_SendCmd(unsigned char pCmd)
2
{
3
  char UartBuffer[10];
4
  strcpy(UartBuffer,"ATRV");
5
  uart_puts(UartBuffer);
6
}
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);

von Karl H. (kbuchegg)


Lesenswert?

Danilo schrieb:

> meine Senderoutine:
>
1
> void Diag_SendCmd(unsigned char pCmd)
2
> {
3
>   char UartBuffer[10];
4
>   strcpy(UartBuffer,"ATRV");
5
>   uart_puts(UartBuffer);
6
> }
7
>
> 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.

von Simon K. (simon) Benutzerseite


Lesenswert?

Einfach mal das ganze Projekt anhängen. uart_puts könnte auch noch einen 
Fehler enthalten.

von Stefan B. (Gast)


Lesenswert?

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

von Danilo (Gast)


Lesenswert?

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

von Danilo (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

Danilo schrieb:

> Was meint ihr dazu?

Das du immer noch Fehler im Programm hast.

von Danilo (Gast)


Lesenswert?

ich dachte eher an Störsignale, die meine Rx-Leitung stören. und bei 
einer geringeren Baudrate ist die anfälligkeit geringer bzw. weg :-/

von Karl H. (kbuchegg)


Lesenswert?

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.

von MartinS. (Gast)


Lesenswert?

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.

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.