Hallo Leute,
ich bastel momentan an meinem Tricopter Regler mit dem µc XMega128A1.
Entwickelt wird unter Ubuntu Linux 10.04 (32bit) mit dem Eclipse Plugin.
Die Treiber für die Sensoren laufen mittlerweile schon, aber leider nur
"einzeln". Beide Sensoren hängen über TWI an PORTE und PORTF (also TWIE
und TWIF). Lasse ich nur den Beschleunigungssensor auslesen kappts. Wenn
ich nur das Gyro auslese klappts auch. Werden beide Sensoren ausgelesen
(alles interruptbasiert) bleibt der µC einfach stehen. Und das in
Codeblöcken, in denen eigentlich nichts großes passiert, ausser ein paar
Berechnungen. Folgendes konnte ich schon in Erfahrung bringen, bzw.
ausschliessen:
* Main wird nicht mehr durchlaufen
* While Schleifen werden überwacht
* In einem Interrupt hängt er auch nicht fest
* Main wird nicht verlassen
So langsam gehen mir wirklich die Ideen aus und ich wäre über einen Tipp
wirklich sehr sehr dankbar, wo ich noch suchen kann bzw. was die Ursache
sein könnte ....
Grüße,
Michael
Hallo gascht, Peterp,
:) ich hab schon verstanden, aber Projekt ist wirklich nicht klein! Mir
gehts mehr darum, ob jemand sowas schon mal hatte und evtl. eine Lösung
bzw. eine Strategie hat um den Fehler zu lokalisieren. Ich kann mir
nicht vorstelle, dass sich jemand durch den Sourcecode wühlen will (rund
25 Dateien, ich hab ihn trotzdem mal angehängt ...)
Grüße,
Michael
Hallo ich nochmal,
jetzt wirds spannend: Hab grad mal unter Windows gebootet und die
aktuellen Sourcen ausgecheckt (svn) und unter Win kompiliert und
geflasht ... und es läuft!?
Was ich festgestellt habe, ist eine unterschiedliche Kompilerversion:
Windows: avr-gcc 4.3.3 (WINAVR 20100110)
Linux: avr-gcc 4.3.4
bitte jetzt keine Ratschläge ala "na dann prog halt unter Windows" ....
Grüße,
Michael
Also. Debuggen, dh den Fehler finden ist Teil der Entwicklung, und
sollte schon zu Begin eingeplant werden. Dh die Leiterplatte sollte die
passenden Testpunkte enthalten. Der Code sollte hinreichend modular
sein, um die Funktionalitaet einer jeden Komponente pruefen zu koennen.
Dann beginnt man mit dem Laufenlaassen einer jeden Komponente. Ich
bevorzuge das UART, denn damit kann man zur Laufzeit Variablen
anschauen. Ich hatt auch schon Designs, da hatt ich einen 8x 8 bit DAC
auf einem gesteckten Adapter, damit konnte man dann zum Debuggen ein
paar schnelle Variablen aufm Scope anschauen.
Hallo hacky,
danke für Deine Antwort. Genau was Du beschreibst habe ich heute den
ganzen Tag getrieben. Der Aufbau ist noch verkabelt und noch nicht auf
einer Platine. Der Proz ist auf einem Headerboard von Alvidi und die
Sensoren sind per Stiftleisten und mit angelöteten Kabeln verbunden.
Stromversorgung und TWI Pegel sind mit Oszi und LA geprüft und da passt
auch alles! Komischerweise läuft der Code ja, wenn unter Windows
kompiliert ohne Probleme, was ich vorhin rausgefunden habe. Unter Linux
treten seltsame Dinge auf, wie dass der Proz an manchen Stellen einfach
eben stehen bleibt. Und das leider auch nicht reproduzierbar, sondern
immer an einer anderen Stelle. Sogar innerhalb von Funktionen, wo
eigentlich nichts ist, wo er stehen bleiben könnte. Ich hab sogar
zwischen den Berechnungen in der Datei fc.c entsprechende Debug Ausgaben
produzieren lassen und plötzlich geht nix mehr. Die Interrupts haben
ALLE auch eine Debug Ausgabe, d.h. ich würde es mitbekommen, wenn da
irgendwas schief läuft ....
Speicher bzw. Stack kanns eigentlich auch nicht sein. Das schreibt der
Kompiler:
AVR Memory Usage
----------------
Device: atxmega128a1
Program: 12752 bytes (9.2% Full)
(.text + .data + .bootloader)
Data: 137 bytes (1.7% Full)
(.data + .bss + .noinit)
Build succeeded with 0 Warnings...
Wirklich sehr suspekt. Ideen ??
Grüße,
Michael
-Vergleich mal die Hexfiles produziert unter Windows und von unter
Linux. Sie sollten eigentlich identisch sein.
Falls unterschiede ausserhalb des Codes zu finden sind :
-Die Pfade zu den Libraries kontrollieren.
-Kann es sein, dass ein nicht expizit initialisierter Pin beim Einen auf
Input steht, beim anderen auf Output ?
Hallo Hacky,
ich hab die Hexfiles mal verglichen. Die Dateigröße ist identisch, aber
der offenbart einige Unterschiede (ist nur der Anfang ...):
diff Linux/Flightcontrol.hex Windows/Flightcontrol.hex
11,12c11,12
< :1000A0000C94390A0C94390A0C94390A0C94E41013
< :1000B0000C94390A0C94390A0C940F130C94390AD5
---
> :1000A0000C94390A0C94390A0C94390A0C947A0C81> :1000B0000C94390A0C94390A0C94A50E0C94390A44
27,28c27,28
< :1001A0000C94390A0C94390A0C94390A0C947B1576
< :1001B0000C94B9130C94390A0C94390A0C94390A2A
---
> :1001A0000C94390A0C94390A0C94390A0C941111E4> :1001B0000C944F0F0C94390A0C94390A0C94390A98
Lib Pfade sind bei beiden OS in Ordnung und die Dateien sind definitiv
identisch (beide aus dem gleichen SVN ausgecheckt).
Wenn ich mich recht erinnere, stehen bei den XMegas nicht initialisierte
IOs immer auf Eingang, wenn nicht explizit als Ausgang definiert. Da
beide Sensoren ja an den TWIs hängen, wird die "DIR" Konfiguration ja
vom TWI Modul überschrieben ... Das komische ist ja, dass beide
Sensortreiber wunderbar laufen, wenn jeweils nur einer aktiviert ist.
Sind beide aktiv, also sollen Daten von beiden Sensoren abgefragt
werden, so tritt der Effekt mit dem "Freeze" auf, aber eben nur, wenn
unter Linux kompiliert wurde. Echt strange ....
Grüße,
Michael
Hmm. Es müsste, denke ich, geklärt werden ob der Unterschied in Deinem
Code liegt oder innerhalb einer der Libraries.
Vergleich doch mal die Assemblerlistings. Da siehst Du die Adresse und
ob der fragliche Code Dein eigener ist oder nicht.
Du schreibst, das Du identlsche Libraries verwendet hast, aber mit zwei
verschiedenen Versionen des Compilers.
Theoretisch sollte also Dein Code und der Code der Libraries im Listing
bzw. Hex-File identisch sein.
Dennoch gibt es einen Unterschied. Jetzt ist die Frage was genau der
Unterschied ist.
Das wird evtl. nicht unmittelbar zur Problemlösung führen, aber unter
Umständen einen Ansatzpunkt liefern.
Es wäre auch interessant mal die Beschreibung der Releases anzuschauen,
ob sich da ein Anhaltspunkt ergibt bzw. ob und wie die Neuerung bei dem
späteren Release mit dem Unterschied im Listingfile korreliert.
Alles ein wenig mühsam und nicht einfach aber das ist der Weg, denke
ich.
Hallo,
ich hatte mal das Problem, dass Objektdateien nicht neu gebaut wurden
und deshalb alte Objektdateien gelinkt wurden. Lösche diese mal manuell
und baue das Projekt neu. Denn dies ist vermutlich passiert, beim
Auschecken unter Windows...
@Huch: Der Code stammt von mir und liegt auch in einem eigenen SVN
Repos. Die Lib-Versionen sollten gleich sein, aber prüfe ich gleich noch
mal und schau' ob da Unterschiede sind. Wie genau komme ich denn an die
Assembler Listings?? Unter AVR Studio kannte ich, dass man beim
Simulieren sich den ASM Code anzeigen lassen kann ... weißt Du wie das
unter Linux geht??
@Wat: Beide OS Varianten wurden frisch kompiliert, also vorher
"gecleaned" und dann gebaut ...
Danke für die Anregungen!! Ich halte Euch auf dem Laufenden!
Grüße,
Michael
>@Huch: Der Code stammt von mir und liegt auch in einem eigenen SVN
Repos.
Mir ist gerade nicht klar, was Du damit sagen willst.
Ich wollte darauf hinaus, dass es Code gibt den Du (oder wer auch immer)
geschrieben hast und solchen der aus den Libraries stammt.
Wesentlich daran, ist folgendes: Liegt der Unterschied im resultierenden
Hex-File in dem Bereich des Library-Codes so bedeutet das etwas anderes
als wenn der Unterschied in "Deinem" Code liegt.
Was das Listing File mit gcc unter Linux betrifft muss man da eine
Option hinzufügen, denke ich. Bin gerade zu faul selbst nachzusehen.
Mach Du das bitte selbst.
Ah, verstehe. Ich hab grad nochmal die Libversionen gecheckt und die
sind identisch (Linux sagt: avr-lib 1:1.6.7-1ubuntu2, WINAVR V.20100110
sagt im WINAVR-User-Manual.txt unter Punkt 2.1 Manifest: 3. avr-libc
1.6.7cvs). Fragt sich nur, ob gleiche Version = gleicher Code !?
Der Quellcode ist definitiv identisch .... hab die Dateien mal auf nen
Stick gezogen und gedifft. Kein Unterschied.
Ich installier grad das Linux in einer VM um nicht dauern umbooten zu
müssen. Dann checke ich mal die Listing Unterschiede. Wusste nicht, dass
der gcc, respektive der avr-gcc direkt so ein Listing erzeugen kann...
DANKE!
Grüße,
Michael
>Fragt sich nur, ob gleiche Version = gleicher Code !?>Der Quellcode ist definitiv identisch .... hab die Dateien mal auf nen>Stick gezogen und gedifft. Kein Unterschied.
Also der Quellcode der Libraries ist identisch? Das wäre schon mal eine
Information.
Wo wir schon über Optionen reden könntest Du auch mal die Optionen beim
Bau mit der alten Compilerversion mit denen beim Bau mit der neuen
Version vergleichen.
Was ich geprüft habe ist der Quellcode von meinem Code, nicht den der
Libraries. Die liegen ja als .a vor und sind schon kompiliert ;-) Ausser
ich zieh mir die sourcen ....
ich teste jetzt mal mit den Kompileroptionen ... -g -Wa,-adhlns=file.lst
klingt schon vielversprechend ...
>Was ich geprüft habe ist der Quellcode von meinem Code, nicht den der
Libraries.
Ach so. Ich habe in den Sätzen:
>Ich hab grad nochmal die Libversionen gecheckt und die>sind identisch (Linux sagt: avr-lib 1:1.6.7-1ubuntu2, WINAVR V.20100110>sagt im WINAVR-User-Manual.txt unter Punkt 2.1 Manifest: 3. avr-libc>1.6.7cvs). Fragt sich nur, ob gleiche Version = gleicher Code !?>Der Quellcode ist definitiv identisch .... hab die Dateien mal auf nen>Stick gezogen und gedifft. Kein Unterschied.
die Frage "ob gleiche Version = gleicher Code" als rethorisch
verstanden, denn in dem nachfolgenden "Der Quellcode ist definitiv
identisch..." wurde das Satzsubjekt nicht vollständig neu spezifiziert,
so das sich "Quellcode" auf den Quellcode der Library zu beziehen
schien.
Ich denke den Vergleich der Quellcodes der Library brauchst Du jetzt
nicht zu durchzuführen. Das wesentliche ist erstmal, anhand des
Listing-Files erstmal festzustellen wo der Unterschied liegt und zu
welcher Quellcode-Zeile der Unterschied gehört.
Dann kann man weiter sehen.
@alibaba: Vielen Dank! Habs auch schon gefunden ;-)
Anbei die beiden Listings .... ich hab die beiden auch mal gedifft und
es gibt einige Unterschiede (mit Notepad++ über
Erweiterungen->Compare->Compare).
Ich verstehe nur leider noch nicht ganz wonach ich suchen soll ...?? Und
asm verstehe ich auch nur in den Grundzügen ... ich hoffe Ihr könnt
daraus mehr lesen als ich!!
Grüße,
Michael
PS: In dem Linux listing sind anscheinend keine Debug Informationen drin
... Ich versuch da mal welche reinzubekommen ....
So der Vollständigkeit anbei noch das Linux Listing mit debug
Informationen.
@hacky: Die Hexfiles unterscheiden sich ja schon in der ersten Zeile!
Könntest Du bitte kurz ausführen, wonach ich suchen muss? Auch die
Speicheraufteilung scheint zwischen Win und Lin unterschiedlich zu sein
... Am Anfang stehen die Strings, die im Flash abgelegt worden sind. Da
ist z.B. die Reihenfolge schon gänzlich anders ....
Grüße,
Michael
@ Michael K.
Kriegst Du das erste Listing (Linux) auch so hin, dass die
C-Source-Zeilen mit in dem File stehen. Das wäre viel einfacher.
>Ich verstehe nur leider noch nicht ganz wonach ich suchen soll ...??
Das kann ich im voraus leider auch nicht genau sagen. Man sollte mal die
C-Zeilen angucken bei denen im Assembler-Code ein Unterschied besteht.
Eine Vermutung wäre, das Du ein C-Statement etwas unglücklich formuliert
hast. Es funktioniert zwar aber vielleicht aber nicht wenn ein Bug
beseitigt wurde. Da gibt es viele Möglichkeiten C-Befehle zwar
syntaktisch korrekt zu formulieren aber so, das es nur unter bestimmten
Bedingungen geht, die im C-Standard als "implementierungsabhängig"
gekennzeichnet sind.
Ist es möglich, dass es zu einem Stack Overflow kommt?
Es könnte z.B. sein, dass unter Windows in den Compileroptionen
Optimierungen an sind, die den Code beschleunigen, so dass es nicht zum
Stack Overflow kommt.
Ein Debugger hast du nicht, wenn ich das geschriebene richtig
interpretiere?
Hallo..
Sagt mal, den einfachsten aller Fälle, einen Programmierfehler, hat hier
noch keiner angenommen? (Die Frage, warum er unter Win geht und unter
Lin
nicht, wäre mir zunächst egal, ich würde den Fehler suchen. Bestimmt
nicht
in den Libs, eher in meinem Code...)
Stichworte wie "atomar" sollten da hellhörig machen..
Gruss, T.
PS: If stack full, erase stack.
>Die Dateigröße ist identisch, aber der offenbart einige Unterschiede
Also, ich habe mir "einige" Unterschiede anders vorgestellt. So drei bis
20-40. Aber das hier ist doch eine etwas andere Dimension.
Deine sprachlichen Äusserungen darf man wohl nicht ganz ernst nehmen.
Ist nicht böse gemeint, aber es ist natürlich wichtig zu wissen wie
präzise Du Dich ausdrückst.
Ich habe ehrlich gesagt keine Lust die Unterschiede selbst zu suchen und
würde ansgesichts der Menge doch erstmal versuchen den Fehler mittels
Debugging einzugrenzen.
Du hast nun folgende Möglichkeiten, denke ich:
1. Suche die Unterschiede selbst heraus und präsentiert sie hier. Es
geht um die C-Codezeilen, der zugehörigen Assemblerzeilen die
unterschiedlich sind. Jedoch sind reine Unterschiede in den Sprungzielen
dabei irrelevant.
- Ganz ehrlich, habe ich das Gefühl, das Du damit überfordert sein
könntest.
2. Versuche den Fehler auf der Ebene des C-Codes zu finden.
Das scheint mir eher erfolgversprechend.
--------------------------------------
Solltest Du Alternative 2. wählen, dann erkläre doch mal folgendes aus
Deinem ersten Posting. Ich kann damit wenig anfangen.
>* Main wird nicht mehr durchlaufen
Wie stellst Du das fest? Was meinst Du damit?
>* While Schleifen werden überwacht
Wie stellst Du das fest und was heisst hier "überwacht"? Von wem, mit
welchen Mitteln, und welchen Ergebnissen?
>* In einem Interrupt hängt er auch nicht fest
Wie stellst Du das fest? Das ist ein Widerspruch zum ersten Punkt: Wenn
der uC main nicht ausführt und keinen Interrupt, was macht er dann?
>* Main wird nicht verlassen
Das sollte so sein bei einem uC-Programm, was erscheint Dir daran
bemerkenswert?
-----------------------------------------------------------------
Ich hoffe Du hast Verständnis dafür, dass ich Dich auf die besondere
Bedeutung einer möglichst korrekten Beschreibung der Fakten hinweise.
Falls Du Anfänger bist, haben wir durchaus Verständnis für unkorrekte
Ausdrucksweise.
Ein Beispiel ist: " bleibt der µC einfach stehen."
Der uC bleibt nur dann stehen, wenn der Takt wegbleibt oder er abbrennt
oder jemand drauftritt. Sonst läuft er immer weiter. Es ist ihm
unmöglich "stehenbleiben". Das geht garnicht. Was also meinst Du damit?
In diesem Fall wäre zusätzlich die Angabe nützlich, auf welche Weise und
anhand welcher Kriterien Du denn feststellst, das er "stehenbleibst".
Daraus können wir uns dann wieder in passende Begriffe 'übersetzen' was
Du damit meinst. Aus den Reaktionen kannst Du auch lernen wie man sich
in dem Thema korrekt ausdrückt. Evtl. stellen wir aber auch fest, das
Deine Kriterien oder die Verfahren verbessert werden können. Auch
interessant.
Hallo zusammen,
@Benni L.:
* Stackoverflow: keine Ahnung ... wie könnte ich das feststellen?
* Debugger ist vorhanden (Atmel JTAG MKII). Als die Software unter Linux
immer "stehen blieb" (dazu später mehr) wollte ich unter Windows
debuggen (unter Linux geht debugging (noch) nicht). Da hab ich dann eben
festgestellt, dass der, unter Win kompilierte Code druchläuft.
* Compileroptionen sind identisch und überprüft
Was ich als nächstes machen werde, ist den Code von Linux unter Windows
flashen und vor allem debuggen ... vllt. sieht man dann wo er "hängen
bleibt".
@T.O.:
* Programmierfehler schließe ich natürlich nicht aus! Ich hab schon
wirklich "megabyteweise" debug Informationen über die USART rausgelassen
und zudem mit dem LA Pinwakler gecheckt.
@Huch:
> Also, ich habe mir "einige" Unterschiede anders vorgestellt. So drei bis> 20-40. Aber das hier ist doch eine etwas andere Dimension.
* stimmt ...leider!
> Deine sprachlichen Äusserungen darf man wohl nicht ganz ernst nehmen.> Ist nicht böse gemeint, aber es ist natürlich wichtig zu wissen wie> präzise Du Dich ausdrückst.
* Ich versuche daran zu arbeiten!
> Ich habe ehrlich gesagt keine Lust die Unterschiede selbst zu suchen und> würde ansgesichts der Menge doch erstmal versuchen den Fehler mittels> Debugging einzugrenzen.
Das erwarte ich auch gar nicht!! Ich will den Fehler schon selber
finden! Bzgl. debugging: s.o.
> Du hast nun folgende Möglichkeiten, denke ich:>> 1. Suche die Unterschiede selbst heraus und präsentiert sie hier. Es> geht um die C-Codezeilen, der zugehörigen Assemblerzeilen die> unterschiedlich sind. Jedoch sind reine Unterschiede in den Sprungzielen> dabei irrelevant.> - Ganz ehrlich, habe ich das Gefühl, das Du damit überfordert sein> könntest.
* Überfordert bin ich noch nicht ... ist halt viel Arbeit da
Unterschiede zu finden und vor allem dauert es eifach ...
> 2. Versuche den Fehler auf der Ebene des C-Codes zu finden.> Das scheint mir eher erfolgversprechend.
Bin dabei.
> -------------------------------------->> Solltest Du Alternative 2. wählen, dann erkläre doch mal folgendes aus> Deinem ersten Posting. Ich kann damit wenig anfangen.>>>* Main wird nicht mehr durchlaufen> Wie stellst Du das fest? Was meinst Du damit?
Ich hab in der main nen USART output drin gehabt, ala Debug_Str (".");
Wenn der µC "stehen" bleibt, dann kam über UART kein "." mehr. Meine
Vermutung war dann, dass der µC in entweder ein Schleife hängt, oder ein
Interrupt permanent auslöst wird und er darin "festhängt".
>>* While Schleifen werden überwacht> Wie stellst Du das fest und was heisst hier "überwacht"? Von wem, mit> welchen Mitteln, und welchen Ergebnissen?
Alle while - Schleifen haben eine Debug Ausgabe drin (gehabt). In keiner
der Schleifen hing der µC länger als erwartet.
>>* In einem Interrupt hängt er auch nicht fest> Wie stellst Du das fest? Das ist ein Widerspruch zum ersten Punkt: Wenn> der uC main nicht ausführt und keinen Interrupt, was macht er dann?
Debug - Ausgaben am Anfang und am Ende der ISR.
>>* Main wird nicht verlassen> Das sollte so sein bei einem uC-Programm, was erscheint Dir daran> bemerkenswert?
Das ist eine der Möglichkeiten, wie der µC "stehen" bleiben kann ;-).
Macht man im main ein return, ist Schluss mit "arbeiten" ....
> ----------------------------------------------------------------->> Ich hoffe Du hast Verständnis dafür, dass ich Dich auf die besondere> Bedeutung einer möglichst korrekten Beschreibung der Fakten hinweise.> Falls Du Anfänger bist, haben wir durchaus Verständnis für unkorrekte> Ausdrucksweise.
Anfänger bin ich nicht mehr, ich hoffe das sieht man auch ein wenig am
Code, aber Profi bin ich auch nicht. Ich programmiere hauptberuflich,
aber eben nur auf PCs unter Linux. Wenn ich mich unkorrekt ausgedrückt
habe, dann möchte ich mich dafür entschuldigen! Ich arbeite dran!
> Ein Beispiel ist: " bleibt der µC einfach stehen."> Der uC bleibt nur dann stehen, wenn der Takt wegbleibt oder er abbrennt> oder jemand drauftritt. Sonst läuft er immer weiter. Es ist ihm> unmöglich "stehenbleiben". Das geht garnicht. Was also meinst Du damit?
Es kommen keine Debug Ausgaben über UART mehr. PC seitige Probleme kann
ich dabei ausschließen. Zudem zeigt der LA keine Aktivität mehr an
"Toggelpins" und die angeschlossene LED (die blinken sollte) bleibt
entweder statisch an oder aus.
> In diesem Fall wäre zusätzlich die Angabe nützlich, auf welche Weise und> anhand welcher Kriterien Du denn feststellst, das er "stehenbleibst".> Daraus können wir uns dann wieder in passende Begriffe 'übersetzen' was> Du damit meinst. Aus den Reaktionen kannst Du auch lernen wie man sich> in dem Thema korrekt ausdrückt. Evtl. stellen wir aber auch fest, das> Deine Kriterien oder die Verfahren verbessert werden können. Auch> interessant.
s.o.
Grüße,
Michael
>* Ich versuche daran zu arbeiten!> Anfänger bin ich nicht mehr, ich hoffe das sieht man auch ein wenig am> Code, aber Profi bin ich auch nicht. Ich programmiere hauptberuflich,> aber eben nur auf PCs unter Linux.
Gut. Ich werde das berücksichtigen. Aber vorerst werde ich Deine
Antworten weiter hinterfragen.
>Wenn ich mich unkorrekt ausgedrückt habe, dann möchte ich mich dafür >entschuldigen!
Das ist wirklich und absolut unnötig. Ich mache Dir keine Vorwürfe,
erwarte keine Zerknirschung, kein Bedauern, keine Unterwerfung oder
Wiedergutmachung. Wenn ich darüber schreibe, dann allein deswegen weil
diese sprachlichen "Eigenheiten" den Analyseprozess entstellend
beeinflussen.
Ich will trotzdem versuchen Dir mit dem was ich weiss zu helfen. Gehe
Dir mit dem sprachlichen Zeug wahrscheinlich ein paarmal auf die Nerven.
Das mit dem Debuggen der Windows-Variante unter Linux scheint mir ein
guter Ansatz zu sein.
Denke daran, das das ausbleiben der Debug-Ausgabe kein "Anhalten"
bedeutet sondern nur, dass der durchlaufene Code keine Ausgaben erzeugt.
Genauso der Zustand in dem keine Änderungen an der LED oder den Ports
mehr erfolgen.
Eine weiter Möglichkeit wäre die Debug-Ausgaben weiter zu
differenzieren. Gib eine Kombination aus einem Buchstaben für die
Funktion und einer Zahl für einen Schritt in der Funktion aus. (Nicht zu
fein gliedern).
Was mir auffällt, ist das Du im Text von Debug-Ausgaben innerhalb des
Interrupts sprichst. An sich ist das absolut tödlich, wenn etwa Ausgaben
selbst auch über Ints laufen. Wenn Du das nicht komplett aus den ISRs
entfernen willst dann kommentiere es mal aus. Eine durchaus reale
Möglichkeit, das hier was knackt.
Ehrlich gesagt halte ich die Möglichkeit des Stacküberlaufs für
wahrscheinlich. Um das zu erkennen kannst Du den Speicher mal mit einem
Muster vollschreiben und hinterher sehen ob das Muster noch da ist.
Gab hier gerade vor ein paar Tagen eine Diskussion dazu. Suche einfach
danach.
Falls es tatsächlich am Stacküberlauf liegt wirst Du mit den bisherigen
Debugausgaben nur bedingt weiterkommen, weil der Code an sich korrekt
ist aber zu viele Verschachtelungsebenen auftreten. Du kannst evtl. eine
Debug-Ausgabe basteln die die die Aufrufebenen zurückgibt, bzw. den
Stackpointer.
Du könntest auch mal im Code gucken ob irgendwo absichtlich oder
unabsichtlich Rekursionen auftreten und ob die Abbruchbedingungen
wirklich mit true bewertet werden.
Läuft der Code im Simulator? Kannst Du den Fehler im Simulator auch
provozieren?
Eine gute Möglichkeit ist auch, einen Lint über Deinen Code laufen zu
lassen. Es gibt da einige für Linux.
Falls noch nicht geschehen, lasse Dir alle Warnings ausgeben und
beseitige alle (zeige die die Du meinst nicht beseitigen zu können).
So, das sind einige Vorschläge. Über die Reihenfolge könnte man noch
gesondert reden, aber da Du schreibst das Du Programmiererfahrung hast,
kannst Du das wahrscheinlich selbst gut entscheiden.
Huch schrieb:>>* Ich versuche daran zu arbeiten!>> Anfänger bin ich nicht mehr, ich hoffe das sieht man auch ein wenig am>> Code, aber Profi bin ich auch nicht. Ich programmiere hauptberuflich,>> aber eben nur auf PCs unter Linux.>> Gut. Ich werde das berücksichtigen. Aber vorerst werde ich Deine> Antworten weiter hinterfragen.
Gerne!
>>>Wenn ich mich unkorrekt ausgedrückt habe, dann möchte ich mich dafür>>entschuldigen!> Das ist wirklich und absolut unnötig. Ich mache Dir keine Vorwürfe,> erwarte keine Zerknirschung, kein Bedauern, keine Unterwerfung oder> Wiedergutmachung. Wenn ich darüber schreibe, dann allein deswegen weil> diese sprachlichen "Eigenheiten" den Analyseprozess entstellend> beeinflussen.
Alles klar. Nochmals danke an alle (und speziell an Dich!) !
> Ich will trotzdem versuchen Dir mit dem was ich weiss zu helfen. Gehe> Dir mit dem sprachlichen Zeug wahrscheinlich ein paarmal auf die Nerven.
Klasse! Wenn ich dabei lerne, dann ists mir nur Recht!
> Das mit dem Debuggen der Windows-Variante unter Linux scheint mir ein> guter Ansatz zu sein.
Das habe ich mittlerweile durchführen können mit folgendem Ergebnis:
1. Flashen des unter Linux kompilierten Hexfiles.
2. Laufen lassen --> µC stellt LED blinken, Pintogglen und Debugausgaben
ein = "meine" Umschreibung für "hängen bleiben".
3. Debugger klar gemacht und versucht das Linux Hexfile zu debuggen.
Also Debugger scharf gemacht und gestartet -> AVR Studio zeigt den
ersten Eintrag in der Main, danach F5 (Run) ==> Läuft ... ????
Wirklich seltsam. Wenn der Debugger dran hängt und der µC per Run laufen
gelassen wird, dann läufts wie soll. Debugausgaben kommen und die LED
blinkt ...
Sobald ich das Programm ohne Debugger auf dem µC laufen lassen, bleibt
er wieder "hängen".
> Denke daran, das das ausbleiben der Debug-Ausgabe kein "Anhalten"> bedeutet sondern nur, dass der durchlaufene Code keine Ausgaben erzeugt.> Genauso der Zustand in dem keine Änderungen an der LED oder den Ports> mehr erfolgen.
Klar. Irgendwo ist das Ding in einer quasi "Endlosschleife" aus der er
nicht mehr rauskommt ...
> Eine weiter Möglichkeit wäre die Debug-Ausgaben weiter zu> differenzieren. Gib eine Kombination aus einem Buchstaben für die> Funktion und einer Zahl für einen Schritt in der Funktion aus. (Nicht zu> fein gliedern).
Hab ich verstanden und auch schon gemacht! Werde den morgigen Tag mal
nutzen und das ausgiebig erweitern!!
> Was mir auffällt, ist das Du im Text von Debug-Ausgaben innerhalb des> Interrupts sprichst. An sich ist das absolut tödlich, wenn etwa Ausgaben> selbst auch über Ints laufen. Wenn Du das nicht komplett aus den ISRs> entfernen willst dann kommentiere es mal aus. Eine durchaus reale> Möglichkeit, das hier was knackt.
Verstehe. Die Debugausgaben werden nicht über Interrupts ausgegeben,
sondern relativ straight forward:
Meine Debugfunktion ist diese hier (PSTR für das ablegen der Strings im
PROGMEM):
#define Debug_Str(_str) ( dputsP (PSTR(_str)) )
die Funktion dputsP sieht folgendermassen aus:
inline void dputsP (const char * str)
{
while (pgm_read_byte(str) != 0x00)
Debug_ch(pgm_read_byte(str++));
}
und dann noch die Funktion Debug_ch:
inline void Debug_ch (char ch)
{
USART_putc (&DEBUG, ch);
}
mit der USART_putc Funktion:
void USART_putc (USART_t * _usart, char ch)
{
// Wait until data register empty interrupt flag is set
while(!(_usart->STATUS & USART_DREIF_bm));
// Write char to DATA register
_usart->DATA = ch;
}
mir fällt grad auf, dass hier auch noch ne while Schleife ist, die noch
nicht überprüft worden ist. Hole ich nach!
> Ehrlich gesagt halte ich die Möglichkeit des Stacküberlaufs für> wahrscheinlich. Um das zu erkennen kannst Du den Speicher mal mit einem> Muster vollschreiben und hinterher sehen ob das Muster noch da ist.> Gab hier gerade vor ein paar Tagen eine Diskussion dazu. Suche einfach> danach.> Falls es tatsächlich am Stacküberlauf liegt wirst Du mit den bisherigen> Debugausgaben nur bedingt weiterkommen, weil der Code an sich korrekt> ist aber zu viele Verschachtelungsebenen auftreten. Du kannst evtl. eine> Debug-Ausgabe basteln die die die Aufrufebenen zurückgibt, bzw. den> Stackpointer.
Das klingt sehr möglich! Mehr dazu morgen. Hab mal nach Möglichkeiten
gesucht den Stack / Speicherbedarf zu checken gesucht. Ist das hier eine
Möglichkeit Beitrag "Re: ATMEGA32 Stackauslastung im AVR Studio anzeigen" ??
> Du könntest auch mal im Code gucken ob irgendwo absichtlich oder> unabsichtlich Rekursionen auftreten und ob die Abbruchbedingungen> wirklich mit true bewertet werden.
Mach ich morgen!
> Läuft der Code im Simulator? Kannst Du den Fehler im Simulator auch> provozieren?
Unter Linux hab ich den Simulator noch nicht bemüht. Könnte man im
Simulator auch die Kommunikation mit den Sensoren simulieren?? Denn das,
denke ich ist Vorraussetzung für einen sinnvollen Test !?
> Eine gute Möglichkeit ist auch, einen Lint über Deinen Code laufen zu> lassen. Es gibt da einige für Linux.
Lint kenne ich noch nicht. Ich mach mich mal schlau ...
> Falls noch nicht geschehen, lasse Dir alle Warnings ausgeben und> beseitige alle (zeige die die Du meinst nicht beseitigen zu können).
Keine Warnings.
> So, das sind einige Vorschläge. Über die Reihenfolge könnte man noch> gesondert reden, aber da Du schreibst das Du Programmiererfahrung hast,> kannst Du das wahrscheinlich selbst gut entscheiden.
Klasse! Vielen Dank nochmals für die Vorschläge!
Grüße,
Michael
Hallo,
also die ersten Test haben folgendes ergeben:
0. Vorbedingungen:
LA an PORTA angeschlossen und alle 8 Leitungen von 0-7 angeklemmt.
PIN0 wird getoggelt, wenn main durchlaufen wird.
PIN1 wird getoggelt, wenn die "PinChange"-ISR des Gyros ausgeführt wird.
Der Sensor setzt einen seiner Pins für 50µs auf high, wenn neue Daten
vorliegen.
PIN2 wird gesetzt am Anfang der TWI-ISR des Gyros und am Ende davon
wieder gecleared.
1. Test: Sensorwerte auslesen und nichts berechnen.
Dafür wurde in der Datei fc.c (hier läuft die Berechnung der Lagewinkel
(phi, theta, psi - mit Filter) und deren Derivate (phi_dot, theta_dot,
...). In der Funktion wurden alle Berechnungen auskommentiert. Zudem
wurde bei jedem 10. neu gelesenen Sensorwert eine LED getoggelt (Gyro
wird mit 100Hz ausgelesen).
ERGEBNIS:
Es läuft durch (hab 10 Minuten gewartet). Das sehe ich an einer
blinkenden LED und den Pinwacklern.
Ich teste jetzt mal die Stackgeschichte speziell für die Funktion.
Grüße,
Michael
Soweit so gut. Der Log der Debug Ausgaben ist dieser:
FC-start: + 7959<\n>
LIS: + 7959<\n>
LIS-end: + 7959<\n>
ITG: + 7959<\n>
p: + 7959<\n>
q: + 7959<\n>
Also der Speicher, wenn ich das Recht interpretiere, kann es nicht sein,
dennoch gehts in folgender Zeile nicht "weiter" (µC bleibt stehen, keine
ISRs mehr, keine Pinwackler am LA und main wird auch nicht mehr
durchlaufen):
Ein Controller bleibt nicht stehen...
Zu den Memorytests : Man sollte dynamisches Memory sowieso vermeiden.
Das einzige, was mir auffaellt ist das call _divmodsi4 ... ist das
ueberhaupt vorhanden ? Die Adressen 0x2000 + x sind oberhalb 8k. Hat's
soviel RAM ?
O.. oha Jetzt ! schrieb:> Ein Controller bleibt nicht stehen...
Das dachte ich auch ;-) Er macht nur nach der Zeile nicht im
geschriebenen Code weiter, sondern anscheinend irgendwo anders ....
> Zu den Memorytests : Man sollte dynamisches Memory sowieso vermeiden.
Wie genau meinst Du das?? Malloc verwende ich jedenfalls nicht und die
verwendeten array sind alle statisch.
> Das einzige, was mir auffaellt ist das call _divmodsi4 ... ist das> ueberhaupt vorhanden ? Die Adressen 0x2000 + x sind oberhalb 8k. Hat's> soviel RAM ?
nope. Der XMega128A1 hat 8k ....
Bzgl. _divmodsi4 sagt das Listing
1
000034c6<__divmodsi4>:
2
34c6:97fbbstr25,7
3
34c8:092emovr0,r25
4
34ca:0526eorr0,r21
5
34cc:0ed0rcall.+28;0x34ea<__divmodsi4_neg1>
6
34ce:57fdsbrcr21,7
7
34d0:04d0rcall.+8;0x34da<__divmodsi4_neg2>
8
34d2:28d0rcall.+80;0x3524<__udivmodsi4>
9
34d4:0ad0rcall.+20;0x34ea<__divmodsi4_neg1>
10
34d6:001cadcr0,r0
11
34d8:38f4brcc.+14;0x34e8<__divmodsi4_exit>
Ich denke Du meinst die Zeile: mit call 0x34c6
Ich kann zwar kein asm, aber ich denke _divmodsi4 ist ne "Funktion", die
der Kompiler baut und auch im Flash ablegt, oder liege ich da falsch??
Grüße,
Michael
Hi Michael K.
tut mir leid, dass ich mich nicht früher gemeldet habe.
Gestern Abend ist bei mir ne Virusinfektion ausgebrochen und ich habe
38,5 Fieber. Meine "Birne" ist dementsprechend "matschig".
Wenn ich wieder fitter bin, dann schau ich wieder rein.
Eines ist mir allerdings trotzdem aufgefallen, (wenn das keine
Fieberphantasie ist):
In dem Codeschnipsel wo der Debugger nichts weiter anzeigt:
ist der erste Summand eine Typenbezeichnung und keine Variable.
Eigentlich bin ich ziemlich sicher, dass das eine Warnung, wenn nicht
sogar einen Fehler zur Folge haben sollte. Wundere mich gerade wieso da
keine kommt. (Kann aber auch an meiner Matschbirne liegen). Prüf das mal
nach, bitte.
Hast Du wirklich alle Warnings eingeschaltet? Das sollte mit -Wall gehen
(ohne Gewähr, guck nochmal nach).
Mehr in ein paar Tagen wenn ich wieder auf dem Damm bin (und Du das
Problem noch nicht anderweitig lösen konntest).
Viel Erfolg
Wenn er "irgendwo" weitermacht, dann riecht das verdammt nach nem Stack
Overflow.
Und den kannst auslösen, indem du zu viele Funktionen aufrufst durch
ISRs.
Evtl. kannst du noch den Call Stack anschaun. Und schaun wie viel da so
drinsteht, bevor der Controller im Nirvana weitermacht. Bzw. schauen ob
der Call Stack immer weiter wächst. Problem beim Debuggen ist halt, dass
Wartzeiten auf Hardwareeinheiten wie UART durch nen Breakpoint
verschwinden.
An deiner Stelle würde ich die Debugausgaben per UART mit ner
Präprozessoranweisung versehen, so dass die nicht unbedingt im Programm
sein müssen. So sind die alle schnell mal weg.
Desweiteren, versuch doch mal die Sachen in den ISRs zu verkleinern und
evtl. falls du Timerinterrupts benutzt, die Intervalle zu vergrößern.
Falls nach ner Schlankheitskur dein Programm läuft war wohl tatsächlich
ein Stack Overflow vorhanden.
Hallo,
na jetzt geht ja was vorwärts!
Huch schrieb:> Hi Michael K.>> tut mir leid, dass ich mich nicht früher gemeldet habe.> Gestern Abend ist bei mir ne Virusinfektion ausgebrochen und ich habe> 38,5 Fieber. Meine "Birne" ist dementsprechend "matschig".> Wenn ich wieder fitter bin, dann schau ich wieder rein.
Kein Problem und GUTE BESSERUNG!!
> Eines ist mir allerdings trotzdem aufgefallen, (wenn das keine> Fieberphantasie ist):>> In dem Codeschnipsel wo der Debugger nichts weiter anzeigt:>>
>> ist der erste Summand eine Typenbezeichnung und keine Variable.> Eigentlich bin ich ziemlich sicher, dass das eine Warnung, wenn nicht> sogar einen Fehler zur Folge haben sollte. Wundere mich gerade wieso da> keine kommt. (Kann aber auch an meiner Matschbirne liegen). Prüf das mal> nach, bitte.
Das soll eigentlich ein Typcast sein. Die Variable (respektive das
Array) GyroRaw_i16_m14d375__deg_d_s ist vom Typ int16_t. Diesen Wert
will ich nach int32 casten. Compiler schmeisst kein Warning!
>> Hast Du wirklich alle Warnings eingeschaltet? Das sollte mit -Wall gehen> (ohne Gewähr, guck nochmal nach).
Wall ist drin!
>> Mehr in ein paar Tagen wenn ich wieder auf dem Damm bin (und Du das> Problem noch nicht anderweitig lösen konntest).>> Viel Erfolg
Danke!
@Benni:
> Wenn er "irgendwo" weitermacht, dann riecht das verdammt nach nem Stack >
Overflow.
Ich denke den kann ich ausschließen durch die Memory Prüfung.
> An deiner Stelle würde ich die Debugausgaben per UART mit ner> Präprozessoranweisung versehen, so dass die nicht unbedingt im Programm> sein müssen. So sind die alle schnell mal weg.
Kein Problem. Mach ich mal!
> Desweiteren, versuch doch mal die Sachen in den ISRs zu verkleinern und> evtl. falls du Timerinterrupts benutzt, die Intervalle zu vergrößern.
Timerinterrupts sind so gut wie keine drin, bis auf das auslesen des
Beschleunigungsensors. Das Auslesen der Sensorwerte produziert keine
Fehler, wenn die Berechnung in der fc.c nicht durchgeführt wird. Ich
prüfs und teste es trotzdem mal!
@hacky:
Das Datenblatt für den ATXMega128A1 sagt: SRAM Bereich von 0x2000 -
0x3FFF
Grüße,
Michael
>Das soll eigentlich ein Typcast sein.
Aber Du siehst das Problem oder? Mit dem Minuszeichen danach ist das
eine Subtraktion. Du subtrahierst sozusagen von dem Objekt int32_t das
Gyro....
Das GyroRaw wird nicht gecastet.
> Aber Du siehst das Problem oder? Mit dem Minuszeichen danach ist das> eine Subtraktion. Du subtrahierst sozusagen von dem Objekt int32_t das> Gyro....
Hab ich ;-) sie Vorgängerpost ...
Grüße,
Michael
>Wirklich seltsam. Wenn der Debugger dran hängt und der µC per Run laufen>gelassen wird, dann läufts wie soll. Debugausgaben kommen und die LED>blinkt ...>Sobald ich das Programm ohne Debugger auf dem µC laufen lassen, bleibt>er wieder "hängen".
Das ist wirklich bemerkenswert, wenn es (mir) zumindest keine weiteren
Informationen liefert.
Aber der Weg ist auch nicht wirklich, den Debugger einfach laufen zu
lassen. Vielmehr setzt Du an entscheidenden Stellen im Code einen
Breakpoint und prüfst sowohl ob er erreicht wird und ob die Daten an der
Stelle im Code konsistent sind, den Werten entsprechen die Du erwartest.
>> Denke daran, das das ausbleiben der Debug-Ausgabe kein "Anhalten">> bedeutet sondern nur, dass der durchlaufene Code keine Ausgaben erzeugt.>> Genauso der Zustand in dem keine Änderungen an der LED oder den Ports>> mehr erfolgen.>Klar. Irgendwo ist das Ding in einer quasi "Endlosschleife" aus der er>nicht mehr rauskommt ...
Möglich, aber das ist auch nicht mehr als eine Vermutung und damit ohne
grösseren Wert. Du musst feststellen was er macht und nicht Vermutungen
darüber anstellen.
>> Was mir auffällt, ist das Du im Text von Debug-Ausgaben innerhalb des>> Interrupts sprichst. An sich ist das absolut tödlich, wenn etwa Ausgaben>> selbst auch über Ints laufen. Wenn Du das nicht komplett aus den ISRs>> entfernen willst dann kommentiere es mal aus. Eine durchaus reale>> Möglichkeit, das hier was knackt.>Verstehe. Die Debugausgaben werden nicht über Interrupts ausgegeben,>sondern relativ straight forward:
Ich habe der Aussage nicht ganz getraut und habe selbst im Code
nachgesehen. Und voilà: Du machst tatsächlich Ausgaben im Interrupt!
Z.B. in der Datei: lis3lv02dq.c, gleich vorne in der ISR (LIS_TWI_INT)
erfolgt tatsächlich eine Ausgabe "im" Interrupt. Ich muss bekennen, das
ich selbst einmal von Ausgaben "im" Interrupt spreche und einmal von
Ausgaben "über" Interrupts. Das ist nicht dasselbe. Ausgaben "über"
(also im Sinne von "mittels") Interrupts sind hier nicht relevant.
Sondern die Ausgaben "in" Interrupts. Diese können wegen der
Warteschleife in USART_putc zu starken Verzögerungen führen. (Die
bessere Technik ist eigentlich auch die Ausgabe in Buffer die per
Interupt ausgegeben werden). Diese Verzögerungen können wiederrum
Probleme verursachen wenn mehrere Int-Quellen aktiv sind.
Also, nehme die Ausgaben in den Ints raus. Dnke daran auch die
Debug-Ausgaben aus den Funktionen herauszunehmen die von der ISR
aufgerufen werden. Aufgrund von Anwenundunginterrupts darf keine
Debugausgabe erfolgen! Allenfalls mal ein wackeln an nem Portpin für ne
LED.
>> Du könntest auch mal im Code gucken ob irgendwo absichtlich oder>> unabsichtlich Rekursionen auftreten und ob die Abbruchbedingungen>> wirklich mit true bewertet werden.>Mach ich morgen!
Was hat sich dabei herausgestellt?
>> Eine gute Möglichkeit ist auch, einen Lint über Deinen Code laufen zu>> lassen. Es gibt da einige für Linux.>Lint kenne ich noch nicht. Ich mach mich mal schlau ...
Und? Wie stehts damit?
>Also der Speicher, wenn ich das Recht interpretiere, kann es nicht sein,>dennoch gehts in folgender Zeile nicht "weiter" (µC bleibt stehen, keine>ISRs mehr, keine Pinwackler am LA und main wird auch nicht mehr>durchlaufen):
Genau genommen ist das nicht so zu interpretieren. Schau Dir die
Testroutine mal an. Sie beschreibt den Speicher mit einem festen Muster
und prüft später bis wohin das Muster noch vorhanden ist. Es sehr wohl
möglich das das Muster auch in den "normalen" Daten vorhanden ist, die
beim Programmlauf auftreten. Insofern ist nur die Aussage wirklich
relevant, das der Speicher nicht ausreicht. Die Aussage, das der
Speicher reicht ist nur bedingt richtig. Es ist nützlich, die Routine
mal mit noch einem oder zwei anderen Mustern mitlaufen zu lassen und die
Ergebnisse zu vergleichen. Ausserdem sind auf diese Weise die Interrupts
nicht abgedeckt. Du müsstet noch sicherstellen, das vor Aufruf von
get_mem_unused alle Interrupts wenigstens einmal in allen Zweigen
durchlaufen worden sind. Besser ist es, das im Simulator einmal
durchzuspielen.
Aber was mir auffällt, ist das Du Dich von dem Gedanken, dass eine CPU
stehenbleibt noch nicht verabschiedet hast. Streich das aus Deinem
Denken. Sowas gibt es nicht. Er macht immer irgendwas. Und genau das ist
wichtig! Was genau macht er anstelle des Codes der dasteht?
Setze einen Breakpoint auf die Codezeile. Bei erreichen stellst Du auf
Anzeige des Assembler-Codes um und gehst im Einzelschritt weiter. Guck
Dir den Stack an, ob die Return-Addressen gültig sind, insbesondere vor
rets.
Berichte hier am besten im Detail darüber was Du festgestellt hast,
auch wenn Dir nichts besonderes auffällt.
Ich möchte Dir an dieser Stelle empfehlen zunächst den Code durch einen
Lint laufen zu lassen. Das Problem ist, das die anderen Methoden relativ
viel Aufwand erfordern und Kenntnisse von Assembler und des uC. Der Lint
hingegen findet relativ mühelos Probleme im Code auf. Erst wenn das
nichts bringt würde ich mit dem Debuggen weitermachen.
Die Entfernung der Debug-Ausgaben aus den Interrupts ist wichtig. Mach
das auf jeden Fall.
Dann erst wieder Debuggen bzw. Simulieren.
Hoffe das bringt Dich weiter.
Viel Erfolg.
Hallo
> Aber der Weg ist auch nicht wirklich, den Debugger einfach laufen zu> lassen. Vielmehr setzt Du an entscheidenden Stellen im Code einen> Breakpoint und prüfst sowohl ob er erreicht wird und ob die Daten an der> Stelle im Code konsistent sind, den Werten entsprechen die Du erwartest.
Das hab ich gemacht. Debuggen geht zur Zeit leider nur unter Windows,
und da läuft der Code ja ....
>>>> Denke daran, das das ausbleiben der Debug-Ausgabe kein "Anhalten">>> bedeutet sondern nur, dass der durchlaufene Code keine Ausgaben erzeugt.>>> Genauso der Zustand in dem keine Änderungen an der LED oder den Ports>>> mehr erfolgen.>>>Klar. Irgendwo ist das Ding in einer quasi "Endlosschleife" aus der er>>nicht mehr rauskommt ...> Möglich, aber das ist auch nicht mehr als eine Vermutung und damit ohne> grösseren Wert. Du musst feststellen was er macht und nicht Vermutungen> darüber anstellen.
Stimmt. Bin dabei!
>>>> Was mir auffällt, ist das Du im Text von Debug-Ausgaben innerhalb des>>> Interrupts sprichst. An sich ist das absolut tödlich, wenn etwa Ausgaben>>> selbst auch über Ints laufen. Wenn Du das nicht komplett aus den ISRs>>> entfernen willst dann kommentiere es mal aus. Eine durchaus reale>>> Möglichkeit, das hier was knackt.>>>Verstehe. Die Debugausgaben werden nicht über Interrupts ausgegeben,>>sondern relativ straight forward:>> Ich habe der Aussage nicht ganz getraut und habe selbst im Code> nachgesehen. Und voilà: Du machst tatsächlich Ausgaben im Interrupt!> Z.B. in der Datei: lis3lv02dq.c, gleich vorne in der ISR (LIS_TWI_INT)> erfolgt tatsächlich eine Ausgabe "im" Interrupt. Ich muss bekennen, das> ich selbst einmal von Ausgaben "im" Interrupt spreche und einmal von> Ausgaben "über" Interrupts. Das ist nicht dasselbe. Ausgaben "über"> (also im Sinne von "mittels") Interrupts sind hier nicht relevant.> Sondern die Ausgaben "in" Interrupts. Diese können wegen der> Warteschleife in USART_putc zu starken Verzögerungen führen. (Die> bessere Technik ist eigentlich auch die Ausgabe in Buffer die per> Interupt ausgegeben werden). Diese Verzögerungen können wiederrum> Probleme verursachen wenn mehrere Int-Quellen aktiv sind.> Also, nehme die Ausgaben in den Ints raus. Dnke daran auch die> Debug-Ausgaben aus den Funktionen herauszunehmen die von der ISR> aufgerufen werden. Aufgrund von Anwenundunginterrupts darf keine> Debugausgabe erfolgen! Allenfalls mal ein wackeln an nem Portpin für ne> LED.
Der Unterschied ist mir klar. Momentan erfolgen keine Ausgaben im
Interrupt. Die können über die tricopter_config.h ausgeschaltet werden:
#define TWI_DEBUGGING 0
#define LIS_DEBUGGING 0
#define LIS_ERROR_DEBUGGING 0
#define ITG_DEBUGGING 0
#define ITG_ERROR_DEBUGGING 0
und in der lis3lv02dq.h:
1
#if (LIS_DEBUGGING == 1)
2
#define LIS_Debug_Str(_str) ( Debug_Str(_str) )
3
#define LIS_Debug_u8(_u8) ( Debug_u8(_u8) )
4
#else
5
#define LIS_Debug_Str(_str)
6
#define LIS_Debug_u8(_u8)
7
#endif
>>> Du könntest auch mal im Code gucken ob irgendwo absichtlich oder>>> unabsichtlich Rekursionen auftreten und ob die Abbruchbedingungen>>> wirklich mit true bewertet werden.>>>Mach ich morgen!> Was hat sich dabei herausgestellt?
Alle so wie es sein sollte ...
>>>> Eine gute Möglichkeit ist auch, einen Lint über Deinen Code laufen zu>>> lassen. Es gibt da einige für Linux.>>>Lint kenne ich noch nicht. Ich mach mich mal schlau ...> Und? Wie stehts damit?
splint ist installiert und läuft ... bekomme leider relativ häufig:
Parse Error. Bin dabei das zu beheben.
>>Also der Speicher, wenn ich das Recht interpretiere, kann es nicht sein,>>dennoch gehts in folgender Zeile nicht "weiter" (µC bleibt stehen, keine>>ISRs mehr, keine Pinwackler am LA und main wird auch nicht mehr>>durchlaufen):> Genau genommen ist das nicht so zu interpretieren. Schau Dir die> Testroutine mal an. Sie beschreibt den Speicher mit einem festen Muster> und prüft später bis wohin das Muster noch vorhanden ist. Es sehr wohl> möglich das das Muster auch in den "normalen" Daten vorhanden ist, die> beim Programmlauf auftreten. Insofern ist nur die Aussage wirklich> relevant, das der Speicher nicht ausreicht. Die Aussage, das der> Speicher reicht ist nur bedingt richtig. Es ist nützlich, die Routine> mal mit noch einem oder zwei anderen Mustern mitlaufen zu lassen und die> Ergebnisse zu vergleichen. Ausserdem sind auf diese Weise die Interrupts> nicht abgedeckt. Du müsstet noch sicherstellen, das vor Aufruf von> get_mem_unused alle Interrupts wenigstens einmal in allen Zweigen> durchlaufen worden sind. Besser ist es, das im Simulator einmal> durchzuspielen.
OK. Ich werde das unter Windows mal durchführen.
> Aber was mir auffällt, ist das Du Dich von dem Gedanken, dass eine CPU> stehenbleibt noch nicht verabschiedet hast. Streich das aus Deinem> Denken. Sowas gibt es nicht. Er macht immer irgendwas. Und genau das ist> wichtig! Was genau macht er anstelle des Codes der dasteht?
Ist gestrichen. Das "anhalten" ist mehr eine Umschreibung meinerseits
für das Beobachtete, als eine konkrete Beschreibung! Das Problem ist,
dass er nichts mehr macht, was im Code darsteht (also weder Pins wackeln
noch LED blinken, noch Debug produzieren)
> Setze einen Breakpoint auf die Codezeile. Bei erreichen stellst Du auf> Anzeige des Assembler-Codes um und gehst im Einzelschritt weiter. Guck> Dir den Stack an, ob die Return-Addressen gültig sind, insbesondere vor> rets.
OK.
> Berichte hier am besten im Detail darüber was Du festgestellt hast,> auch wenn Dir nichts besonderes auffällt.
Mach ich.
> Ich möchte Dir an dieser Stelle empfehlen zunächst den Code durch einen> Lint laufen zu lassen. Das Problem ist, das die anderen Methoden relativ> viel Aufwand erfordern und Kenntnisse von Assembler und des uC. Der Lint> hingegen findet relativ mühelos Probleme im Code auf. Erst wenn das> nichts bringt würde ich mit dem Debuggen weitermachen.
s.o.
> Die Entfernung der Debug-Ausgaben aus den Interrupts ist wichtig. Mach> das auf jeden Fall.
Ist schon passiert!
> Dann erst wieder Debuggen bzw. Simulieren.>> Hoffe das bringt Dich weiter.>> Viel Erfolg.
Vielen Dank nochmals an alle ... ich kämpfe weiter und gebe Feedback!
Grüße,
Michael
Soooo,
viel ist passiert und gleich vorweg ... ich scheine einen Bug
unabsichtlich behoben zu haben, denn jetzt läufts. Warum -- weiss ich
noch nicht genau ;-)
Der von mir eingesetzte Sensor ITG-3200 gibt an einem Pin für 50µs ein
high Signal aus wenn neue Daten abgefragt werden können. Das hab ich mir
einer PinChange ISR (rising edge) mitgekriegt und die Datenabfrage
gestartet. Soweit so gut, aber mein anfängliches Problem war, dass mit
dem Sensor relativ häuft der Busstate "ARB Lost" eingetreten ist, trotz
sauberer I2C Beschaltung (Pullups, etc.). Stromversorgung war ok, die
Pegel auch und trotzdem liefs einfach nicht so wirklich rund. Alle 1 - 2
Sekunden hat sich der Bus verabschiedet. Mein Workaround war dann:
1. TWI abschalten und SDA als Input und SCL als Output konfigurieren.
2. SCL so lange toggeln bis SDA wieder hoch kommt
3. Wenn SDA wieder high ist, dann TWI wieder einschalten und
konfigurieren und weiter gehts.
Das hat soweit auch recht gut funktioniert. Jetzt habe ich zu
Testzwecken mal ne Debugausgabe vor dem Starten der Datenabfrage
reingemacht und plötzlich waren die ARB-Lost Stati weg!? Mittlerweile
wird die Datenabfrage gestartet, wenn das Data-Ready-Signal fällt, also
50µs später und die ARB-Lost sind so gut wie verschwunden (1 - 2 in 10
Minuten).
Zum Recovern wurde der TWI Bus Status im Interrupt abgefragt und wenn
der State ARB Lost eingetreten ist, dann wurde die "Recoverfunktion" aus
dem Interrupt heraus aufgerufen. Im Zuge der Einarbeitung Eurer
Vorschläge (Ints schlank und schnell halten, ohne Debug Ausgaben) hab
ich dann auch den Aufruf Funktion aus dem Interrupt genommen und statt
dessen einfach ein Flag gesetzt, das eine Funktion prüft, die aus der
main aufgerufen wird. Und ... jetzt rennts. Genau kann ich noch nicht
sagen warum genau, aber ich habe die Vermutung, dass der µC dauerhaft im
TWI Interrupt hängen geblieben ist und nicht mehr raus kam. Das hätte
ich eigentlich mit dem LA sehen müssen - hab ich aber nicht ... ich
teste weiter und immerhin hab ich schon mal nen Anhaltspunkt, wo die
Ursache liegen könnte.
Ich halte Euch auf dem Laufenden!
Grüße,
Michael
Hallo zusammen,
Leider ist die Zeit im Hinblick auf Neujahr leider ein wenig knapp und
deshalb konnte ich weniger schaffen, als erwartet, aber es gibt wieder
ein paar Neuigkeiten. Ich hab das vorgeschlagene Vorgehen von Huch mal
durchgeführt und ausgiebigst gedebugged. Den Beschleunigungssensor hab
ich mal "rausgenommen" und die Gyrowerte abgefragt und das Ganze im
Debugger angeschaut. Breakpoints in den Interrupts vor und nach while
Schleifen und mir auch den ASM Code angeschaut und die
Rücksprungadressen kontrolliert. Dabei konnte ich keinen Fehler
feststellen. Alles läuft wie gewollt.
Kompiliert, geflasht und gedebugged unter Windows. Soweit super. Ich
wollte die Änderungen vom Gyro-"Treiber" auch für den
Beschleunigungssensor (der soll mit 100Hz abgefragt werden) umsetzen,
der nicht wie das Gyro per PinChange-Interrupt abgefragt wird, sondern
per Timer-Interrupt.
0. Gyrosensor soll mit 400Hz ausgelesen werden.
1. Sensor gibt für 50µs ein High - Signal, wenn neue Daten verfügbar
sind.
2. PinChange - Interrupt startet das Auslesen des Sensors per TWI
3. Gyro-Treiber arbeitet Interruptbasiert
4. LA Konfiguration:
-- 0: Pin toggle in der main
-- 1: Pin toggle in der Pin Change ISR (Gyro)
-- 2: am Anfang der TWI ISR wird Pin2 gesetzt und beim verlassen wieder
gecleared
-- 4: Pin toggle in der Timer OVF ISR (Accelerometer)
Bild LA_WIN / LA_WIN2 ist ein Screener vom LA.
* Die weißen Blöcke auf Kanal 0 zeigen, wenn die main durchlaufen wird.
* Kanal 1 zeigt den Pin Toggle aus der PinChange ISR. Die
"Toggle"-Frequenz entspricht den gewollten 400Hz.
* Kanal 2 zeigt die TWI ISR. Sobald neue Daten am Gyro verfügbar sind
startet die Datenübertragung und die TWI ISR wird durchlaufen. Ein ISR
Durchlauf dauert in der Regel 1-3µs. Und die komplette Datenabfrage vom
Sensor ist nach ca. 0.2ms abgeschlossen.
* Kanal 4 zeigt die TimerOVF-ISR in der momentan nur ein Pin getoggelt
wird.
Alles super.
Dann gings unter Linux weiter. Also wieder LA dran und schon gab es die
ersten seltsamen Ergebnisse.
Code ist der gleiche wie unter Windows.
Die Bilder LA_LINUX / LA_LINUX2 zeigen den gleichen Code, nur unter
Linux kompiliert und geflasht. Das Gyro arbeitet wie erwartet, jedoch
wird die Timer OVF ISR für den Beschleunigungssensor nicht so "sauber"
ausgeführt (unregelmässiger PinToggle, vgl. Kanal4) wir mit dem unter
Windows kompilierten Code. Der Beschleunigungssensor wird momentan noch
nicht ausgelesen und ist somit inaktiv! Ich wollte nur kontrollieren, ob
die Timer-ISR sauber ausgeführt wird und zu der Windows Version sind
hier heftige Unterschiede!! Irgendwas ist mit dem Linux faul ....
Ich wünsche Euch dennoch ein gutes neues Jahr und einen guten Rutsch
heute abend!! Ich melde mich dann bis ins neue Jahr ab, da langsam die
Vorbereitungen für heute abend anlaufen ...
Grüße,
Michael
Michael K. schrieb:> Soweit so gut, aber mein anfängliches Problem war, dass mit> dem Sensor relativ häuft der Busstate "ARB Lost" eingetreten ist,
Das hatte ich auch. Hat mich ziemlich lang beschäftigt. Hat sich
herausgestellt, dass ich einen Wackelkontakt am Weg von Xmega zu
Steckbrett hatte. Gemessen habe ich mit dem Oszilloskop immer an den
Pullups... Die so gesehene Spannung hat der Xmega an seinem SDA Pin
allerdings nie zu spüren bekommen. Der war damit mehr oder weniger
Floating... --> ARB Lost...
Sry, dass ich damit dieses alte Thema noch mal aufgreife... Habs aber
mit Googel gefunden, da "gleiches Problem" und möchte zukünftige Sucher
damit einen Lösungsweg aufzeigen. :)