Forum: Mikrocontroller und Digitale Elektronik 16-Bit-Wert: falscher Speicherzugriff


von Günter N. (turtle64)


Lesenswert?

Hallo,

ich habe eine 16-Bit-Variable, die zufällig
an der Adresse 0x01FF/0x0200, also an einer
Seitengrenze liegt. Wenn ich diese Variable
dekrementiere, wird 0x01FF dekrementiert.
Bei einem Underflow des Low Byte (256 => 255)
wird aber nicht 0x0200, sondern
0x0100 mit dekrementiert.

Ist das ein Bug im Compiler?

Wie bekomme ich den Compiler dazu, 16-Bit-Variablen
an gerade Adressen zu legen? Habe keine Direktive
dazu gefunden.

Oder ist das gar ein Problem des Controllers?

Ich habe mir erst mal mit einer 8-Bit-Dummy-Variablen
geholfen, die den 16-Bit-Wert auf eine gerade
Adresse schiebt. Geht, aber jetzt muss ich jedes Mal
die Symboltabelle durchsehen, ob dieser Fall wieder
aufgetreten ist...

Compiler: PCWH V3.215 (!)

Controller: PIC18C252

von Joachim (Gast)


Lesenswert?

Ich habe bislang noch keinen Compiler gesehen, bei dem man nicht 
einstellen kann, dass eine 16-Bit-Variable auf einer geraden Adresse 
anfängt.

Das ist auch sinnvoll, weil sonst meistens mehrere Assemblerbefehle 
notwendig sind um die Variable zu dekrementieren.

Also such einfach nochmal bei Deinem Compiler nach dieser Einstellung.

von Günter N. (turtle64)


Lesenswert?

tja, ich denke auch, dass es so eine Option geben müßte.
Aber trotz intensiver Suche und Internetrecherche habe
ich nichts Passendes gefunden.

Kann mir bitte jemand einen Tip geben, wie ich den Compiler
dazu zwingen kann, 16-Bit-Variablen an gerade Adressen
zu legen?

von Peter D. (peda)


Lesenswert?

Joachim schrieb:
> Ich habe bislang noch keinen Compiler gesehen, bei dem man nicht
> einstellen kann, dass eine 16-Bit-Variable auf einer geraden Adresse
> anfängt.
>
> Das ist auch sinnvoll, weil sonst meistens mehrere Assemblerbefehle
> notwendig sind um die Variable zu dekrementieren.

Das ist Quatsch, der 8-Bitter braucht in jedem Fall 2 einzelne Zugriffe 
für ne 16-Bit Variable.
Bei 8-Bittern ist daher die Plazierung von Variablen nur an geraden 
Adressen oft nicht vorgesehen.

Ob das ein Compilerbug oder ein Hardwarebug ist, muß man sich mal im 
Assemblerlisting ansehen.

Oder die Errata lesen. Der PIC18C252 ist ja eh nicht mehr für 
Neuentwicklungen empfohlen (Status: Mature Product) und durch den 
PIC18F2520 abgelöst.


Peter

von JL (Gast)


Lesenswert?

alternativ sollte es möglich sein alle 16bit Variablen in ein eigenes 
Segment zu legen. Damit kann sich kein Byte mehr dazwischenschmuggeln.

Kenn zwar den PIC und den Compiler nicht aber so lassen sich genutzte 
Variablen strukturiert ablegen. Bedeutet aber auch vor der Deklaration 
der Variable den entsprechenden Compilerschalter zu setzen und wieder 
zurückzunehmen.

Bsp von meinem S12X:
    #pragma DATA_SEG RAM_ZERO_WORD
        unsigned int xyz;
    #pragma DATA_SEG default


JL

von Peter D. (peda)


Lesenswert?

JL schrieb:
> alternativ sollte es möglich sein alle 16bit Variablen in ein eigenes
> Segment zu legen. Damit kann sich kein Byte mehr dazwischenschmuggeln.
...
> Bsp von meinem S12X:

