Forum: Mikrocontroller und Digitale Elektronik Cortex M4F: RAM Image analysieren


von Adam P. (adamap)


Lesenswert?

Hallo zusammen,

kurze Problemdarstellung:
In meinem System kommt es zu einem Verhalten was auftritt (Messungen 
belegen dies), jedoch kann "ich" es weder nachvollziehen noch 
reproduzieren.
Ich habe zwar eine Idee was es sein könnte, kann es jedoch nicht prüfen, 
da ich es nicht in diesen Zustand bekomme.

Nun die Idee:
Falls ich in der FW diesen Zustand erkenne, würde ich direkt alle 
Interrupts deaktivieren und die 128KB RAM auf die SD Karte spiegeln.
Danach die Werte mithilfe des *.map File analysieren.
(Um zu schauen welche Variablen evtl. aus der Reihe tanzen)

Gibt es ein Programm welches eine *.map File über ein Image vom RAM legt 
und direkt anzeigt welche Variablen welche Werte hatten?

Gruß Adam

von c-hater (Gast)


Lesenswert?

Adam P. schrieb:

> In meinem System kommt es zu einem Verhalten was auftritt (Messungen
> belegen dies), jedoch kann "ich" es weder nachvollziehen noch
> reproduzieren.
> Ich habe zwar eine Idee was es sein könnte, kann es jedoch nicht prüfen,
> da ich es nicht in diesen Zustand bekomme.

Nun, wenn du eine Idee hast, was es sein könnte (das ist gut, praktisch 
der halbe Weg zur Lösung, wenn sie zutrifft!!!), dann sollte es kein 
Problem sein, die Situation gewollt herbei zu führen.

Leider ist es viel typischer, dass man eigentlich erstmal gar keine Idee 
hat, denn man hat natürlich alles nach bestem Wissen und Gewissen 
umgesetzt.

> Nun die Idee:
> Falls ich in der FW diesen Zustand erkenne

Das setzt doch aber schon eine zutreffende Idee voraus, oder nicht? Wie 
soll das sonst gehen?

> würde ich direkt alle
> Interrupts deaktivieren und die 128KB RAM auf die SD Karte spiegeln.

Nunja, heutzutage macht man sowas mit einem Debugger. Wenn man erstmal 
weiß, wo es sinnvoll ist, einen Breakpoint zu setzen, um die 
Fehler-Situation zu fangen, ist schonmal ein Drittel der Miete drin.

Mit ein bissel Glück ist es dann möglich, mit der im Debugger 
eingefrorenen Situation (die ja im Prinzip deiner Mapfile-Idee 
entspricht, aber eher doch besser ist als diese), die Sache zu klären.

Leider ist das aber nicht immer möglich. Es gibt da leider richtig fiese 
Fehler, die sich Millionen oder Milliarden Takte vor dem eingefrorenen 
Zustand ausgewirkt haben, ursächlich für diesen Zustand sind, aber aus 
dem eingefrorenen Zustand trotzdem praktisch nicht mit vernünftigem 
Aufwand ermitteln lassen.

Solche Fehler zu finden, das ist dann die Spielwiese für Simulatoren und 
Stimuli. Natürlich zusammen mit in den Code einzubauenden Mechanismen 
für's Logging (woher sollen sonst die Stimuli für den Simulator kommen).

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Kommt es denn zu einem Hardfault oder ähnliches?

Ansonsten guck dir mal Segger Systemview an, damit kannste live aufs 
System gucken.
Geht mit deren Tracer zwar noch schneller, aber der kost dann 
ordentlich.

von Adam P. (adamap)


Lesenswert?

c-hater schrieb:
> dann sollte es kein
> Problem sein, die Situation gewollt herbei zu führen.

Ich kenne die Auswirkung, aber bekomme diesen Zustand nicht hin, sprich 
den Grund für dieses Verhalten.

c-hater schrieb:
>> Nun die Idee:
>> Falls ich in der FW diesen Zustand erkenne
>
> Das setzt doch aber schon eine zutreffende Idee voraus, oder nicht? Wie
> soll das sonst gehen?

In dem ich prüfe ob dieser Zustand gerade da ist.

