1

I have a struct defined in MCU header file

typedef struct tagANSBBITS {
  unsigned ANSB0:1;
  unsigned ANSB1:1;
  unsigned ANSB2:1;
  unsigned ANSB3:1;
  unsigned ANSB4:1;
  unsigned :7;
  unsigned ANSB12:1;
  unsigned ANSB13:1;
  unsigned ANSB14:1;
  unsigned ANSB15:1;
} ANSBBITS;

Only some bits are defined because they are implemented in hw. The problem is I made myself a macro like this

#define  pinMode(pin) pin(_ANS_F)
#define _ANS_F(alpha,bit) (ANS ## alpha ## bits.ANS ## alpha ## bit)

And used like this

pinMode(RED_LED) = 0;

Which obviously fails when corresponding ANSBx is not defined in structure. Can I test somehow for presence of ANSx before using macro? Or convince gcc this is ok?

Thanks in advance,

Noich
  • 14,631
  • 15
  • 62
  • 90
user1973900
  • 381
  • 4
  • 18
  • What exactly would you like to achieve? Sorry, but I am lost now. Why are you doing these macros at all? Can you explain that? – László Papp Aug 18 '13 at 09:42
  • 2
    Macros happen before the compiler even knows your structure exists. Also, your second macro is a [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). – chris Aug 18 '13 at 09:44
  • Was the header provided by the compiler vendor in this form? It's usually not a good idea to try to map C bitfields to hardware registers, because you can't control the order or the read-modify-write behaviour of the generated code. – sh1 Aug 18 '13 at 09:46
  • @Laszlo Papp - trying to use logical RED_LED definition with all hw pins, depending on needs. – user1973900 Aug 18 '13 at 09:50
  • @sh1 - Yes, the header is provided by manufacturer and I was trying to use "as is". A solution perhaps is to use may own, with #define for each existing bits I am interested. – user1973900 Aug 18 '13 at 09:51
  • @sh1 - on this MCU, there are bsf/bcf instructions which guarantees atomicity, this is not a problem in my case. – user1973900 Aug 18 '13 at 09:53
  • Yes, I would suggest a define for each. It is clearer than a complicated and nested macro magic. :) – László Papp Aug 18 '13 at 09:54
  • @sh1: If the vendor is responsible for the HW, the compiler and the headers, then it's probably fine! – Oliver Charlesworth Aug 18 '13 at 10:16

1 Answers1

3

You cannot test for presence or absence of a particular bit in a struct: if compiler sees a reference to a filed that isn't defined, it will complain even if there is no code path to reach that field. However, you can add some "metadata" of your own to make a single macro usable in all contexts:

// This is your "metadata": it defines which fields your struct has
static extern unsigned int unused; // Access of undefined values redirects here
#define ANSB0 ANSBBITS.ANSB0       // ANSB0 and ANSB2 are defined
#define ANSB1 unused               // ANSB1 is not defined
#define ANSB2 ANSBBITS.ANSB2
...                                // Do the remaining bits in the same way

Now you can rewrite your "magic" macro like this:

#define _ANS_F(alpha,bit) (ANS ## alpha ## bit)

For this to compile you need to add a definition for the static unused variable declared at the top of your metadata.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks for answer, so I have to make my own .h slightly modified. Well I don't want to compile anyhow like you suggested. Some pins exists in hardware but have no ANS feature (only digital pins). When I choose this pin, I just want to not compile ANS initialization because it hasn't such feature. So #define existing one seems to be the only option here... – user1973900 Aug 18 '13 at 10:07