Du weißt aber schon, daß der S12X im Gegensatz zum PIC ein 16-Bitter 
ist?


Peter

von Günter N. (turtle64)


Lesenswert?

Ok, also hier das Listing der fraglichen Stelle:

....................     int16 *pulTimer ;  // Temporary pointer to 
timer element.

....................   (*pulTimer)-- ;
0CA0:  MOVFF  30C,03
0CA4:  MOVFF  30B,FE9
0CA8:  MOVFF  30C,FEA
0CAC:  MOVLW  FF
0CAE:  ADDWF  FEF,F
0CB0:  BC    0CB6
0CB2:  INCF   FE9,F
0CB4:  DECF   FED,F

Wenn der Pointer auf 0x01FF zeigt, geht das Dekrementieren
bei den oberen 8 Bit schief, es geht dann auf die Adresse 0x0100.
Bei jeder geraden Adresse und bei Adressen, die nicht am
Ende eines 256-Byte-Blocks liegen, geht es.

Ich kenne den Assembler-Code dieses Prozessors nicht und bitte
um Info, ob der Fehler schon im Code steckt oder ob der
Microcontroller etwas falsch macht.

von (prx) A. K. (prx)


Lesenswert?

Günter Nowinski schrieb:

> 0CA4:  MOVFF  30B,FE9

ptr(lo) = ...

> 0CA8:  MOVFF  30C,FEA

ptr(hi) = ...

> 0CAC:  MOVLW  FF

W = -1

> 0CAE:  ADDWF  FEF,F

*ptr += W

> 0CB0:  BC    0CB6

if (!carry)

> 0CB2:  INCF   FE9,F

   ptr(lo) += 1

> 0CB4:  DECF   FED,F

   *ptr-- -= 1

Könnte ein Compilerbug sein. Könnte aber auch sein, dass der Zugriff auf 
eine ungerade Adresse eines 16bit Werts beim Compiler als unzulässig 
definiert ist.

von Günter N. (turtle64)


Lesenswert?

Danke, dann muss ich wohl die Variablen von Hand plazieren.

Ich habe die gleiche Frage auch im Forum des Compiler-Herstellers
gepostet. Dort wurde geantwortet, dass es außer
#locate (variable) (adresse)
keine Möglichkeit gibt, Variablen an bestimmte Positionen
zu legen.
Es handelt sich wohl um einen Compiler-Fehler, der Operationen
am Ende von 256-Byte-Blöcken betrifft.

Irgendwie macht mir das etwas Angst. Schließlich habe ich den
Fehler erst nach mehreren Jahren Arbeit mit diesem Controller
bemerkt. Wo der sonst noch überall so drinsteckt...

von Peter D. (peda)


Lesenswert?

A. K. schrieb:

>> 0CB0:  BC    0CB6
>
> if (!carry)
>
>> 0CB2:  INCF   FE9,F ;<- Fehler, richtig: MOVF FEE (increment data pointer 0)
>
>    ptr(lo) += 1
>
>> 0CB4:  DECF   FED,F
>
>    *ptr-- -= 1
>

Jau, das ist ein astreiner Compilerfehler.

Daß beim PIC zusätzliche Befehle als Memory-Zugriffe getarnt werden, ist 
aber schon ziemlich strange.


Peter

von JL (Gast)


Lesenswert?

> Du weißt aber schon, daß der S12X im Gegensatz zum PIC ein 16-Bitter
> ist?

ja ist mir klar, mir ging es nur um die Möglichkeit dem Linker Segmente 
vorzugeben in die die Variablen gelegt werden. Wenn dann alle 16bit 
Variablen ab einer geraden Adresse gelinkt werden kann dein Problem 
nicht mehr vorkommen.

Das gleiche gilt dann auch für long, die auf 4byte allign gelinkt werden 
sollten.


JL

von JL (Gast)


Lesenswert?

such mal nach
#TYPE in der Dokumentation

dort kannst du beeinflussen wohin deine Variablen gelinkt werden.

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.