mikrocontroller.net

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


Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
..
....
lwzx     r3,r3,r0  ; schreibe 0 nach r3
se_mtctr r3        ; schreibe r3 nach CTR (Count Register)
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:
                    ; r0 = 0x0003A360
                    ; r1 = 0x40003E2F
se_lhz r0,0x10(r1)   ; nach diesem Schritt ist r0 gleich 0
se_cmpli r0,0x8
se_bgt 0x37A1E
e_lis r8,0x40000000
e_add16i r3,r8,0x1CD8
se_slwi r0,0x2
lwzx     r3,r3,r0  ; schreibe 0 nach r3
se_mtctr r3        ; schreibe r3 nach CTR (Count Register)
se_bctr            ; branch zu CTR


Ich verstehe hier nicht, wass der ASM mit
se_lhz r0,0x10(r1)
macht. Was bedeutet diese Zeile?

Autor: TManiac (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
int a;
void foo (int i)
{
    switch (i)
    {
        a = 1;
        
        case 2:
            a = 4;
            break;
            
        case 5:
            a = 7;
            break;
    }
}

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

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok. Dein compilierbarer Testfall ist also
void foo0();
void foo1();
void foo2();
void foo3();
void foo4();
void foo5();
void foo6();

void test (int actionId)
{
  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;
  }
}

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
// irgendein Code
werden vom Compiler wie Kommentare behandelt, es gibt keine Magie, die 
deine C-Quelle rät :-)

Autor: TManiac (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-(

Autor: Karl M. (movex)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Udo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.