From: Stuart M. <stu...@st...> - 2007-04-20 20:32:19
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Fabio Giovagnini wrote: > Hi all, > I have found the following problem. > I'm using gcc 3.2.3 hms for sh target; in particular I'm using the c compiler (gcc without g++) and Icompiled 3.2.3 - hms version without any patch. > > On sh2 7145 and 7044 I had no problem; now I'm porting a software on sh2 7085 (7080 family; > http://eu.renesas.com/fmwk.jsp?cnt=sh7080_series_landing.jsp&fp=/products/mpumcu/superh_family/sh7080_series/) and I discovered such a problem: > I have this struct describing the AD converter registers: > struct st_ad0 { /* struct A/D0 */ ... struct contents cut ... > }; /* */ > > > Reading the hw manual you can see ADCSR is a register accessible only as word (16 bit) so the only assembler allowed istruction to access the register is MOV.W; > Obviusly if I write > AD0.ADCSR.WORD |= BIT14 or AD0.ADCSR.WORD &= ~BIT14 > what I read in assembler is correct; > if I write > AD0.ADCSR.BIT.ADIE = 1 or AD0.ADCSR.BIT.ADIE = 0 > in assembler is used a MOV.B instruction being not allowed by the architecture. > > Is this a complier bug? How could I approach the problem? > Obviusly I can avoid the bit field manupulation in the 16 bit access register but I'd like to have a full featured compiler. In general, I'd recommend against using structs like this to manipulate hardware registers. Compilers just don't give enough guarantees about what they will actually do when accessing registers in this way: - the exact layout of the structure isn't defined, and can vary from compiler to compiler - the compiler is at liberty to reorder and optimise your code as it sees fit to try and make it more efficient. volatile helps somewhat in this but even this different compilers can interpret in different ways. - hardware memory barriers are required on some architectures to ensure that operations are performed in the correct order - buffers may need flushing to ensure data has actually left the CPU, and other operations may be required to ensure data has reached the register. This is why systems such as Linux use the readl(), writel() etc macros to access registers, and have all the various memory barrier macros. It also makes the intention of your code much clearer. You know that when a writel() call appears in your code it is touching hardware, while a struct member assignment could be easily confused with updating a software data structure. And when porting your code it makes it much easier to work out what needs changing. Just my twopenny worth. Stuart -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGKSM061BlSKQGbXkRAqmJAJ9kxFEo1zqfuDSOaytv4dJIVK5spQCbBsIJ 6aBoVlOuqwJ5oTOAZ+GWrl0= =tu7l -----END PGP SIGNATURE----- |