detroitwilly
detroitwilly

Reputation: 821

Building an Array of #define Directives

I have some microcontroller code that uses some header files where GPIO pins are defined like this:

#define PA3 GPIO(GPIO_PORTA, 3)

Using the IDE, I can navigate to the implementation of GPIO and I find this:

#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))

Where pin is defined as:

const uint8_t pin

and port is an enum defined as:

enum gpio_port { GPIO_PORTA, GPIO_PORTB, GPIO_PORTC, GPIO_PORTD, GPIO_PORTE }

I would like to create an array of all the GPIO defins (PA3, PA4, etc.) that can be indexed by an integer passed over a serial port.

I tried the following:

GPIO knavePinList[] = {PA3, PA4, PA21, PB4, PHY_RESET_PIN, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9};

But this obviously doesn't work as GPIO is not a recognized C-type, but in fact a macro. While trying to build, I receive this error message:

unknown type name 'GPIO'

Is it even possible for me to declare an array of macros? If so, how would I note the type for what I'm working with?

Thanks.

Upvotes: 0

Views: 1292

Answers (3)

Luis Colorado
Luis Colorado

Reputation: 12718

The array you post is perfectly legal, I think you have not tested it. Anyway, it is best to ask with a testable example, (see How to create a Minimal, Complete, and Verifiable example) but the code:

GPIO knavePinList[] = {PA3, PA4, PA21, PB4, PHY_RESET_PIN, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9};

will produce a perfectly legally initialized array of integers, with the bitwise values of the constants you have expanded from the macros. Try to use

cpp source.c | more

to see how the array declaration is actually expanded. By the way, you have another, different problem in your code... you are using the same identifier, GPIO, to indicate the GPIO macro name, and the type of the array elements, so when the macro processor encounters it, it sees no parameters, which is not how you have #defined it, and complaints about a two parameter macro GPIO called with no parameters at all.

You have to test your code... and send 1. what you expect... and 2. what you get instead... because the error should be evident, if you had simply stopped to read it.

A solution to your problem is to rename the macro GPIO to GPIO_BITS for example... and then change all the definitions:

#define GPIO_BITS(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))

...

#define PA3 GPIO_BITS(GPIO_PORTA, 3)

so when you encounter the array definition, the type name is not tried to expand as a macro.

Upvotes: 1

John Bode
John Bode

Reputation: 123596

No, you cannot create an array of macros like that.

If you want to execute a particular macro based on an input, you will need to use an if-else or switch statement. If the input is an integer, you could do something like:

switch( input )
{
  case 0: PA3; break;
  case 1: PA4; break;
  case 2: PA21; break;
  ...
 }

Upvotes: 1

rdowell
rdowell

Reputation: 729

#define statements perform text replacement, they have no inherent type. As you noted, GPIO is not a valid type, it's a macro that appears to calculate pin numbers/addresses (actually GPIO is undefined, while GPIO(a,b) is the macro).

If you want to store an array of many of these, then you need to know what actual type they all evaluate to. Given that the GPIO macro returns a sum of a port and a pin value, where port is an enum, whose underlying type is int (technically, it's an implementation specific integral type - see What is the underlying type of a c++ enum?) and pin is a uint8_t, the actual type of your array values would also be an integer type - which one specifically depends on your implementation and the range of possible values.

Upvotes: 2

Related Questions