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

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

Re: [avr-gcc-list] Efficient I/O handling w. bitfields codegen problem


From: E. Weddington
Subject: Re: [avr-gcc-list] Efficient I/O handling w. bitfields codegen problem
Date: Thu, 02 Dec 2004 16:00:21 -0700
User-agent: Mozilla Thunderbird 0.7.3 (Windows/20040803)

Albert Seward wrote:

I have some problems with code generation from GCC 3.3. Read my question
in the main block.

/*
* bitfields.c
*
* GCC bitfields optimization test
*/
typedef union {
       unsigned char byte;
       struct {
               unsigned char pin0 : 1;
               unsigned char pin1 : 1;
               unsigned char pin2 : 1;
               unsigned char pin3 : 1;
               unsigned char pin4 : 1;
               unsigned char pin5 : 1;
               unsigned char pin6 : 1;
               unsigned char pin7 : 1;
       };
} volatile * const port_t;

port_t port[] = {(port_t)0x3d, (port_t)0x38, (port_t)0x35, (port_t)0x32};

// Another way...
struct  {
       port_t portA;
       port_t portB;
       port_t portC;
       port_t portD;
} ports = {(port_t)0x3d, (port_t)0x38, (port_t)0x35, (port_t)0x32};


int main(void) {
       /*  This works!
        *  It will give asm:
        *  cbi     0x18, 7
        */ sbi     0x18, 7
       port[1]->pin7 = 0;
       port[1]->pin7 = 1;

       /*  Why dont I get the same asm as above?
        *  Now I do get this:
        *
        *  lds     r30, 0x0068
        *  lds     r31, 0x0069
        *  ld      r24, Z
        *  andi    r24, 0x7F       ; 127
        *  st      Z, r24
        *
        *  lds     r30, 0x0068
        *  lds     r31, 0x0069
        *  ld      r24, Z
        *  ori     r24, 0x80       ; 128
        *  st      Z, r24
        *
        *  This is not as efficient, and it does not do the job
        *  if I for example want to change GIMSK this way.
        */
       ports.portA->pin7 = 0;
       ports.portA->pin7 = 1;

       for(;;)

       return 0;
}


Hope anyone has the time to help me. I am really stuck.


The canonical way to change bits in ports in C language is not through the use of bitfields. You need to learn to use the C language's bitwise operators, in conjunction with a simple macro include in avr-libc:

#include <avr/io.h>
PORTA |= _BV(1);   // Set bit 1
PORTA &= ~_BV(1);    // Clear bit 1

See this thread on the AVR Freaks website on how to use these operators:
<http://www.avrfreaks.net/phpBB2/viewtopic.php?t=8764&highlight=programming+101>
Go to the post that starts with "Programming 101", which should be highlighted.


reply via email to

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