c-hater schrieb:
> Nunja, heutzutage macht man sowas mit einem Debugger.

Klar, wenns neben dir liegt, sehr gerne...jedoch sind diese Geräte nicht 
bei mir und externe Debug Möglichkeiten gibt es dort vor Ort nicht.

Mw E. schrieb:
> Kommt es denn zu einem Hardfault oder ähnliches?

Nein, ein Hardfault wäre ja noch einfach zu finden (Call Stack).
Es ist einfach ein "Funktionsaussetzer", ein Modul tut nicht mehr das 
was es soll.

Mw E. schrieb:
> Ansonsten guck dir mal Segger Systemview an, damit kannste live aufs
> System gucken.
> Geht mit deren Tracer zwar noch schneller, aber der kost dann
> ordentlich.

Das geht wie gerade gesagt nicht, da ich es nicht in diesen Zustand 
bekomme. Keine Ahnung was oder wie die es da draußen machen, 
unerklärlich.

Deshalb wollte ich diesen Weg einschlagen.
Ein Log (Image) erstellen und dann auslesen lassen, mir zuschicken, 
schauen/vergleichen.

Die Sache ist, ich kann mich doch jetzt nicht da hinsetzen und ein RAM 
Image händisch mit dem map file vergleichen und dann schauen welche 
Werte ok sind oder nicht.

Wäre schon schick, wenn es ein Programm gäbe das ein Byte Image und dem 
map File übereinander legt und zumindest die Werte der Variablen 
anzeigt.

Aber ich glaub das werde ich dann wohl selbst schreiben müssen?

: Bearbeitet durch User
von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

Nie was damit gemacht aber evtl. hilft dir das weiter
https://github.com/adamgreen/CrashDebug

Matthias

von Olaf (Gast)


Lesenswert?

> Klar, wenns neben dir liegt, sehr gerne...jedoch sind diese Geräte nicht
> bei mir und externe Debug Möglichkeiten gibt es dort vor Ort nicht.

Es gibt auch J-Links mit Netzwerkanschluss. .-)


Ansonsten kannst du dir natuerlich beim uebersetzen deines Programms 
eine lange Liste mit allen Variablen und sonstigen Speicherpositionen 
erzeugen lassen. Ich nutze das z.B um in einem selbstgeschriebenen 
Programm mit Jlink auf einen Controller zuzugreifen um mir in Echtzeit 
Variablen anzuschauen.
Das macht in Ausnahmen Sinn. Allerdings nicht wenn du letztlich die 
gesamte Funktionalitaet eines Debuggers ersetzen willst. Einfach zuviel 
Arbeit.

Du koenntest aber einen anderen Weg gehen.

Schreibe dein Speicherabbild und natuerlich auch ein Abbild der Register 
des Controllers raus und lese es zuhause wieder ein. Dann kannst du dich 
danach ja mit deinem Debugger mit dem Programm verbinden und schauen was 
es so macht. Das sollte grundsaetzlich kein Problem sein, jedenfalls 
wenn du mit der dann fehlenden Initialisierung deiner Hardware leben 
kannst. Aber immerhin koenntest du dann mit dem Debugger den 
Softwarestand analysieren.
Trotz allem vermutlich noch eine Menge Arbeit bis es im Detail laeuft.

Olaf

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Da es kein offensichtliches Tool für sowas gibt machts wohl auch kaum 
jemand.
Wennes selber schreibst, dann nimm das elf File mit Debugsymbolen statt 
dem map.
Das müssteste ja sonst noch selber parsen.
Zudem steht im mapfile nicht jede Variable einzeln, sondern der 
Größenverbrauch der obj wird gemappt. (Beim GCC, andere Compiler machens 
vllt anders)
(Beispiel:  .bss  0x20000af0  0x1c periph/usart.o)
Für elf gibts Python Libs.
-> https://github.com/eliben/pyelftools
Da lässt sich Adresse, Name und Initwert von Speicherbereichen auslesen.

Olaf schrieb:
> Es gibt auch J-Links mit Netzwerkanschluss. .-)

Segger bietet auch nen Tunnelserver an um Remote überall auf der Welt zu 
debuggen!
-> 
https://www.segger.com/products/debug-probes/j-link/tools/j-link-remote-server/
Das geht aber auch mitm USB J-Link und nem Laptop.

