Need idea for io bit field macro

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi all,

Currently I'm using bit field style for I/O and I'm making the definitions of I/O bit field as below.

typedef struct {
	unsigned char	b0:1;
	unsigned char	b1:1;
	unsigned char	b2:1;
	unsigned char	b3:1;
	unsigned char	b4:1;
	unsigned char	b5:1;
	unsigned char	b6:1;
	unsigned char	b7:1;
} bit_field;

typedef union {
	unsigned char	byte;
	bit_field		bit;
} io_reg;

#define	   ioPORTB	 ((volatile io_reg*)&PORTB)->byte
#define		ioPORTB0	((volatile io_reg*)&PORTB)->bit.b0
#define		ioPORTB1	((volatile io_reg*)&PORTB)->bit.b1
#define		ioPORTB2	((volatile io_reg*)&PORTB)->bit.b2
#define		ioPORTB3	((volatile io_reg*)&PORTB)->bit.b3
#define		ioPORTB4	((volatile io_reg*)&PORTB)->bit.b4
#define		ioPORTB5	((volatile io_reg*)&PORTB)->bit.b5
#define		ioPORTB6	((volatile io_reg*)&PORTB)->bit.b6
#define		ioPORTB7	((volatile io_reg*)&PORTB)->bit.b7

#define	   ioPORTC	 ((volatile io_reg*)&PORTC)->byte
#define		ioPORTC0	((volatile io_reg*)&PORTC)->bit.b0
#define		ioPORTC1	((volatile io_reg*)&PORTC)->bit.b1
#define		ioPORTC2	((volatile io_reg*)&PORTC)->bit.b2
#define		ioPORTC3	((volatile io_reg*)&PORTC)->bit.b3
#define		ioPORTC4	((volatile io_reg*)&PORTC)->bit.b4
#define		ioPORTC5	((volatile io_reg*)&PORTC)->bit.b5
#define		ioPORTC6	((volatile io_reg*)&PORTC)->bit.b6
#define		ioPORTC7	((volatile io_reg*)&PORTC)->bit.b7

Usage

ioPORTB  = 0xff;
ioPORTC0 = 1;

But I would like to making some macro that able to fill in a name and address of I/O bit field for instead of above definitions. But same usage.

#define  SOME_MACRO(__NAME,  __ADDR) \
------------------------------------------------------\
------------------------------------------------------\
------------------------------------------------------\
------------------------------------------------------\

SOME_MACRO(ioPORTB, &PORTB);
SOME_MACRO(ioPORTB, &PORTC);

Any someone guide me for achieve this macro ?

Regards,

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But what does such a macro really buy you? As far as I know no AVR has a port above PORTL so the worst case is you have to Ctrl-C/Ctrl-V/Ctrl-H one of those blocks 12 times? You do this once in your life and you have a header file that is good for all time. Just wrap each block in (for example):

#ifdef PORTG
#define      ioPORTG    ((volatile io_reg*)&PORTG)->byte 
#define      ioPORTG0   ((volatile io_reg*)&PORTG)->bit.b0 
#define      ioPORTG1   ((volatile io_reg*)&PORTG)->bit.b1 
#define      ioPORTG2   ((volatile io_reg*)&PORTG)->bit.b2 
#define      ioPORTG3   ((volatile io_reg*)&PORTG)->bit.b3 
#define      ioPORTG4   ((volatile io_reg*)&PORTG)->bit.b4 
#define      ioPORTG5   ((volatile io_reg*)&PORTG)->bit.b5 
#define      ioPORTG6   ((volatile io_reg*)&PORTG)->bit.b6 
#define      ioPORTG7   ((volatile io_reg*)&PORTG)->bit.b7 
#endif

(I just used Ctrl-H and changed PORTB to PORTG in that)

In fact you don't even need the #ifdef - just don't use a "G" entry on an AVR that doesn't have PORTG

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Currently I'm using this idea already.

#ifdef PORTG 
#define      ioPORTG    ((volatile io_reg*)&PORTG)->byte 
#define      ioPORTG0   ((volatile io_reg*)&PORTG)->bit.b0 
#define      ioPORTG1   ((volatile io_reg*)&PORTG)->bit.b1 
#define      ioPORTG2   ((volatile io_reg*)&PORTG)->bit.b2 
#define      ioPORTG3   ((volatile io_reg*)&PORTG)->bit.b3 
#define      ioPORTG4   ((volatile io_reg*)&PORTG)->bit.b4 
#define      ioPORTG5   ((volatile io_reg*)&PORTG)->bit.b5 
#define      ioPORTG6   ((volatile io_reg*)&PORTG)->bit.b6 
#define      ioPORTG7   ((volatile io_reg*)&PORTG)->bit.b7 
#endif 

But I plan for use the macro for more registers not only I/O.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it is not possible to have a single macro generate multiple identifiers.

If your compiler allows for anonymous structures & unions, you could use that feature to create what you want, because the member names will be promoted up in scope to the containing non-anonymous block. [I'm not sure if GCC offers this or not, it is non-standard behaviour]

IAR does this with a chain of macros that essentially create the union in place, with the desired names. The union itself is anonymous, thus the bit fields end up being promoted to the global scope.

#define __BYTEBITS(_NAME,_A,_B,_C,_D,_E,_F,_G,_H) \
unsigned char _NAME ## _ ## _A:1, \
              _NAME ## _ ## _B:1, \
              _NAME ## _ ## _C:1, \
              _NAME ## _ ## _D:1, \
              _NAME ## _ ## _E:1, \
              _NAME ## _ ## _F:1, \
              _NAME ## _ ## _G:1, \
              _NAME ## _ ## _H:1;

#define SFR_B_BITS(_NAME, _ADDR, _A,_B,_C,_D,_E,_F,_G,_H) \
    __io union { \
      unsigned char   _NAME;   /* The sfrb as 1 byte */ \
      struct {                 /* The sfrb as 8 bits */ \
        __BYTEBITS(_NAME, _A,_B,_C,_D,_E,_F,_G,_H) \
      };  \
    } @ _ADDR;

#define SFR_B(_NAME, _ADDR) SFR_B_BITS(_NAME, _ADDR,\ 
                                    Bit0,Bit1,Bit2,Bit3,Bit4,Bit5,Bit6,Bit7)

SFR_B(PINF,   0x00)     /* Input Pins, Port F */

this is from an old version of IAR, the newer versions do it slightly differently.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.