Check for concatenated define in C preprocessor - c

I access registers by concatenated defines unsing the function GETREG
#define NUMBER 1 //changes
#define REG1 register.N1
#define REG2 register.N2
#define REG8 register.N8
#define GETREG_(N) REG ## N
#define GETREG(N) GETREG_(N)
Sometimes the registers for that NUMBER are not defined so i want to make sure the macro correctly expands before inserting it in the code so i tried to do:
#define NUMBER 5
#ifdef GETREG(NUMBER)
GETREG(NUMBER) = 0
#endif
However this always seems to evaluate as true and the compiler prints
Warning:extra tokens at end of #ifdef directive
Background Story:
In my projects I create libraries to interface with a HAL to abstract the hardware level. Often from one project to another the codebasis in the HAL stays exactly the same but just the location of pins changes. For that reason i would like to use macro-expansion to access the pins. The following macro does the job for me at adressing the analog features of the pin:
#define ANSEL_(Pin) _ANS ## Pin
#define ANSEL(...) ANSEL_(__VA_ARGS__)
that way i can turn on or off analog features by:
#define PIN_RX A0
ANSEL(PIN_RX)= 0;
and other registers by similar macros. The problem i am facing now is that some pins for example do not have analog features (e.g. Pin A5). Because of that i would like to test if the define in the library esists. I was tryin to do this by:
#ifdef ANSEL(PIN_RX)
ANSEL(PIN_RX)= 0;
#endif
However this simple approach is not working.
The microcontroller (PIC33) lib:
Edit: Shipped from the manufactorer
#define ANSELA ANSELA
extern volatile unsigned int ANSELA __attribute__((__sfr__));
typedef struct tagANSELABITS {
unsigned ANSA0:1;
unsigned ANSA1:1;
unsigned ANSA2:1;
unsigned ANSA3:1;
unsigned ANSA4:1;
unsigned :4;
unsigned ANSA9:1;
} ANSELABITS;
extern volatile ANSELABITS ANSELAbits __attribute__((__sfr__));
/* ANSELA */
#define _ANSA0 ANSELAbits.ANSA0
#define _ANSA1 ANSELAbits.ANSA1
#define _ANSA2 ANSELAbits.ANSA2
#define _ANSA3 ANSELAbits.ANSA3
#define _ANSA4 ANSELAbits.ANSA4
#define _ANSA9 ANSELAbits.ANSA9

You have the wrong expectation for the behavior of the #ifdef directive. That directive is equivalent to #if defined, where defined is a preprocessing operator in that context. Although the condition of an overall #if directive is evaluated only after the line is fully macro-expanded, the defined operator operates on the next preprocessing token, which must have the form of an identifier, before macro expansion:
Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator) [...]
[C2011, 6.10.1/4]
Thus, your
#ifdef GETREG(NUMBER)
tests whether GETREG is a defined macro, and the (NUMBER) constitutes a sequence of unexpected extra tokens.
The defined operator therefore cannot serve your purpose. It is conceivable that there is a way to use a more general #if directive to achieve your aim, but I'm not seeing it at the moment. Instead, I'm inclined to suggest letting the compiler find such errors for you, instead of expecting the preprocessor to do it. If compile time is too late, then perhaps you need to look to a build configuration system such as the Autotools or CMake could help you create.

You can do more or less what you want if you are prepared to use two #defines instead of one for each pin:
#define HAS_ANS_A0 1
#define ANS_A0 ANSELAbits.ANSA0
#define HAS_ANS_A1 1
#define ANS_A1 ANSELAbits.ANSA1
#define HAS_ANS_A5 1
#define ANS_A5 ANSELAbits.ANSA5
#define HAS_ANSEL_(Pin) HAS_ANS_ ## Pin
#define HAS_ANSEL(...) HAS_ANSEL_(__VA_ARGS__)
#define ANSEL_(Pin) ANS_ ## Pin
#define ANSEL(...) ANSEL_(__VA_ARGS__)
#if HAS_ANSEL(PIN_RX)
ANSEL(PIN_RX)= 0;
#endif
This works because in an #if, an undefined identifier token (that is, an identifier token which has not been #defined) has the value 0. It is not an error, or even a warning.
Note: I changed the symbols starting _ANS to conform with ยง7.1.3 (Reserved Names), paragraph 1:
All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

