Ich habe hier den C-Compiler von Renesas fuer SH. Fuer den liefert
Renesas ein File fuer die Registerdefinitionen der CPUs mit.
Das sieht in etwa so aus:
struct st_iic3 { /* struct IIC3 */
union { /* ICCR1 */
_UBYTE BYTE; /* Byte Access */
struct { /* Bit Access */
_UBYTE ICE:1; /* ICE */
_UBYTE RCVD:1; /* RCVD */
_UBYTE MST:1; /* MST */
_UBYTE TRS:1; /* TRS */
_UBYTE CKS:4; /* CKS */
} BIT; /* */
} ICCR1; /* */
[einiges gekuerzt]
union { /* NF2CYC */
_UBYTE BYTE; /* Byte Access */
struct { /* Bit Access */
_UBYTE :6; /* */
_UBYTE PRS:1; /* PRS */
_UBYTE NF2CYC:1; /* NF2CYC */
} BIT; /* */
} NF2CYC; /* */
}; /* */
#define IIC3_1 ( *(volatile struct st_iic3 *) 0xFFFEE400 ) /* IIC3_1
Address */
Ein Zugriff auf ein Bit ist dann zum Beispiel einfach so moeglich:
IIC3_1.ICCR1.BIT.ICE = 1;
Ich wuerde gerne dieses File auch unter dem gcc nutzen. Der Prozessor
hat eine ganze Menge Register und das File ist 600kbyte gross. Das
schreibt man nicht mal eben so neu.
Es ist auch kein Problem das einzubinden und ich habe damit auch schon
einiges programmiert. Es sollte also funktionieren. Allerdings habe ich
hier auch einen relativ schlichten Programmteil (i2c-bus) der mit dem
Compiler von Renesas funktioniert, mit dem gcc aber nicht.
Daher meine Frage ob soetwas portabel ist, oder ob es sein kann das der
gcc die Reihenfolge der Bits oder anderer Elemente umsortiert?
Olaf
Hi
die Anordnung der Bits in einem Bitfeld ist vom C Standard nicht
vorgeschrieben -> "Implementation defined". Du kannst dich also nicht
darauf verlassen wir der Compiler die Bits anordnet.
Matthias
> Du kannst dich also nicht> darauf verlassen wir der Compiler die Bits anordnet.
Hm..gut, oder auch schlimm.
Allerdings habe ich mittlerweile herausgefunden das auch soetwas
nicht funktioniert:
pointer = (void*) 0xfffee402; //Adress of ICMR_1
vari1 = *pointer;
Ich lese hier ein Register indem laut Datenblatt des Controllers
bestimmte Bits immer 1 sein muessen, aber bekomme trotzdem null raus.
Woran es auch immer liegt, der vom gcc erzeugten Assemblercode sieht
unauffaellig aus, es liegt jedenfalls erstmal nicht an den structs.
Der zugriff ueber structs:
vari1 = IIC3_1.ICMR.BYTE;
fuehrt zum selben falschen Ergebnis. Die structs sind also unschuldig.
Olaf
>...>pointer = (void*) 0xfffee402; //Adress of ICMR_1>vari1 = *pointer;>...
Typ von pointer und vari1? Adresse impliziert
"16-bit"-Zugriffsmöglichkeit. So etwas ausprobiert?:
val sollte so im Debugger "watchbar" sein, zumindest sollte ein
Core-Register den Wert von TESTREG enthalten.
Aktuelle Version der KPIT GNU tools im Einsatz? Falls nicht, könnte sich
ein Update lohnen. Denn wenn richtig erinnert, ist im mitgelieferten GNU
Compiler die Funktionalität von -fstrict-volatile-bitfields enthalten
und per default aktiviert. Damit sind die Aussichten auf Funktion des
"struct/union/Bitfelder über Hardwareregistern"-Ansatzes besser.
> Typ von pointer und vari1? Adresse impliziert> "16-bit"-Zugriffsmöglichkeit. So etwas ausprobiert?
Daran lag es nicht. Das Register ICMR soll zwar immer 0x38 liefern,
aber macht das wohl erst wenn das gesamte I2C-Modul eingeschaltet ist.
Allerdings hatte ich I2C eingeschaltet. Und zwar so:
CPG.STBCR5.BIT.MSTP56 = 0;
Das funktioniert aber nicht. Schalte ich es dagegen so
ein:
pointer = (void*) 0xfffe0410; //STBCR5 Register
*pointer &= ~0x40; //MSTP56 ist Bit6
Dann bekomme ich meine 0x38.
Schaue mir jetzt mal an was der Compiler aus
CPG.STBCR5.BIT.MSTP56 = 0;
macht:
37 .loc 1 37 0
38 0004 02E00010 movi20 #-131056,r2 //0xfffe0010
39 0008 01000400 movi20 #1024,r1 //0x00000400
40 000c 312C add r2,r1 //r1=STBCR5
41 000e 6311 mov.w @r1,r3 //Inhalt holen
42 0010 02F0BFFF movi20 #-16385,r2 //0xbfff ARGH!
43 0014 2239 and r3,r2
44 0016 2121 mov.w r2,@r1
Es sieht also so aus als wenn der Compiler das Register wirklich
an der falschen Stelle im Struct verortet. Oder er macht einen 16Bit
Zugriff obwohl er nur 8Bit darf. Muss ich noch weiter pruefen.
> Aktuelle Version der KPIT GNU tools im Einsatz?
Aber aber, mein gcc stammt aus eigenem Ansatz:
/home/olaf/sources/SH2A/test1: sh2a-gcc --version
sh2a-gcc (GCC) 4.5.1
> val sollte so im Debugger "watchbar" sein, zumindest sollte ein> Core-Register den Wert von TESTREG enthalten.
Waer schoen, dafuer muesste ich aber erstmal den gdb-stub vollstaendig
laufen haben. Soweit bin ich noch nicht.
> ist im mitgelieferten GNU> Compiler die Funktionalität von -fstrict-volatile-bitfields enthalten> und per default aktiviert.
Hm..interessant. Werde ich gleich mal testen ob mein original gcc das
auch kann und ob es das Problem loest.
BTW: Wenn ich mal den Code vergleich den der gcc erzeugt und den der
Renesas compiler erzeugt dann schneidet gcc aber ziemlich schlecht ab.
Ich glaub der gcc erzeugt etwa Faktor 2-3 mehr code. Ausserdem
verschachtelt der Renesas-Compiler Instruktionen von verschiedenen
C-Befehlen lustig ineinander. Das macht zwar das debuggen etwas nervig,
aber ich nehme mal an das macht er nicht ohne Grund. Ich vermute er
sortiert den Code so um damit der Prozessor wirklich zwei Befehle
gleichzeitig ausfuehren kann.
Olaf
Hm..interessant...
Ich nutze auch ein RS232 Modul und schalte das so ein:
CPG.STBCR4.BIT.MSTP44 = 0;
63 .loc 1 66 0
64 000c 02E00010 movi20 #-131056,r2
65 0010 010003FC movi20 #1020,r1
66 0014 312C add r2,r1
67 0016 6311 mov.w @r1,r3
68 0018 02F0EFFF movi20 #-4097,r2
69 001c 2239 and r3,r2
70 001e 2121 mov.w r2,@r1
Das sieht identisch aus zu obigen Problem, aber es funktioniert!
Ich vermute mal das Problem ist der 16Bit-Zugriff auf das Register. Im
Datenblatt steht naemlich nur was von 8Bit-Zugriff. Das geht vielleicht
bei manchen Registern gut und bei manchen nicht.
Allerdings frage ich mich wieso der Compiler auf die Idee kommt 16bit
weise zuzugreifen. Definiert ist das struct naemlich so:
union { /* STBCR5 */
_UBYTE BYTE; /* Byte Access */
struct { /* Bit Access */
_UBYTE MSTP57:1; /* MSTP57 */
_UBYTE MSTP56:1; /* MSTP56 */
_UBYTE MSTP55:1; /* MSTP55 */
_UBYTE :1; /* */
_UBYTE MSTP53:1; /* MSTP53 */
_UBYTE MSTP52:1; /* MSTP52 */
_UBYTE MSTP51:1; /* MSTP51 */
_UBYTE MSTP50:1; /* MSTP50 */
} BIT; /* */
} STBCR5; /* */
_UBYTE wk7[3]; /* */
Olaf
> Denn wenn richtig erinnert, ist im mitgelieferten GNU> Compiler die Funktionalität von -fstrict-volatile-bitfields enthalten> und per default aktiviert.
djdelorie hat mir gerade dasselbe erzaehlt. Dieser switch ist aber erst
im neuen 4.6er enthalten. Das hat man davon wenn man einmal einen total
modernen und voll coolen Controller verwendet. :-)
Da werde ich wohl mal updaten muessen...
Olaf
>Das hat man davon wenn man einmal einen total>modernen und voll coolen Controller verwendet. :-)
... und kein Geld für einen modernen und voll coolen Compiler ausgeben
möchte. Mit falschem Code läuft da nichts :-)
> ... und kein Geld für einen modernen und voll coolen Compiler ausgeben> möchte. Mit falschem Code läuft da nichts :-)
Ich verwende diesen voll coolen Compiler ja auch. Aber leider laeuft der
nicht unter meinem voll coolen Betriebssystemen und das nervt etwas wenn
ich jedesmal um was zu testen erstmal ein voll uncooles Windows booten
muss. .-)
Olaf