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

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

Re: [avr-gcc-list] Bit-wise structure and unions


From: David Brown
Subject: Re: [avr-gcc-list] Bit-wise structure and unions
Date: Wed, 22 Nov 2006 09:44:14 +0100
User-agent: Thunderbird 1.5.0.8 (Windows/20061025)

Keith Gudger wrote:
Below is a program which illustrates the following issue:

When using AVR ports, I would like to define them with bit-wise
structures.  This way I can easily access individual bits (or groups of
bits).  e.g.:

typedef struct port_reg {
        unsigned bit0:1   ;
        unsigned bit1:1   ;
        unsigned unused:6 ;
} PORT_REG;

However, I cannot assign the 8 bit port value directly to a structure
defined this way.  Here is the code and the gcc error:

    PORT_REG *pLED_DIR = (PORT_REG *)0x37 ; ///< LED Port DIR REG PORT B
    *pLED_DIR = (PORT_REG) 0x03 ;

main.c:27: error: conversion to non-scalar type requested

I can fix this problem by introducing a union:

typedef union {
    PORT_REG port_bits ;
    uint8_t  byte ;
} PORT_UNION ;

   PORT_UNION *pLED_DIR = (PORT_UNION *)0x37 ; ///< LED Port DIR REG PORT B
   PORT_UNION *pLED_OUT = (PORT_UNION *)0x38 ; ///< LED Port Output PORT B
   pLED_DIR->byte = 0x3 ;

But I would rather not have the union.  Is there any other way around
this?  Thanks.

Keith


Gcc supports anonymous unions as an extension, which can be used unless you have specified stricter standards compliance (i.e., it works with -std=gcc99, but not -std=c99):

typedef union {
        struct {
                unsigned bit0:1   ;
                unsigned bit1:1   ;
                unsigned unused:6 ;
        };
        unsigned char raw;
} PORT_REG;


PORT_REG *pLED_DIR = (PORT_REG *)0x37 ; ///< LED Port DIR REG PORT B

void foo(void) {
        pLED_DIR->raw = 0x03 ;
}

void bar(void) {
        pLED_DIR->bit1 = 1;
}


You want to make sure you don't have any name conflicts between the union parts.

Of course, your generated code will be very much more efficient if you use the port address directly (named in a macro), rather than via a pointer.



#define LED_DIR (*(PORT_REG *)0x37)

void foo2(void) {
        LED_DIR.raw = 0x03 ;
}

void bar2(void) {
        LED_DIR.bit1 = 1;
}



mvh.,

David




reply via email to

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