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: Ned Konz
Subject: Re: [avr-gcc-list] Bit-wise structure and unions
Date: Wed, 22 Nov 2006 11:31:35 -0800
User-agent: Thunderbird 1.5.0.8 (Macintosh/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.

I made a script that took a chunk of text copied from the Atmel PDFs (before they stupidly made it impossible to copy text from them!) and wrote such definitions.

[ BTW: PLEASE email Atmel and complain about the non-copyability of text in recent datasheet PDFs. This makes their datasheets (and hence processors) less usable. ]

I tried to support both the old-style (bit numbers and shifts) as well as bitfield-style.

That is, you can do these kinds of things (see header code below):

UDR1 = 0xCC;    // assign whole byte register
UDR10 = 1;      // assign a single bit
UBRR1 = 0xFC;   // assign 12 bits at once
UDR1 = _BV(bitUDR10) | _BV(bitUDR11);   // use shifted bit numbers
UDR1 = (1 << bitUDR10) | (1 << bitUDR11); // use shifted bit numbers

Perhaps some of the ideas I used might be useful for you.


I started with a text file that looked something like this (copied from the SFR definitions in the AT90CAN128 PDF file):

(0xCE) UDR1 UDR17 UDR16 UDR15 UDR14 UDR13 UDR12 UDR11 UDR10 page 189
(0xCD) UBRR1H - - - - UBRR111 UBRR110 UBRR19 UBRR18 page 193
(0xCC) UBRR1L UBRR17 UBRR16 UBRR15 UBRR14 UBRR13 UBRR12 UBRR11 UBRR10 page 193
(0xCB) Reserved
(0xCA) UCSR1C - UMSEL1 UPM11 UPM10 USBS1 UCSZ11 UCSZ10 UCPOL1 page 192
(0xC9) UCSR1B RXCIE1 TXCIE1 UDRIE1 RXEN1 TXEN1 UCSZ12 RXB81 TXB81 page 191
(0xC8) UCSR1A RXC1 TXC1 UDRE1 FE1 DOR1 UPE1 U2X1 MPCM1 page 189



Here's a chunk of such a header, showing both 8-bit (UDR1) and 16-bit (UBRR1H/L) usage:

/* UDR1 ($CE) (page 189) */
typedef union UDR1_t {
  uint8_t asByte;
  struct {
    uint8_t bUDR10 :1;
    uint8_t bUDR11 :1;
    uint8_t bUDR12 :1;
    uint8_t bUDR13 :1;
    uint8_t bUDR14 :1;
    uint8_t bUDR15 :1;
    uint8_t bUDR16 :1;
    uint8_t bUDR17 :1;
  } b;
} UDR1_t;
#define UDR1_sfr (*(volatile UDR1_t *) (0xCE))
#define UDR1 UDR1_sfr.asByte /* entire register */
/* single bits */
#define UDR10 UDR1_sfr.b.bUDR10
#define UDR11 UDR1_sfr.b.bUDR11
#define UDR12 UDR1_sfr.b.bUDR12
#define UDR13 UDR1_sfr.b.bUDR13
#define UDR14 UDR1_sfr.b.bUDR14
#define UDR15 UDR1_sfr.b.bUDR15
#define UDR16 UDR1_sfr.b.bUDR16
#define UDR17 UDR1_sfr.b.bUDR17
/* bit numbers */
#define bitUDR10 0
#define bitUDR11 1
#define bitUDR12 2
#define bitUDR13 3
#define bitUDR14 4
#define bitUDR15 5
#define bitUDR16 6
#define bitUDR17 7

/* UBRR1L ($CC) (page 193) */
typedef union UBRR1L_t {
  uint8_t asByte;
  struct {
    uint8_t bUBRR10 :1;
    uint8_t bUBRR11 :1;
    uint8_t bUBRR12 :1;
    uint8_t bUBRR13 :1;
    uint8_t bUBRR14 :1;
    uint8_t bUBRR15 :1;
    uint8_t bUBRR16 :1;
    uint8_t bUBRR17 :1;
  } b;
} UBRR1L_t;
#define UBRR1L_sfr (*(volatile UBRR1L_t *) (0xCC))
#define UBRR1L UBRR1L_sfr.asByte /* entire register */
/* single bits */
#define UBRR10 UBRR1L_sfr.b.bUBRR10
#define UBRR11 UBRR1L_sfr.b.bUBRR11
#define UBRR12 UBRR1L_sfr.b.bUBRR12
#define UBRR13 UBRR1L_sfr.b.bUBRR13
#define UBRR14 UBRR1L_sfr.b.bUBRR14
#define UBRR15 UBRR1L_sfr.b.bUBRR15
#define UBRR16 UBRR1L_sfr.b.bUBRR16
#define UBRR17 UBRR1L_sfr.b.bUBRR17
/* bit numbers */
#define bitUBRR10 0
#define bitUBRR11 1
#define bitUBRR12 2
#define bitUBRR13 3
#define bitUBRR14 4
#define bitUBRR15 5
#define bitUBRR16 6
#define bitUBRR17 7

/* UBRR1H ($CD) (page 193) */
typedef union UBRR1H_t {
  uint8_t asByte;
  struct {
    uint8_t bUBRR18 :1;
    uint8_t bUBRR19 :1;
    uint8_t bUBRR110 :1;
    uint8_t bUBRR111 :1;
    uint8_t bReserved4 :1;
    uint8_t bReserved5 :1;
    uint8_t bReserved6 :1;
    uint8_t bReserved7 :1;
  } b;
  struct {
    uint8_t fUBRR1H :4;
    uint8_t :1; /* Reserved4 */
    uint8_t :1; /* Reserved5 */
    uint8_t :1; /* Reserved6 */
    uint8_t :1; /* Reserved7 */
  } f;
} UBRR1H_t;
#define UBRR1H_sfr (*(volatile UBRR1H_t *) (0xCD))
#define UBRR1H UBRR1H_sfr.asByte /* entire register */
/* single bits */
#define UBRR18 UBRR1H_sfr.b.bUBRR18
#define UBRR19 UBRR1H_sfr.b.bUBRR19
#define UBRR110 UBRR1H_sfr.b.bUBRR110
#define UBRR111 UBRR1H_sfr.b.bUBRR111
/* bit numbers */
#define bitUBRR18 0
#define bitUBRR19 1
#define bitUBRR110 2
#define bitUBRR111 3
/* multi-bit fields */

/* UBRR1 ($CC) (page 193) -- / */
typedef union UBRR1_t {
  uint16_t asWord;
  struct {
    uint16_t bUBRR10 :1;
    uint16_t bUBRR11 :1;
    uint16_t bUBRR12 :1;
    uint16_t bUBRR13 :1;
    uint16_t bUBRR14 :1;
    uint16_t bUBRR15 :1;
    uint16_t bUBRR16 :1;
    uint16_t bUBRR17 :1;
    uint16_t bUBRR18 :1;
    uint16_t bUBRR19 :1;
    uint16_t bUBRR110 :1;
    uint16_t bUBRR111 :1;
    uint16_t bReserved4 :1;
    uint16_t bReserved5 :1;
    uint16_t bReserved6 :1;
    uint16_t bReserved7 :1;
  } b;
  struct {
    uint16_t fUBRR1 :12;
    uint16_t :1; /* Reserved4 */
    uint16_t :1; /* Reserved5 */
    uint16_t :1; /* Reserved6 */
    uint16_t :1; /* Reserved7 */
  } f;
} UBRR1_t;
#define UBRR1_sfr (*(volatile UBRR1_t *) (0xCC))
/* single bits */
/* bit numbers */
/* multi-bit fields */
#define UBRR1 UBRR1_sfr.f.fUBRR1

--
Ned Konz
address@hidden
http://bike-nomad.com




reply via email to

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