Mal noch ne Frage am Rande (für die Zukunft).
Die MPU is aktiv?
Damit lassen sich die Adressbereiche vor dem Flash sperren und schon 
fällt jeder Nullpointerzugriff direk auf, der sonst zu vagabundierenden 
Programmen inkl "komischer" Zustände führen kann.
(Nich vergessen das VBAR aufn FLash zeigen zu lassen vorher)

von Klaus W. (mfgkw)


Lesenswert?

Eigentlich ist das alles genau Aufgabe von gdb.
Der kann auch eine core-Datei einlesen und wenn man ihm die 
Symboltabelle spendiert, kann man direkt per Name jede Variable 
anschauen.

Also geht es doch "nur" darum, alles was du hast, in eine Form zu 
bringen, die der gdb lesen kann.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Klaus W. schrieb:
> Eigentlich ist das alles genau Aufgabe von gdb.
> Der kann auch eine core-Datei einlesen und wenn man ihm die
> Symboltabelle spendiert, kann man direkt per Name jede Variable
> anschauen.
> Also geht es doch "nur" darum, alles was du hast, in eine Form zu
> bringen, die der gdb lesen kann.

Und genau das versucht das von mir genannte Tool zu automatisieren.

Matthias

von Stefan F. (Gast)


Lesenswert?

Adam P. schrieb:
> Falls ich in der FW diesen Zustand erkenne, würde ich direkt alle
> Interrupts deaktivieren und die 128KB RAM auf die SD Karte spiegeln.

Und dann hast du eine große Menge an Daten, die niemand auswerten kann.

Erzeuge lieber Log-Meldungen die du auf ein Speichermedium schreibst 
oder seriell ausgibst. Bei Dateien kann es Sinn machen, diese in einem 
FIFO Puffer zu sammeln und den Puffer nur dann in die Datei zu 
schreiben, wenn ein Fehler erkannt wurde. Wobei dann jeder Thread einen 
eigenen Puffer haben sollte.

von Adam P. (adamap)


Lesenswert?

Erstmal danke für die genannten Tools, werde ich mir mal näher 
anschauen.

Die Ideen mit "Ferndebugen" sind nicht möglich, da die Geräte zu sind 
und nicht geöffnet werden dürfen/können.

Stefan ⛄ F. schrieb:
> Erzeuge lieber Log-Meldungen die du auf ein Speichermedium schreibst

Ja, das war meine erste Idee, da ich eh Log-Meldungen habe die seriell 
ausgegeben werden. (Diese Schnittstelle ist jedoch auch nicht 
zugänglich)

Ich werde es dann wohl erst mit den Log-Meldungen versuchen und diese 
auf die SD Karte umleiten.

von Olaf (Gast)


Lesenswert?

> Zudem steht im mapfile nicht jede Variable einzeln, sondern der
> Größenverbrauch der obj wird gemappt. (Beim GCC, andere Compiler machens
> vllt anders)

So?

Eine Kommandozeile schnell getippert:

nm -n -S BoardTest |grep '^2' |grep ' 0000' |grep -v '__' >variable.txt


Olaf

von Adam P. (adamap)


Lesenswert?

Olaf schrieb:
> Eine Kommandozeile schnell getippert:
>
> nm -n -S BoardTest |grep '^2' |grep ' 0000' |grep -v '__' >variable.txt

Ist "BoardTest" dein *.map File?

: Bearbeitet durch User
von Klaus W. (mfgkw)


Lesenswert?

Adam P. schrieb:
> Ist "BoardTest" dein *.map File?

nm gibt man eine Objektdatei mit als Argument.

Nachtrag: gibt man keine an, wird a.out angenommen.

: Bearbeitet durch User
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Also nimmt Olafs Kommandozeile kein map file, sondern die elf.
Die Endung is ja egal.
Da steht dann auch alles sinnvolle drinne, so wie ich oben schon 
angemerkt habe.

