Ich habe das Problem, dass bei einer Übertragung die XOR Checksumme
immer wieder falsch berechnet wird. (ca. 50 bis 70% der Checksummen
werden falsch berechnet.)
Ich verwende einen ATtiny24.
Ich bin mir ziemlich sicher dass der Fehler bei der Berechnung passiert,
da wenn ich die Datenquelle abhänge, wird immer die gleiche, falsche
Checksumme überbittelt.
Dass Merkwürdige ist, dass alle Arrays Global sind, wodurch eigentlich
keine übermäßige Ram-Menge belegt werden sollte.
Aktuell sind ca.87% des Flash, ca.53% des SRams und 0% des EE-Proms
belegt.
Das Merkwürdige ist, dass solange ich beim Starten geladene
Standardwerte ohne Fehler verarbeitet werden.
Der Fehler tritt erst auf, sobald das erste mal Daten eingelesen werden.
(ADC-Werte und PWM-Signale)
Vor dem Berechnen der Checksumme werden mit cli alle Interrupts
abgedreht um mit die Daten nicht zu verändern.
Dann werden alle Daten in ein eigenes Übertragungsarray geschrieben.
Erst nach dem Kopieren der Daten werden die Interrupts wieder mit sei
aktiviert.
Kann mir bitte jemand ein paar generelle Tipps geben wie man solche
Fehler eingrenzen kann?
Wie kann man z.B. feststellen dass der Stack überläuft?
Bitte kommt mir jetzt nicht dass der Fehler in Programmzeile 42 liegt.
Ich brauche nur ein paar Tipps um das Problem selbst lösen zu können.
Bernhard schrieb:> Bitte kommt mir jetzt nicht dass der Fehler in Programmzeile 42 liegt.> Ich brauche nur ein paar Tipps um das Problem selbst lösen zu können.
Was erwartest du dann hier? Mann könnte dir jetzt alles mögliche raten,
was aber vielleicht in deinem Programm noch nicht mal verwendet wird.
Und da du noch nicht mal deine Programmiersprache explizit erwähnst, ist
das nicht mehr Stochern im Nebel, das ist einfach Zeitverschwendung.
Aber bitte:
einfache Eingabe -> checksumme berechnen lassen -> ausgeben -> von hand
prüfen
Bernhard schrieb:> Ich bin mir ziemlich sicher dass der Fehler bei der Berechnung passiert,
Darauf würde ich nicht wetten.
Seltsame Fehler, die völlig unerklärlich sind, haben meistens ihren
Ursprung in einem Fehler ganz wo anders.
Arrayüberläufe, für Strings zu klein dimensionierte Arrays sind da die
klassischen Kandidaten, allerdings sind das beileibe nicht alle
Möglichkeiten. Eigentlich kann man erst hinterher, wenn man den Fehler
gefunden hat, genau sagen wie sich dieser Fehler auswirkt, so dass man
die Symptome sieht, die man sieht. Genau das ist das fiese an der Sache.
Folgendes kann man zum Beispiel machen:
-Auf einem normalen PC kompilieren (vorausgesetzt, die Funktion ist in C
oder so geschrieben) und dort mal mit entsprechenden Beispielwerten
diverse Testläufe laufen lassen. Kommt auf der anderen Plattform immer
das richtige Ergebnis raus, kann es also nicht an der
Prüfsummen-Funktion an sich liegen, denn man hat dann ja gezeigt dass
sie korrekt implementiert ist.
-Debugger benutzen, Breakpoint setzen und die Funktion auf der
Zielplattform Schritt für Schritt durchsteppen, notfalls hier mit
Testarrays als Eingabe arbeiten weil man die Daten ja dann nicht in
Echtzeit (über irgendeine Schnittstelle) bekommt
-Laufzeit prüfen: Einen Digitalausgang des Mikrocontrollers auf 1 setzen
wenn die zu prüfende Funktion startet, und auf 0 setzen wenn sie endet.
So kann man mit einem Oszilloskop sehr schön sehen, wie groß die
Bearbeitungszeit für die Funktion ist - eventuell liegt sie nicht mehr
im passenden Rahmen, je nachdem welchen Zeitbedingungen die Anwendung
unterliegt.
-Generell prüfen, ob der Defekt nicht in der Hardware vorliegt: Mal den
Mikrocontroller gegen einen anderen austauschen und die exakt gleiche
Software aufspielen.
-Generell prüfen, ob einem nicht der (falsch eingestellte) Watchdog
dazwischenhaut - ein beliebter Fehler, wie ich aus eigener Erfahrung in
meinem ersten Projekt nach dem Studium erleben durfte :-)
Die Wahrscheinlichkeit, dass der Speicher an irgendeiner Stelle
korrumpiert wird (z.B. wie von Karl heinz Buchegger beschrieben), halte
ich für sehr viel größer als dass eine einfache Schleife über ein Array
von Bytes und deren XOR-Verknüpfung Probleme macht.
Floh schrieb:> Aber bitte:>> einfache Eingabe -> checksumme berechnen lassen -> ausgeben -> von hand>> prüfen
Dass war das 1. das ich gemacht habe um herauszufinden welche Seite der
Komunikation da die falsche Checksumme liefert.
Karl heinz Buchegger schrieb:> Bernhard schrieb:>>> Ich bin mir ziemlich sicher dass der Fehler bei der Berechnung passiert,>> Darauf würde ich nicht wetten.> Seltsame Fehler, die völlig unerklärlich sind, haben meistens ihren> Ursprung in einem Fehler ganz wo anders.>> Arrayüberläufe, für Strings zu klein dimensionierte Arrays sind da die> klassischen Kandidaten, allerdings sind das beileibe nicht alle> Möglichkeiten. Eigentlich kann man erst hinterher, wenn man den Fehler> gefunden hat, genau sagen wie sich dieser Fehler auswirkt, so dass man> die Symptome sieht, die man sieht. Genau das ist das fiese an der Sache.
Dass ist mir leider schon zu oft passiert.
Desswegen hatte ich gefragt welche Herangehensweise es gibt um den
Fehler eingrenzen zu können. Denn jeder geht anders an die Fehlersuche
heran. Und dadurch gibt es immer wieder nsätze an die man selbst nie im
Leben gedacht hätte.
Arrayüberläufe kann ich (fast) ausschließen.
Denn ich habe die Felder inzwischen um 5 einträge größer germacht als
nötug und habe auch einen Versuch mit hardcodet Zugriffen auf die Arrays
gemacht.
(Da schreit AVR Studio wenn man außerhalb des Arrays zugreift und man
greift nicht so schnell daneben.)
Es wird eigentlich ganz ohne Strings gearbeitet.
Ich verwende nur 8 und 16 Bit Arrays.
Was mir aufgefallen ist, ist dass AVR Studio hin und wieder ein 16 Bit
Array dur ein 8 Bit Array ersetzt.
Und dass obwohl ich ausdrücklich unsigned short geschrieben habe.
Mir ist dass nur aufgefallen weil die Ram-Adressen der einzelnen
Array-Werte beim Simulieren direkt aufeinander folgten.
Mark Brandis schrieb:> Folgendes kann man zum Beispiel machen:>> -Auf einem normalen PC kompilieren (vorausgesetzt, die Funktion ist in C> oder so geschrieben) und dort mal mit entsprechenden Beispielwerten> diverse Testläufe laufen lassen. Kommt auf der anderen Plattform immer> das richtige Ergebnis raus, kann es also nicht an der> Prüfsummen-Funktion an sich liegen, denn man hat dann ja gezeigt dass> sie korrekt implementiert ist.>> -Debugger benutzen, Breakpoint setzen und die Funktion auf der> Zielplattform Schritt für Schritt durchsteppen, notfalls hier mit> Testarrays als Eingabe arbeiten weil man die Daten ja dann nicht in> Echtzeit (über irgendeine Schnittstelle) bekommt>> -Laufzeit prüfen: Einen Digitalausgang des Mikrocontrollers auf 1 setzen> wenn die zu prüfende Funktion startet, und auf 0 setzen wenn sie endet.> So kann man mit einem Oszilloskop sehr schön sehen, wie groß die> Bearbeitungszeit für die Funktion ist - eventuell liegt sie nicht mehr> im passenden Rahmen, je nachdem welchen Zeitbedingungen die Anwendung> unterliegt.>> -Generell prüfen, ob der Defekt nicht in der Hardware vorliegt: Mal den> Mikrocontroller gegen einen anderen austauschen und die exakt gleiche> Software aufspielen.>> -Generell prüfen, ob einem nicht der (falsch eingestellte) Watchdog> dazwischenhaut - ein beliebter Fehler, wie ich aus eigener Erfahrung in> meinem ersten Projekt nach dem Studium erleben durfte :-)>> Die Wahrscheinlichkeit, dass der Speicher an irgendeiner Stelle> korrumpiert wird (z.B. wie von Karl heinz Buchegger beschrieben), halte> ich für sehr viel größer als dass eine einfache Schleife über ein Array> von Bytes und deren XOR-Verknüpfung Probleme macht.
Dass habe ich auch schon gemacht.
Dass Problem ist, dass mit Daten-Tabellen und Startwerten alles richtig
arbeitet.
Sowol auf dem PC als auch auf dem uC.
Nur sobald die richtigen Daten kommen, gibt's Fehler.
Ich vermute, dass da irgentetwas bei der Berechnung und dem Ermitteln
der Daten nicht ganz koscher ist.
Aber da ich alle Interrupts global abdrehe, dürfte eigentlich nichts
passieren.
Ich glaube ich werde mich dass Wochenende ausgibig mit dem Quellcode
beschäftigen müssen.
Bernhard schrieb:>> die Symptome sieht, die man sieht. Genau das ist das fiese an der Sache.> Dass ist mir leider schon zu oft passiert.> Desswegen hatte ich gefragt welche Herangehensweise es gibt um den> Fehler eingrenzen zu können.
Den Fehler gar nicht erst entstehen lassen :-)
Klingt jetzt neunmalklug, ist aber so.
In kleinen Abschnitten entwickeln. Jeden Abschnitt für sich auf Herz und
Nieren testen.
> Denn jeder geht anders an die Fehlersuche> heran.
Das ist gar nicht so sehr der springende Punkt.
Der springende Punkt ist, dass es unglaublich schwer ist, in ein
fünf-tausend Zeilen Code die eine zu finden, die für das momentan
sichtbare Symptom verantwortlich ist, wenn man nicht nachweisen kann,
dass es 4500 nicht sein können, weil man die ausreichend getestet hat.
> Und dadurch gibt es immer wieder nsätze an die man selbst nie im> Leben gedacht hätte.
Im Extremfall gehört auch ein Quentchen Glück mit dazu.
Debugger, die man auf Speicherzellen ansetzen kann und die sich melden,
wenn diese Zelle ihren Wert ändert (egal warum, also Überwachung indem
nach jeder Anweisung gecheckt wird, ob sich die Zelle verändert hat)
> Was mir aufgefallen ist, ist dass AVR Studio hin und wieder ein 16 Bit> Array dur ein 8 Bit Array ersetzt.
Ganz sicher nicht.
>> Die Wahrscheinlichkeit, dass der Speicher an irgendeiner Stelle>> korrumpiert wird (z.B. wie von Karl heinz Buchegger beschrieben), halte>> ich für sehr viel größer als dass eine einfache Schleife über ein Array>> von Bytes und deren XOR-Verknüpfung Probleme macht.>> Dass habe ich auch schon gemacht.>> Dass Problem ist, dass mit Daten-Tabellen und Startwerten alles richtig> arbeitet.> Sowol auf dem PC als auch auf dem uC.> Nur sobald die richtigen Daten kommen, gibt's Fehler.
Dann bleibt dir nichts mehr anderes übrig als:
Programm mit printf (bzw dem Äquivalent) spicken und alle auch nur
irgendwie interessant scheinenden
* Eingangswerte
* Zwischenwerte
* Ergebnisse
ausgeben (UART ist da besser als LCD, weil ein Termialprogramm
normalerweise eine längere Sitzung protokollieren kann)
Dieses Protokoll mitlesen, Werte auf Plausibilität prüfen und hoffen das
man dort den Bereich in etwa eingrenzen kann.
Du musst die Black Box öffnen. Momentan weißt du nur, dass hinten was
falsches raus kommt, wenn du vorne etwas reinsteckts (die Eingangswerte
hast du hoffentlich schon geprüft. Es kommt gar nicht so selten vor,
dass eine Funktion gar nicht die Werte vorgesetzt bekommt, die sich der
Entwickler vorstellt und mit denen er Debugging betreibt).
Also bleibt dir nichts anderes übrig als dir ein 'Fenster' in den µC zu
schaffen, durch welches du deinem µC möglichst gut bei der Arbeit
zusehen kannst.
Schau mal nach ob deine Arbeitsvariable zum berechnen der XOR Prüfsumme
jedes mal zu Anfang der Berechnung richtig initialisiert wird (0 oder
der Startwert deiner Wahl).
Oder ist einer der verwendeten Variablen mit static deklariert?
Verwendet der Compiler evtl. die Arbeitsvariable noch in einem anderen
Zusammenhang -> volatile ?
Ohne Quellcode kann ich auch nur raten...
> Ohne Quellcode kann ich auch nur raten...
Dito.
Was bei mir immer gerne passiert ;-) :
Bei einem Rotierbefehl RLC/RRC ist vorher das Carry nicht richtig
gesetzt....und je nach Aktivitaeten im Interrupt kann's auch mal falsch
sitzen ;-)
Generell stimuliert es die Motivation von Mitlesern mehr, eine sinnvolle
Antwort zu suchen, wenn der Fragesteller mehr Informationen gibt.
Angefangen vom tollen (?) Titel "Brauche Hilfe", "Tipps gesucht", "Was
ist der Fehler" bis zur Beschreibung der Randbedingungen:
Du schreibst nur, was nicht geht, und fragst was Du machen sollst,
schreibst aber nicht was Du ueberhaupt machen KANNST!
Keine Info ob ein SW-Simulator vorliegt, ob Du einen Emulator hast......
Im Simulator wuerde ich alle moeglichen Eingangswerte von 0 bis FFFF (?)
mal stimulieren und sehen, ob Werteabhaengig was passiert,
Wenn's das nicht ist, im Emulator mal die Uebertragungen freischalten,
aber als Werte immernoch die Defaultdaten benutzen um zu sehen, obdurch
die Kommunikation selber etwas passiert.....
vielleicht liegt der Fehler also wirklich in Zeile 42!
gruss
Michael
Ich weis dass ich den Titel etwas unglücklich gewählt habe.
Ach etwas Quellcode schadet normalerweise nicht.
Aber es ging mir um generelle Vorgehensweisen um den Fehler
einzugrenzen.
Karl heinz Buchegger schrieb:> Darauf würde ich nicht wetten.> Seltsame Fehler, die völlig unerklärlich sind, haben meistens ihren> Ursprung in einem Fehler ganz wo anders.
Genau so wahr's.
Ich bin alle Dateien Zeile für Zeile durchgegangen und habe genau
überlegt ob die Vorgehensweise stimmt.
Ich habbe alle möglichen Werte durchprobiert.
(Alle Kombinationen habe ich nicht durchprobiert, da es einfach zu lange
gedauert hätte. Ich habe aber eine Stunde lang den Zufallsgenerator
Kombinationen ausspucken lassen.)
Aber bis auf einige Optimierungsmöglichkeiten habe ich nichts gefunden.
@Michael
Bei diesem Fehler hätte es nichts gebracht den Quellcode des Projekts zu
schicken.
Der Fehler war übrigens in der Zeile 136.
Der Fehler war übrigens fieserweise nicht im eigentlichen Projekt,
sondern im Programm das die Ausgaben des Projekts auf Richtigkeit
überprüft.
Bernhard schrieb:> Der Fehler war übrigens fieserweise nicht im eigentlichen Projekt,> sondern im Programm das die Ausgaben des Projekts auf Richtigkeit> überprüft.
Wie gesagt -
Mark Brandis schrieb:> -Debugger benutzen, Breakpoint setzen und die Funktion auf der> Zielplattform Schritt für Schritt durchsteppen, notfalls hier mit> Testarrays als Eingabe arbeiten weil man die Daten ja dann nicht in> Echtzeit (über irgendeine Schnittstelle) bekommt
Für einen einzelnen Zyklus (oder wenige Zyklen) kann/soll man das
durchaus mal von Hand prüfen. Und dann sieht man ja, dass auf dem
Zielsystem das richtige Ergebnis herauskommt, und kann bei einer
Diskrepanz zur Prüfsoftware diese sogleich in Gewahrsam nehmen.
Mark Brandis schrieb:> Für einen einzelnen Zyklus (oder wenige Zyklen) kann/soll man das> durchaus mal von Hand prüfen. Und dann sieht man ja, dass auf dem> Zielsystem das richtige Ergebnis herauskommt, und kann bei einer> Diskrepanz zur Prüfsoftware diese sogleich in Gewahrsam nehmen.
Wie ich schon geschrieben habe, hat sich der Fehler bei manuellem Prüfen
nicht gezeigt.
Er ist nur beim normalen Programmablauf aufgetreten.
Bernhard schrieb:> Der Fehler war übrigens fieserweise nicht im eigentlichen Projekt,> sondern im Programm das die Ausgaben des Projekts auf Richtigkeit> überprüft.
Dann ist dieses Programmnichts wert, wenn es dir im Fehlerfall nicht
gestattet den (seiner Meinung) nach fehlerhaften Fall nachzuvollziehen.
Soweit nachzuvollziehen, dass du aus diesem Prüfprogramm die notwendigen
Input Daten erhältst, mit denen du die Berechnung kontrollieren kannst.
Michael Roek-ramirez schrieb:> Bei einem Rotierbefehl RLC/RRC ist vorher das Carry nicht richtig> gesetzt....und je nach Aktivitaeten im Interrupt kann's auch mal falsch> sitzen ;-)
Dann ist aber der Interrupthandler auch noch defekt. Wenn der Handler
das flag verändert, muss er dafür sorgen, dass es wieder zurückgesetzt
wird.
Oder was passiert hier:
CLC
<-- Interrupt
RLC
RRC
...
Karl heinz Buchegger schrieb:> Dann ist dieses Programmnichts wert, wenn es dir im Fehlerfall nicht> gestattet den (seiner Meinung) nach fehlerhaften Fall nachzuvollziehen.> Soweit nachzuvollziehen, dass du aus diesem Prüfprogramm die notwendigen> Input Daten erhältst, mit denen du die Berechnung kontrollieren kannst.
Jepp
Der Fehler war da nicht in der Fehleranalyse selbst, sondern in der
Datenerfassung.
Und wenn die erfassten Daten fehlerhaft sind, kann man die Daten noch so
oft händisch nachrechnen und auf pausibilität überprüfen.
Dass Ergebnis stimmt immer mit dem Analyseprogramm überein.
(Außer man verrechnet sich.)
Desswegen habe ich ja auch so lange an der falschen Stelle nach dem
Fehler gesucht.
Aber jetzt Schwamm drüber über die ganze Sache.