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-08 by brendanmurphy37
Attachments
- No local attachments were found for this message.