I agree, avoid using bit fields. How bit fields are implemented is
compiler dependent. Granted many (all?) compilers give the option of
signed/unsigned and such, but I'd prefer to avoid that issue entirely.
Plus accessing individual bits can be wasteful as far as code size is
concerned, and flat out may not give the results you want.
Last year I had one piece of code that crashed the system when it ran.
I was setting up the EMC register and GPIO for external RAM by using
bit fields, and the code died a miserable death. After I replaced it
with simple register assignments it worked. I learned my lesson and
ripped out every bit field definition I had. Bit fields are in the
grey area of C/C++ standards and are probably best left out of code.
David
--- In lpc2000@yahoogroups.com, "brendanmurphy37"
<brendan.murphy@i...> wrote:
>
>
> At the risk of adding yet more controversy to what is getting to be a
> somewhat heated discussion, can I suggest that access to hardware
> registers is best done using something like:
>
> 1. Define general MACRO in some hardware-specific include file:
>
> #define REG(addr) (*(volatile unsigned int *)(addr))
>
> 1. Define machine registers in some include file:
>
> /* example is I2C control register */
>
> #define I2C_I2CONSET (0xE001C000) /* ctrl set reg */
>
> 3. Use as follows:
>
> REG(I2C_I2CONSET) = 0x44; /* set I2EN and AA */
>
> As an alternative, you can define extra values as follows:
>
> #define I2C_BIT_AA (0x04)
> #define I2C_BIT_SI (0x08)
> #define I2C_BIT_STO (0x10)
> #define I2C_BIT_STA (0x20)
> #define I2C_BIT_I2EN (0x40)
>
> and use as follows:
>
> REG(I2C_I2CONSET) = I2C_BIT_I2EN | I2C_BIT_AA;
>
> This has the advantage of:
>
> - it always works, regardless of compiler, optimisation settings,
> time of day,....
> - it's easy to follow (or as easy as any other alternative)
> - it's invariably efficiently encoded by the compiler
>
> Contrast this with the number of questions you see on why particular
> bit-field constructs mapped to hardware registers don't work, and it
> might change your mind on how to do this.
>
> Regards
> Brendan Murphy
>
> P.S. On the main topic, I've used GCC on and off for maybe ten years
> now. I find it fine for professional development, PROVIDED someone
> else has set it up for the development system being used (we use
> Ashling for LPC2000 developments, which package it nicely with their
> IDE and ICE). It's not worth the time and effort of doing it
> yourself, unless you're into that sort of thing (maybe you should get
> out more if you are?). We don't use any built-in library functions,
> so library size isn't an issue for us. The reason I like it (apart
> from the cost!) is the lack of bugs in the code generation, unlike
> ither commercial compilers I've used. Reasons for not liking it are
> the usual (limited support, overwhelming documentation etc. etc.).
>
> --- In lpc2000@yahoogroups.com, Sten <list@n...> wrote:
> >
> > Àëåêñàíäð Áîðèñîâ wrote:
> > >>Alex,
> > >>
> > >>
> > >>>b> Just one data point, but: I'm a professional developer (30
> > >>>years s/w
> > >>>b> development experience from micros to mainframes). Now
> working
> > >>>on
> > >>>b> third LPC-based commercial product. Compared Keil, IAR,
> > >>>and gcc and
> > >>>b> chose Rowley Crossworks (gcc-based).
> > >>>
> > >>>Oh, I can't hold out from the reply.
> > >>>I tried to use Crossworks in the begining to explore LPC2xxx.
> > >>>It ugly work with the structures. I tried to define T0MCR like
> > >>> struct:
> > >>>{{
> > >>>typedef struct
> > >>> {
> > >>> __REG32 MR0I :1;
> > >>> __REG32 MR0R :1;
> > >>> __REG32 MR0S :1;
> > >>>
> > >>> __REG32 MR1I :1;
> > >>> __REG32 MR1R :1;
> > >>> __REG32 MR1S :1;
> > >>>
> > >>> __REG32 MR2I :1;
> > >>> __REG32 MR2R :1;
> > >>> __REG32 MR2S :1;
> > >>>
> > >>> __REG32 MR3I :1;
> > >>> __REG32 MR3R :1;
> > >>> __REG32 MR3S :1;
> > >>> __REG32 :4;
> > >>>} __txmcr_bits;
> > >>>
> > >>>#define T0MCRbits (*(volatile __txmcr_bits *)0xE0004014)
> > >>>
> > >>>}}
> > >>>
> > >>>but when I handle to it, Crossworks GCC compile it to this code:
> > >>>
> > >>><<T0MCRbits.MR0I = 1;>>
> > >>>
> > >>>mov r3, #0xE0000000
> > >>>add r3, r3, #0x00004000
> > >>>add r3, r3, #0x00000014
> > >>>ldrb r2, [r3]
> > >>>orr r2, r2, #0x00000001
> > >>>strb r2, [r3]
> > >>>
> > >>>so, I get change in LSB and _in_the_second_byte_!.
> > >>
> > >>And you tell me *why* this is incorrect code generation? You
> might
> > >>not
> > >>like what is generated, but is is *not* incorrect according to the
> > >>standard. It is only incorrect *if* you think volatile has some
> > >>extra
> > >>meaning above what it does in the standard. Or *if* you think an
> > >>"unsigned long" bitfield is somehow "standard". That is why the
> > >>Embedded C TR has I/O support. Volatile does *not* mean "I'm
> > >>dealing
> > >>with a device" or "Access this data atomically". Far from it.
> > >
> > >
> > > I tried to explain my point of view in other mail.
> > > The generated code works incorrectly because it use BYTE
> instructions.
> > > You can compile it, load into the chip and debug. We discuss
> compiler
> > > for ARM core, or what? I think IAR, Keil compilers know about
> data
> > > access in the ARM core.
> > >
> >
> > This behaviour is not bug, it's really a feature. GCC is optimizing
> the
> > accesss to this bit-field to a minimum. Loading and storing only
> _one_
> > byte for modifing only _one_ bit is a very good optimization on
> designs
> > with external memory, which is not 32bit wide, to minimize memory
> access
> > cycles. GCC doesn't know that a certain register _must_ be accessed
> with
> > 32bit (with or without "volatile") and C standard does not say that
> a
> > bit field manipulation is forced to be a 16bit or 32bit access. What
> > should happen, in your opinion, if you declare a bit field with more
> > than 32 bit??? How should it be handled?
> > With other words: Compiler which are using a 32bit access for such
> a bit
> > field manipulation lacks an optimization feature!!!
> >
> > Sten
> >
> > --
> > /************************************************
> > Do you need a tiny and efficient real time
> > operating system (RTOS) with a preemtive
> > multitasking for LPC2000 or AT91SAM7?
> >
> > http://nanortos.net-attack.de/
> >
> > Or some open-source tools and code for LPC2000?
> >
> > http://www.net-attack.de/
> >
> > ************************************************/
> >
>Message
Re: Looking to buy compiler
2005-11-09 by Alan Strickland
Attachments
- No local attachments were found for this message.