mikrocontroller.net

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


Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Ich hoffe es findet sich ein pfifiger Helfer.

Da das hier ein Hellseher-Forum ist, bestimmt.

MfG Spess

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danilo schrieb:

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

Sicher? Fuses kontrolliert?

Autor: Uwe ... (uwegw)
Datum:

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

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Danilo (Gast)
Datum:

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

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: Anja (Gast)
Datum:

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

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welche Uart-Bibliothek verwendet ihr?

ich habe die von Peter Fleury.

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
strcpy(SearchCmd,"AT");

Datentyp: char  SearchCmd[8];

Ideen?

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

Bewertung
0 lesenswert
nicht lesenswert
Danilo schrieb:

> wenn ich allerdings folgende zeile drin lass, gibt eben diese
> sporadischen resets.
>
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.

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin einfach zu alt und mit anderen Spielzeugen aufgewachsen ;)

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
void Diag_SendCmd(unsigned char pCmd)
{
  char UartBuffer[10];
  strcpy(UartBuffer,"ATRV");
  uart_puts(UartBuffer);
}
char UartBuffer[10] ist eine lokale Variable in der Sendefunktion.

hier meine main():
  do
  {
    Diag_SendCmd(SEND_SIGNAL);
    WaitInMs(50);
  }
  while(1);

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

Bewertung
0 lesenswert
nicht lesenswert
Danilo schrieb:

> meine Senderoutine:
>
> void Diag_SendCmd(unsigned char pCmd)
> {
>   char UartBuffer[10];
>   strcpy(UartBuffer,"ATRV");
>   uart_puts(UartBuffer);
> }
> 
> char UartBuffer[10] ist eine lokale Variable in der Sendefunktion.
>
> hier meine main():
>
>   do
>   {
>     Diag_SendCmd(SEND_SIGNAL);
>     WaitInMs(50);
>   }
>   while(1);
> 

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.

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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__pfle...

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

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

Bewertung
0 lesenswert
nicht lesenswert
Danilo schrieb:

> Was meint ihr dazu?

Das du immer noch Fehler im Programm hast.

Autor: Danilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-/

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

Bewertung
0 lesenswert
nicht 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.

Autor: MartinS. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

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.