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?:
1 | #define TESTREG (*((volatile unsigned short*) 0xfffee402))
|
2 | volatile unsigned short val; |
3 | int main(void) { val = TESTREG; while(1) {;} return 0;} |
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
So, das hier funktioniert: 37:i2c.c **** CPG.STBCR5.BYTE &= ~0x40; 37 .loc 1 38 0 38 0004 01E00010 movi20 #-131056,r1 39 0008 02E00010 movi20 #-131056,r2 40 000c 32214400 mov.b @(1024,r2),r2 41 0010 632C extu.b r2,r3 42 0012 E2BF mov #-65,r2 43 0014 2239 and r3,r2 44 0016 622C extu.b r2,r2 45 0018 31210400 mov.b r2,@(1024,r1) Wie man sieht liegt es wohl wirklich am verbotenem wordweisen Zugriff. 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.