Hallo,
in meinem PowerPC (56xx) Programmablauf kommt es nach gewisser Zeit zu
einem falschen Programmablauf. Und zwar springt er zu Adresse 0x0.
Die Ursache für diesen Sprung ist in diesen Zeilen zu finden:
1
..
2
....
3
lwzx r3,r3,r0 ; schreibe 0 nach r3
4
se_mtctr r3 ; schreibe r3 nach CTR (Count Register)
5
se_bctr ; branch zu CTR
Kann mir jemand sagen, was das für einen Sinn haben soll?
An Adresse 0x0 steht das Reset Configuration Half Word (RCHW) =
0x015A0000.
Da wird er wohl kaum hinspringen wollen.
Ich glaube, dass r3 einfach nicht 0 sein darf - aber nur eine Vermutung.
Wie die Null zu stande kommt sieht man wie folgt. Hier also der ganze
Abschnitt:
1
; r0 = 0x0003A360
2
; r1 = 0x40003E2F
3
se_lhz r0,0x10(r1) ; nach diesem Schritt ist r0 gleich 0
4
se_cmpli r0,0x8
5
se_bgt 0x37A1E
6
e_lis r8,0x40000000
7
e_add16i r3,r8,0x1CD8
8
se_slwi r0,0x2
9
lwzx r3,r3,r0 ; schreibe 0 nach r3
10
se_mtctr r3 ; schreibe r3 nach CTR (Count Register)
11
se_bctr ; branch zu CTR
Ich verstehe hier nicht, wass der ASM mit
se_lhz r0,0x10(r1)
macht. Was bedeutet diese Zeile?
Hi Udo,
wenn ich mich richtig erinnere holt deine Zeile einen Wert aus der
Speicherzelle, welche durch R1 plus 0x10 adressiert wird. In deinem
Codeschnippsel steht darüber dass r1 = 0x40003E2F ist. Also wird der
Wert aus dem RAM geholt. Entweder hast du vergessen eine Initfunktion
aufzurufen. Oder es Mangelt an einer Routine zum Kopieren, der
vorinitialisierten Variablen.
Gruß,
TManiac
ok, er holt sich den Wert aus 0x40003E2F + 0x10 = 0x40003E3F.
Dort steht 0x40 drin. Warum er denkt, es wäre 0, weis ich nicht :-(
Ja, es wird aus dem RAM geholt. Warum meinst du, dass es falsch wäre?
Deine Antwort klingt zumindest so.
Habe nochmal geschaut. An der Stelle steht wirklich 0x00 drin.
In dem Bereich liegt der Stack - ist also ein Stack Zugriff.
Greift der falsch auf den Stack zu? Ist schon komisch, da es nur ab und
zu dieses Verhalten bringt.
Weitere Erkenntniss:
der code oben ist der Assembler Code einer switch-case Anweisung.
switch (value):
>> code_oben
case 0:
break;
case 1:
break;
...
case 7:
break;
Wenn ich nur 4 case Auswertungen habe, 3 andere also weglösche, sieht
der ASM code anders aus (andere Befehlfolge). Und dann schmiert er auch
nicht ab.
Für den Compiler gilt also ab 5 case Auswertungen eine andere
Optimierung?
Desweiteren habe ich die switch-case durch ein if-else-if ersetzt.
Damit gehtn auch alle meine 7 erfolgreich - auch weil anderer ASM code
erzeugt wird.
Welche Gründe gibt es denn hierfür?
Udo schrieb:> Weitere Erkenntniss:>> der code oben ist der Assembler Code einer switch-case Anweisung.>>> switch (value):> >> _code_oben_>> case 0:> break;>> case 1:> break;>> ...
Sieht den Code wirklich so aus?
also in etwa
1
inta;
2
voidfoo(inti)
3
{
4
switch(i)
5
{
6
a=1;
7
8
case2:
9
a=4;
10
break;
11
12
case5:
13
a=7;
14
break;
15
}
16
}
Code im switch ohne case/default davor ist nicht wirklich prickelnd...
> Wenn ich nur 4 case Auswertungen habe, 3 andere also weglösche, sieht> der ASM code anders aus (andere Befehlfolge). Und dann schmiert er auch> nicht ab.>> Für den Compiler gilt also ab 5 case Auswertungen eine andere> Optimierung?
Ja. Ab 5 oder 4 (hängt wiederum von was anderem ab) case-Labels
verwendet gcc Sprungtabellen, wenn die case-Werte "dicht" sind. Das
müsste in deinem Code erkennbar sein, indem zB der Startwert der
Sprungtabelle in ein Register geladen wird, etwas simple Arithmetimk
darauf veranstaltet wird und dann indirekt darüber gesprungen wird.
> Desweiteren habe ich die switch-case durch ein if-else-if ersetzt.> Damit gehtn auch alle meine 7 erfolgreich - auch weil anderer ASM code> erzeugt wird.>>> Welche Gründe gibt es denn hierfür?
Denkbar ist ein Compilerfehler. Um den Fehler nachvollziehbar zu machen
empfiehlt sich ein Testfall, den andere übersetzen können. Hilfreich ist
dann eine möglichst einfache/kurze Quelle zu haben. Leider ist das nicht
immer möglich, wenn Änderungen "hier" einen Fehler "da" bewirken.
PPC-Code ist für mich absolutes Kauderwelsch :-) Die Quelle mit
-save-temps -dp -fverbose-asm zu übersetzen bringt aber lesbare
Kommentare in der .s Datei (evtl. -dP).
Also bei mir siehts so aus:
[c]
switch(actionId)
{
case 0:
foo0();
break;
case 1:
foo1();
break;
case 2:
foo2();
break;
case 3:
foo3();
break;
case 4:
foo4();
break;
case 5:
foo5();
break;
case 6:
foo6();
break;
case 7:
break;
}
[c]
Zwischen Switch und dem ersten case steht natürlich kein Code. Wollte
oben nur hindeuten dass an dieser Stelle der ASM von ganz oben steht.
für den falscher Code erzeugt wird -> Bugreport für gcc erstellen falls
der Fehler nicht schon bekannt ist. Ohne konkreten Code ist da aber
nix zu wollen, also Kommentare wie
1
// irgendein Code
werden vom Compiler wie Kommentare behandelt, es gibt keine Magie, die
deine C-Quelle rät :-)
Hallo Udo,
Welchen Compiler nutzt du überhaupt? Es gibt nunmal für den PPC
haufenweise Compiler. Und ehrlich bezweifle ich dass ein Bug im Compiler
daran schuld ist.
Wie sieht dein Linkerfile aus? Ist das aufgeräumt? Eine Sprungtabelle
für switch anweisungen steht im Normalfall nicht im Stack oder RAM.
Sprünge mit Adrressen aus dem RAM kommen nur bei berechneten Adressen
vor, Also Zugriffen auf (größere) Arrays oder Strukturen. Sonderfall
sind natürlich Rücksprünge aus einer Unterfunktion.
Wenn du einen Debuger zur Verfügung hast, dann schau dir den Stack im
Programmablauf genau an. Wird der Stack überhaupt bis zu der Adresse
gefüllt? Wenn ja wann?
Hast du nur einen Stack oder mehrere? Bei nur einem würde es mich noch
mehr wundern wenn der Compiler eine Sprungadresse aus dem Stack
herauskramt. Vorallem wie in deinem Fall mit einer festkodierten
Arithmetik. Der Stack könnte je nach eingetroffener Interupte völlig
anders aussehen.
Wie gesagt, schau dir dein Linkerfile an. Wenn der Stack
(unbeabsichtigt) beeinflusst wird, ist das nicht lustig man sucht Tage
lang an den falschen Stellen nach Fehlern. Das hab ich erst letzte Woche
durch (war aber kein selbstgeschriebener Code).
Gruß,
TManiac
Ich würde auf einen amoklaufenden Pointer tippen, der den Stack
zerhagelt. Du suchst vermutlich an der falschen Stelle. Aber mangels
konkretem Code lässt sich das nicht verifizieren...
Compiler ist Metrowerks 2.x. Habe zwei verschiedene Versionen probiert,
gleiches Verhalten. Ich denke eigentlich auch nicht dass es der Compiler
ist.
Benutze nur 1 Stack. Im Linkerfile ist dieser auch separat wie alle
andere Sektionen angegeben. Stack liegt als letztes im RAM.
SRAM geht von 0x4000.0000 bis 0x4004.0000.
Stack:
Adress Length
0x4003.0000 0x0000.0FF0
STACK_START = ADDR(Stack)+LEN(Stack)
STACK_END = ADDR(Stack)
Ohje - amoklaufende Pointer. Da swill man nicht wirklich debuggen :-(
Grundsätzlich erstmal die Fragen:
- treten Exceptions auf bzw. werden diese gezielt abgefagen ?
- sind Interrupts aktiviert ? (bei längeren Interruptroutinen
reicht es nicht unbedingt aus die Register 0-12 zu sichern sondern
0-30)
- wird ein Codewarrior defaultprojekt verwendet oder modifizierte
Einstellungen (v.a. Linker file) ? (kann zur Folge haben das Variablen
nicht initialisiert werden, Stichwort: Rom Image bei den Linker
Einstellungen)
Um welches MPC56xx device handelt es sich ?
Evt. mal mit Book-E anstatt VLE compilieren.
- Exceptions treten nachweisbar keine auf. IVxR Register sind
programmiert.
- Interrupts sind an. Das mit den r0..r30 werde ich nachsehen, Danke!
- verwendet wird ein startup vom 55xx , sollte aber gehen. Linker File
ist selbst erstellt. Das alles da das Device sehr neu ist. Ist ein 567x,
mehr sollte ich denke ich nicht veröffentlichen.
BookE werde ich auch mal probieren.