Output:
1
20000000 00000004 D _impure_ptr
2
20000008 00000428 d impure_data
3
200009ac 00000100 b usart3_tx_buf
4
20000aac 00000024 b usart3_irq
5
20000ad0 00000010 b usart3_rx_buf
6
20000ae0 00000001 b receive_index
7
20000ae4 00000002 b recbuf
8
20000ae8 00000004 b ubase
9
20000aec 00000004 b byteout_p
10
20000af0 0000001c b irq_idx
11
20000b40 00000004 B _PathLocale
12
20000b44 00000004 b heap_end.4144
13
20000b6c 00000004 B errno

Scheint jetz aber nich alles zu sein, die Lücke vor 200009ac kommt mir 
etwas zu groß vor.

von Adam P. (adamap)


Lesenswert?

Mw E. schrieb:
> Also nimmt Olafs Kommandozeile kein map file, sondern die elf.
> Die Endung is ja egal.
> Da steht dann auch alles sinnvolle drinne, so wie ich oben schon
> angemerkt habe.

Also das sieht schon einmal gut aus.

von Olaf (Gast)


Lesenswert?

> Scheint jetz aber nich alles zu sein, die Lücke vor 200009ac kommt mir
> etwas zu groß vor.

Man kann mit den Parametern von nm einiges spielen. Ich hab da
ganz bewusst verschiedenes weggelassen weil ich nur diese Variablen
brauche um sie ueber den jlink aus meinem Controller auszulesen.

Olaf

von Jim M. (turboj)


Lesenswert?

Mw E. schrieb:
> Scheint jetz aber nich alles zu sein, die Lücke vor 200009ac kommt mir
> etwas zu groß vor.

Nö, die impure_data struktur is so absurd groß in newlib. Such das mal 
im Map File.

von Johannes (Gast)


Lesenswert?

Ist an sich eine gute Idee und wird so auch häufig bei komplexeren 
Systemen gemacht (wenn man nicht mit dem Debugger rein kommt). Der Linux 
Kernel erzeugt dir einen Core Dump wenn er sich verabschiedet, bei 
Windows heißt die Technik dazu Minidump und macht das gleiche.

Was du nicht vergessen solltest: Speicher nach Möglichkeit auch ein paar 
wichtige Register (Stack- und Base Pointer, MSRs bzw. auf ARM ?Control 
Register? usw.) und MMIO Address Spaces ab (=Register der Peripherie).


Um das fehlende Tooling anzugehen könntest du probehalber das Image auf 
ein baugleiches Board spielen und dann mit dem Debugger drauf gehen. 
Brauchst ja gar nicht laufen lassen.

Ansonsten musst du halt die Bytes durchgehen, wobei man mit ein wenig 
Skripting da schon viel erreichen kann.

von Klaus W. (mfgkw)


Lesenswert?

Mw E. schrieb:
> die Lücke vor 200009ac kommt mir
> etwas zu groß vor.

Der letzte Wert vorher könnte ja auch ein Feld sein.

Außerdem wechselt an der Lücke die section:
Vorher ist D und d, das sind Werte aus der initialisierten data section.
Die mit B und b sind BSS (unitialisiert).

von Adam P. (adamap)


Lesenswert?

Johannes schrieb:
> Um das fehlende Tooling anzugehen könntest du probehalber das Image auf
> ein baugleiches Board spielen und dann mit dem Debugger drauf gehen.
> Brauchst ja gar nicht laufen lassen.

Das ist mal eine gute Idee.
Weißt du zufällig wie ich das geschickt machen könnte?

Ich arbeite mit Atmel Studio und dem Atmel SAM-ICE von SEGGER.

Bekomme ich im Debug Mode (Breakpoint) auch irgendwie das RAM geschickt 
ausgelesen, außer mit dem Memory View?

von Johannes (Gast)


Lesenswert?

Mit den Debuggern hab ich leider keine Erfahrung. Mit dem GDB kannst du 
blockweise Speicher lesen/schreiben von/in Datei, egal ob die CPU läuft 
oder angehalten ist.

https://sourceware.org/gdb/onlinedocs/gdb/Dump_002fRestore-Files.html

von Adam P. (adamap)


Lesenswert?

Habs für SEGGER gefunden, dass Tool heißt "JMem.exe".

von Til S. (Firma: SEGGER) (til_s)


Lesenswert?


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.