Related

Can a preprocessor function be used to define multiple preprocessor macros?

Is it possible to create a preprocessor function that will cause multiple other preoprocessor macros to be defined?
I'm working in a micro controller framework that requires a few macros to be made in order for a generic interrupt handler to function:
<MODULE_NAME>_IRQ_PIN //ex: PORTB_PIN(0)
<MODULE_NAME>_IRQ_IN_REGISTER //ex: GPIO_PBIN
<MODULE_NAME>_IRQ_NUMBER //ex: GPIO_IRQA
<MODULE_NAME>_IRQ_INTCFG_REG //ex: GPIO_INTCFGA
I am trying to make this process more generic and easier from an implementation standpoint. There are about ten of these macros that need to be defined, but their definitions can all be derived when given 1) the port name 2) the pin number and 3) the IRQ name. I am hoping then to create a pre-processor function that will result in the generation of all of these macros. Something like:
#define MAKE_INTERRUPT_MACROS(module, port, pin, irq_num) \
#define module##_IRQ_pin PORT##port##_PIN(##pin##) \
#define module##_IRQ_IN_REGISTER GPIO_P##port##IN \
#define module##_IRQ_NUMBER GPIO_IRQ##irq_num \
#define module##_IRQ_INTCFG_REG GPIO_INTCFG##irq_num
Is there a legal way to get the proprocessor to do something like the above, where a single preprocessor function causes the generation of multiple other macros based on the parameters passed to the function?
I think this classical scheme may solve your problem. This is a simple and clear way:
#ifdef CPU_X
#define IRQ_PIN 0
#define IRQ_IN_REGISTER 3
#define IRQ_NUMBER 11
#define IRQ_INTCFG_REG 12
#endif
#ifdef CPU_YY
#define IRQ_PIN PORTB_PIN(1)
#define IRQ_IN_REGISTER GPIO_PBIN(6)
#define IRQ_NUMBER GPIO_IRQA(9)
#define IRQ_INTCFG_REG GPIO_INTCFGA(0xA)
#endif
#ifdef CPU_KK
/* .
. Another CPU
.
*/
#endif
#ifdef CPU_K2
/* .
. Another CPU
.
*/
#endif
You may compile the code specifying the CPU using -D CPU_xx and the problem shoudl be solved!
I assume you might have some other macros (E.G.: GPIO_IRQA(9)), and in CPU_YY I've used it, but It might be used also for the other CPUs.
If you can use C++ rather than C, look at using classes, one per CPU type, and simply use constants and interfaces in the class. Then, you don't even care that they are different, simply use the same names to access them (the differentiation is done based upon the class being instantiated.
If you really and truly must use C (such as writing a device driver), you can use the approach device driver writers use (all flavors of *nix, VxWorks, PSOS, QNX, and most of the old DEC OSs use this approach, don't know about Windows): Simply build a structure containing the values and any functions you may need to manipulate the hardware (or anything else, for that matter). Create one instance of this structure per hardware (or in your case, module) type. Then indirect through the structure.
Example:
struct module_wrapper {
const char *module_name;
int irq_pin;
int irq_register;
int irq_number;
int irq_intcfg_reg;
int (*init_fcn)(void);
int (*reg_access)(int register_number);
int (*open)(void);
int (*close)(void);
int (*read)(char *dst_buffer, int len);
int (*write)(const char *src_buffer, int len);
};
module_wrapper portB = { /* initialize here */ };
module_wrapper gpio = { /* initialize here */ };
printf("GPIO pin %d\n", gpio.irq_pin);
Obviously, modify as desired. You can also replace the constant variables with functions that return the values.
You can't define other macros with a macro, but you achieve something similar by doing it kind of in a totally opposite way.
You could autogenerate a file which has the following block for each possible module:
#ifdef <MODULE>_IRQ_DATA
#define <MODULE>_IRQ_pin CALL(GET_IRQ_PIN, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_IN_REGISTER CALL(GET_IRQ_IN_REGISTER, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_NUMBER CALL(GET_IRQ_NUMBER, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_INTCFG_REG CALL(GET_IRQ_INTCFG_REG, <MODULE>_IRQ_DATA)
#endif
And then have:
#define CALL(MACRO, ...) MACRO(__VA_ARGS__)
#define GET_IRQ_PIN(port, pin, irq_num) PORT##port##_PIN(pin)
#define GET_IRQ_IN_REGISTER(port, pin, irq_num) GPIO_P##port##IN
#define GET_IRQ_NUMBER(port, pin, irq_num) GPIO_IRQ##irq_num
#define GET_IRQ_INTCFG_REG(port, pin, irq_num) GPIO_INTCFG##irq_num
(Depending on how the defines are used, you can possibly get rid of the #ifdef-#endif -pairs, eg. if all of them must/can always be defined)
Then actually defining the needed values could be done with just:
#define <MODULE>_IRQ_DATA B,0,A

Any workaround to self-referential macros in C? I'd like to append to a macro

I have a file that uses a FLAGS macro from an include that I do not control. What is in FLAGS is not consistent. Occasionally I need to change FLAGS to add a flag to it. Now I know I can't do #define FLAGS FLAGS|MY_FLAG, but I thought if I stored FLAGS in a temporary variable that I could then undefine it and redefine it using the temporary and my flag. For example:
// Assume this next line is what's in the include file
#define FLAGS (1|2|4)
// The rest of this is source, assume compile with -DMOD
#ifdef MOD
#define TEMP (FLAGS|8)
#undef FLAGS
#define FLAGS TEMP
#endif
int main()
{
printf("0x%x\n", FLAGS);
}
And if MOD is defined the error is error: 'FLAGS' was not declared in this scope. I know that I can change all the actual C code that uses FLAGS to instead use FLAGS|MY_FLAG but I was hoping to modify the macro rather than all the code.
Your only real way to do exactly what you are trying to do is to define an additional macro
// Assume this next line is what's in the include file
#define FLAGS_FOR_A (1|2|4)
#define FLAGS FLAGS_FOR_A
// The rest of this is source, assume compile with -DMOD
#ifdef MOD
#undef FLAGS
#define FLAGS ( FLAGS_FOR_A | 8 )
#endif
int main()
{
printf("0x%x\n", FLAGS);
}
Macros just do simple text replacement, computed before runtime
You can do something logically equivalent to #define FLAGS FLAGS|MY_FLAG if you define the macro as modifiable using Boost's "evaluated slots":
#include <boost/preprocessor/slot/slot.hpp>
// define FLAGS as a modifiable macro and create a setter for it
#define FLAGS BOOST_PP_SLOT(1)
#define UPDATE_FLAGS BOOST_PP_ASSIGN_SLOT(1)
int main(void) {
// set the initial value of FLAGS
#define BOOST_PP_VALUE (1|2|4)
#include UPDATE_FLAGS
printf("0x%x\n", FLAGS); // 0x7
// update FLAGS with a new value using the old one
#define BOOST_PP_VALUE (FLAGS|8)
#include UPDATE_FLAGS
printf("0x%x\n", FLAGS); // 0xf
}
Despite being witchcraft, this is completely standard-compliant C, no extensions. Only works for integers.
(It works by taking advantage of something important: macros aren't just expanded into program code, but also need to be expanded to determine whether to follow an #if branch as well. Since #if directives are also capable of evaluating integer math, this is able to expand the actual numeric value and use it to construct a new expansion for the PP_SLOT that doesn't involve a reference to any macro name. This is all hidden behind the #include UPDATE_FLAGS directives.)

Macro as a parameter to another macro

I'm trying to pass the parameters to macro SETBIT with another predefined macro like this:
#define SETBIT(ADDRESS,BIT,N) {(N) ? (ADDRESS &= ~(1<<BIT)) : (ADDRESS |= (1<<BIT))}
#define DAC_SYNC PORTB,3,POS
SETBIT(DAC_SYNC);
However I receiver error:
macro SETBIT requires 3 parameters only 1 given
There is an article with the following recommendations:
to prevent misnesting of arithmetic operations: #define foo (a,b) or #define bar(x) lose((x))
But even though I still have an error. BTW, reading the article I've indicated I can make the following conclusion: preprocessor expands ALL macroses appearing. But actually it looks like macro #define DAC_SYNC PORTB,3,POS is not expanding by preprocessor.
Could anyone make more clear how the GCC's preprocessor works?
This works:
#define SETBIT2(ADDRESS,BIT,N) ((N) ? (ADDRESS &= ~(1<<BIT)) : (ADDRESS |= (1<<BIT)))
#define SETBIT(PARAMS) SETBIT2(PARAMS)
#define PORTB 5
#define POS 7
#define DAC_SYNC PORTB,3,POS
int main() {
int a = SETBIT(DAC_SYNC);
return 0;
}
Just for the sake of completeness, that same manual you are linking to also states:
The number of arguments you give must match the number of
parameters in the macro definition. When the macro is expanded, each
use of a parameter in its body is replaced by the tokens of the
corresponding argument.
So ooga's example is a nice demonstration of how macro expansion works recursively, first the outer macro gets expanded, then the argument.

C-Macros produces unexpected behavior

I'm trying to make my header file easily changeable with macros. I'm debugging my code and it seems these MACROS are not doing what they are supposed to. Can someone tell me how I achieve the following effect? LED_ID_AMS etc.
#define LED_NUMBER (2)
#define LED_ID_X (0)
#define LED_ID_Y (1)
#define LED_PIN_X (0)
#define LED_PIN_Y (3)
#define LED_PORT_X (PORTE)
#define LED_PORT_Y (PORTG)
#define LED_DD_X (DDRE)
#define LED_DD_Y (DDRG)
#define LED_PORT(LED_ID_X) (LED_PORT_X)
#define LED_PORT(LED_ID_Y) (LED_PORT_Y)
#define LED_PIN(LED_ID_X) (LED_PIN_X)
#define LED_PIN(LED_ID_Y) (LED_PIN_Y)
#define LED_DD(LED_ID_X) (LED_DD_X)
#define LED_DD(LED_ID_Y) (LED_DD_Y)
What am I trying to achieve?
I'm trying to make it so I can loop through the port init like so:
for(i=0;i<LED_NUMBER;i++){
/* set data direction to output*/
LED_DD(i)|=((0x01)<<LED_PIN(i));
/* turn on led */
LED_PORT(i)|=((0x01)<<LED_PIN(i));
}
You will regret using too many macros later. Actually, you're regretting it already, as they don't work and, being macros, they are very difficult to debug.
Just a few points:
your LED_PIN(i) expressions are always expanding to 0
your LED_PORT(i) expressions are always expanding to PORTE whatever that may be
For instance LED_PIN(LED_ID_X) expands to LED_PIN_X. Note, macro parameter LED_ID_X is not used at all. Instead, LED_PIN_X simply expands to 0.
This should scream warnings at you, as e.g. LED_PORT(SOME_ARG) has several definitions. And in LED_PORT(LED_ID_X) the LED_ID_X is just a dummy argument, with absolutely no relation to your constant LED_ID_X.
You can make your code equally readable by using a constant array, perhaps used from macros like you try to do here.
Unless there are a massive number of LED_ID_<foo>, this is at best a minor simplification. Don't do that. If there is a lot of code futzing around with those is mostly the same way, it might make sense to define a macro that iterates some action over each of them, i.e.:
#define FROB_LEDS \\
action(LED_ID_X); \\
action(LED_ID_Y); \\
action(LED_ID_Z);
and define action(X) locally as a macro to do the action on LED X, FROB them, and undefine action again. Quite ugly, true.
You'll have to add at least one of:
arrays
inline functions
more complicated macros
And it also seems to me that dereferencing of hardware addresses will be required.
For example, using macros, you can define:
#define LED_PORT(i) *(uint16_t *)( \
(i) == LED_ID_X ? LED_PORT_X : \
(i) == LED_ID_Y ? LED_PORT_Y : \
etc)
where:
#define LED_ID_X (0)
#define LED_ID_Y (1)
#define LED_PORT_X (PORTE)
#define LED_PORT_Y (PORTG)
#define PORTE (0x11112222U) // example only
#define PORTG (0x33334444U) // example only
Here uint16_t is only a guess: I'm assuming 16-bit ports in a 32-bit address space.
Or, using arrays and C99's designated initializers:
const uint32_t LED_PORT[] = {
[LED_ID_X] = LED_PORT_X,
[LED_ID_Y] = LED_PORT_Y
};
#define LED_PORT(i) (*(uint16_t *)LED_PORT[i])
And of course, without C99 you can use just:
const uint32_t LED_PORT[] = {LED_PORT_X, LED_PORT_Y};
which assumes that LED_ID_X is 0, etc.

Is there a way to control macro expansion order

I am hoping that someone may have an idea on how to control/specify the order of macro expansion. Here is the context:
// 32 bit increments, processor has registers for set, clear and invert
#define CLR_OFF 1
#define SET_OFF 2
#define INV_OFF 3
#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits
//Now if I use this I can do it quite nicely with
#define STATUS_LED 0x0040;
SET(LATB, STATUS_LED); // LATB is port of the LED.
I've actually had to move hardware around quite a bit as of late so I decided to group the LATB info with the STATUS_LED like so...
#define STATUS_LED_PORT LATB
#define STATUS_LED_MASK 0x0040;
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK
//And I try to use it via
SET( STATUS_LED );
But alas, LATB,0x0040 is passed to argument 1 of the SET macro. When not used as a macro this method works properly:
inline void SET(u32_t *reg, u32_t bits) { ((volatile u32_t *) (((u32_t)reg) + SET_OFF*4 )) = bits; }
//Change the STATUS_LED macro to
#define STATUS_LED &STATUS_LED_PORT, STATUS_LED_MASK
SET( STATUS_LED); //Works great!
But unfortunately my compiler doesn't see the need to inline the function and causes 6 instructions to set the register as opposed to 4, so for use while bit-banging it is unpredictable.
I am hoping someone may know of a way to expand the STATUS_LED macro first, something like:
SET( ##STATUS_LED )
Currently my solution to move on is to have two macros SET, and SETRM (set register, mask) but I feel like there should be a solution because the code for SET looks like...
#define SETRM(reg,bits) ...
#define SET(args) SETRM(args) //WHY WOULD THIS GET EXPANDED HERE??
And lastly, my processor's compiler does not support n-arguments to a macro, I thought I might be able to play with that but alas :(.
Thank you very much for your time, and I would appreciate any thoughts, I can move forward, but it would be so much cleaner if I could just use SET everywhere.
Substitution of parameters in the expansion of function-like macros happens in a set way. All arguments which don't appear after the # operator or either side of a ## are fully macro expanded when they are replaced, not before the function-like macro is expanded.
This means that to make a single macro become two macro arguments a round of macro substitution must occur before the required function like macro is itself expanded.
This means that the solution of a second function like macro that expands to the desired function-like macro is the simplest solution.
i.e. given your original SET definition
#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits
and a macro that expands to two potential arguments
#define STATUS_LED_PORT LATB
#define STATUS_LED_MASK 0x0040;
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK
You have to use another function-like macro to get the substitution that you need.
e.g.
#define SET2(x) SET(x)
Then SET2( STATUS_LED ) expands as follows.
SET( LATB , 0x0040; )
then
*((volatile unsigned long*)(& LATB + 2 )) = 0x0040;
This isn't valid as there are not enough arguments to the SET macro; the parameters are matched to arguments before any expansion of the argument occurs. My compiler generates an error; the behaviour isn't defined.
SET( STATUS_LED )
If the root name is always the same you could use:
#define SET_COMPOSITE(root) SET(root##_PORT, root##_MASK)

Resources