Forum: Mikrocontroller und Digitale Elektronik [ASM] PowerPC springt nach 0x0


von Udo (Gast)


Lesenswert?

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?

von TManiac (Gast)


Lesenswert?

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

von Udo (Gast)


Lesenswert?

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.

von Udo (Gast)


Lesenswert?

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.

von Udo (Gast)


Lesenswert?

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?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
int a;
2
void foo (int i)
3
{
4
    switch (i)
5
    {
6
        a = 1;
7
        
8
        case 2:
9
            a = 4;
10
            break;
11
            
12
        case 5:
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).

von Udo (Gast)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ok. Dein compilierbarer Testfall ist also
1
void foo0();
2
void foo1();
3
void foo2();
4
void foo3();
5
void foo4();
6
void foo5();
7
void foo6();
8
9
void test (int actionId)
10
{
11
  switch (actionId)
12
  {
13
    case 0:  foo0();  break;
14
    case 1:  foo1();  break;
15
    case 2:  foo2();  break;
16
    case 3:  foo3();  break;
17
    case 4:  foo4();  break;
18
    case 5:  foo5();  break;
19
    case 6:  foo6();  break;
20
    case 7:
21
       break;
22
  }
23
}

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 :-)

von TManiac (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

von Udo (Gast)


Lesenswert?

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 :-(

von Karl M. (movex)


Lesenswert?

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.

von Udo (Gast)


Lesenswert?

- 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.

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.