avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] port access with avr-gdb


From: David Brown
Subject: Re: [avr-gcc-list] port access with avr-gdb
Date: Thu, 17 Jun 2004 10:34:59 +0200

> On Wed, 16 Jun 2004, Larry Barello wrote:
>
> > I put this header together for the mega8...  I checked out accesses via
a
> > zero pointer and, indeed, the compiler did the right thing for all
accesses:
> > LDS/STS, IN, OUT and SBI/CBI when appropriate.
> >
> > Maybe GCC should consider replacing the archaic #define headers with
> > structs, like this one?  Being able to do direct bit access is pretty
nice
> > (rather than PORTB |= BV(PORTB1);) Or, maybe just adding this struct to
the
> > current headers so either way could be used.
>
> Just for my curiousity, why do you consider the #defines archaic? The
> same concepts are used in Linux kernel headers.
>

#define's are not archaic, but having your computer shout at you in all caps
is archaic - keyboards have had small letters for some years now.  So when
breaking with tradition and using bitfield structs, why not go the whole hog
and use small letters, thus avoiding the conflicts?

For some uses, I like bit-field structs best, while for others, traditional
#define'ed registers are better.  There is no reason why they can't both be
used - keep the standard #define's as they are, and add some structs as well
(I haven't updated my msp430 gcc for a while, but I believe that's how they
do it now).  If seperate structs are defined for much-used registers rather
than attempting to use a huge struct for the whole device, then you avoid
many of the problems described below while getting a number of advantages.
In particular, it means you can write things like

    if (pinc.pin4) portb.pin1 = 1;

rather than the uglier

    if (PINC & _BV(PINC4)) PORTB |= _BV(PB1);

Far better, however, is that it means you can write a header file used by
all modules in your project with something like:

    #define lightSwitch pinc.pin4
    #define lightOn portb.pin1

and then in the main code:

    if (lightSwitch) lightOn = 1;

Changing round pins and ports on new versions of the card is just a matter
of changing a single line in a header.  It is possible to get this using
standard #define'd ports, using a number of macros, but it is not as neat
and the macros are not directly portable between different compilers and
different architectures

On the other hand, I'd hate to have to work with, say, a four-bit databus on
a port if it was only defined as a bitfield...

David



> A few things bother me about your header.
>
> - It's not compatible with the current #defines (e.g. PORTB in your
>   struct gets replaced by the PORTB #define)
>
> - We already have a hard enough time adding headers for new devices (it
>   takes quite a few interations to get all the bugs worked out). Writing
>   structures like these by hand will be virtually impossible to do
>   without bugs. Forget one register and all the following registers will
>   be off by one (or more). That will be a fun bug to track down in a
>   large application. ;-)
>
> - If you were to use this structure to print out the values of all the
>   io registers using a gdb command like this:
>
>     (gdb) print *((struct _avr_regio *)0)
>
>   you could get some nasty side effects. Reading some registers changes
>   the state of the MCU (e.g. reading UDR). There's also no guarantee
>   about what happens when you read/write a reserved register. (I vaguely
>   remember hearing that some reserved registers have secret functionality
>   used by Atmel during testing - I could be quite wrong about this
>   though).
>
> - The order of bit fields in a structure is not defined by the C
>   standard. As such, you are never guaranteed which bit (0 or 7) the
>   first bit field in the structure will be assigned to. This could vary
>   from one compiler to another.
>
> >
> > Cheers!
> >
> > P.S. if attachments are stripped, I'll stick this somewhere public...
> >
> > -----Original Message-----
> > From:  Dave Hylands
> >
> > One way to get the registers to show up symbolically, is to create a
> > structure which has the same layout as the registers. Then you can
access
> > through a null pointer. This would allow you to see the registers in
GDB.
> > They still wouldn't show up I nthe linker map though.
> >
> > There are ways of making them show up in the linker map too. Just create
an
> > asm file which has each of the registers named. On the C side you'd have
> > appropriate externs decalred.
>
> Have you tried 'info io_registers' in gdb when using avarice?
>
> You can set r0-r31 (and anything else that comes up with 'info reg') in
> gdb using 'set var $r10 = EXP'. There's not currently a way to do this
> for io registers, but it might be possible to extend the 'set var'
> method to allow something like 'set var $PORTB = 0xff' in a similar way
> to how we handle the 'info io_registers' command.  This would mean
> making changes to gdb, avarice and possibly simulavr.
>
> One other thing, doesn't the DWARF debugging format allow handling of
> defines in the symbol table? I've been wanting to look into DWARF, but
> just haven't had the time.
>
> I've also used enums instead of #defines to allow getting the values in
> the debugger but it doesn't always work the way you think.
>
> ---
> Ted Roth
> PGP Key ID: 0x18F846E9
> Jabber ID: address@hidden
>
> _______________________________________________
> avr-gcc-list mailing list
> address@hidden
> http://www.avr1.org/mailman/listinfo/avr-gcc-list
>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]