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.
Related
I'm writing some libraries for a microcontroller, and for that purpose, I use macro-like functions. For example, a macro-like function to enable an I2C module is defined as:
#define I2C_MODULE_ENABLE(_x) \
I2C##_x##CONLbits.I2CEN = 1
where _x is the module number (e.g.,1 or 2 in my case).
If a user calls this macro-like function as I2C_MODULE_ENABLE(1), it would be expanded by a preprocessor as I2C1CONLbits. I2CEN = 1.
However, if a user calls this macro-like function as I2C_MODULE_ENABLE(MY_I2C), where MY_I2C is a macro constant defined in a user-defined config.h file that is included by my i2c.h library (e.g., the macro constant is defined as #define MY_I2C 1), the macro-like function would be expanded as I2CMY_I2CCONLbits. I2CEN = 1.
I know that I need to somehow evaluate the MY_I2C macro constant before concatenation, and I can do that by adding another macro level:
#define __I2CxCONLbits(_x) I2C##_x##CONLbits
#define I2C_MODULE_ENABLE(_x) \
__I2CxCONLbits.I2CEN = 1
My question is: is there a more elegant solution to this problem since I have multiple registers like the CONLbits register. Using this approach I would need to define a special __I2CxREGISTER(_x) macro for every register.
I tried to do something like this:
#define __I2Cx(_x) I2C##_x
#define I2C_MODULE_ENABLE(_x) \
__I2Cx(_x)##CONLbits.I2CEN = 1
but that produces an output like this: I2C1 CONLbits .I2CEN = 1, and my compiler is complaining about the whitespace between I2C1 and CONLbits tokens.
You aren't adding the macro level properly, as I see it. The usual idiom is to define a wrapper that does nothing but forward the argument. That way, if the argument is itself a macro, it will be expanded before being passed to the macro that is wrapped:
#define I2C_MODULE_ENABLE__(x_) \
I2C##x_##CONLbits.I2CEN = 1
#define I2C_MODULE_ENABLE(x_) \
I2C_MODULE_ENABLE__(x_)
I took the liberty of renaming your macro parameter, since identifiers with leading underscores are defined as reserved for the implementation, I think it's better to be safe than sorry.
To solve your problem of the space I'd go with the proverbial level of indirection, and use a function like macro to generate the correct prefix token, and pass it along two levels to make sure it's expanded correctly:
#define I2Cx__(x_) I2C##x_
#define I2C_MODULE_ENABLE__(IC_) \
IC_##CONLbits.I2CEN = 1
#define I2C_MODULE_ENABLE_(IC_) \
I2C_MODULE_ENABLE__(IC_)
#define I2C_MODULE_ENABLE(x_) \
I2C_MODULE_ENABLE_(I2Cx__(x_))
See it live here
The whole shtick is to make sure the preprocessor sees and produces valid tokens at each step. Which can be a bit tiresome.
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.
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.
I've defined the following, of course it's not correct...
#define SET_PIN_MODE_INPUT(DREG, PORT, PIN) (DREG &= ~_BV(PIN), PORT &= ~_BV(PIN))
#define LED_CLOCK_PIN (DDRB, PORTB, PB3)
and I want to use them like this:
SET_PIN_MODE_INPUT(LED_CLOCK_PIN)
So I need help with C syntax.
Indirection is required:
#define SET_PIN_MODE_INPUT_(DREG, PORT, PIN) (DREG &= ~_BV(PIN), PORT &= ~_BV(PIN))
#define SET_PIN_MODE_INPUT(ARGS) SET_PIN_MODE_INPUT_ ARGS
// Note that this is an object-like macro
#define LED_CLOCK_PIN /**/ (DDRB, PORTB, PB3)
With your current macros, you are passing a single argument to SET_PIN_MODE_INPUT, which requires three arguments.
This solution uses indirection to use the replacement list of LED_CLOCK_PIN as the argument list for the invocation of the real SET_PIN_MODE_INPUT.
You might want to define them as static inline functions in the header file, instead than defines. In this way you will get typecheck and you won't risk unexpected things to happen because of the preprocessor.
And the compiler will inline them.
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)