I'm having problem building C macro for my PIC. It's the same for other C-based system's, so non-PIC C experts are also more than welcome.
Lets assume that I have defined my LED_1 pin :
#define LED_1 A1 //A1 as output for LED_1
So if I want to light a LED I would write:
PORTAbits.RA1 = 1;
And if I would like to do it using my LED_1 definition I have to add two more macros:
#define change_PORT_(var) PORTAbits.R##var
#define change_PORT(var) change_PORT_(var
And to use it:
change_PORT(LED_1) = 1;
And it works like a charm. But the problem is that in definitions above I have
PORT A bits.##var
So what if I want to change PORTB values? I would have to build separate macros for PORTs A and B. But it's not even close to be a robust solution.
And I came up with an idea which, I don't know why, doesnt work.
#define LED_1 A1
#define LED_2 B1
#define __A1 A //This would be defined for all PORTA's pins such as A2,A3,A4 etc
#define __B1 B
#define ___change_PORT(var,var2) PORT##var2 bits.R##var
#define __change_PORT(var,var2) ___change_PORT(var,var2)
#define _change_PORT(var) __change_PORT(var,__##var) // creating e.g. __A1
#define change_PORT(var) _change_PORT(var)
And when I try to run this:
change_PORT(LED_1);
The compiler changes __##var to ___A1 but it never changes __A1 to A so this MACRO doesn't work as it supposed to.
I spent a lot of time trying to fix it so I'd appreciate any help :)
EDIT::
I might have found a solution to my problem:
(LAT is just another register name, but it works same as PORT, so this name-change is irrelevant)
#define ___PORTchange(var,var2) PORT##var2##bits.R##var
#define __PORTchange(var,var2) ___PORTchange(var,var2)
#define CHANGE_TO_PORT_NAME(var) ___##var
#define _PORTchange(var) __PORTchange(var,CHANGE_TO_PORT_NAME(var))
#define PORTchange(var) _PORTchange(var)
but I get a compiler error:
100: PORTAbits.RA0 = 1;
^ (374) missing basic type; int assumed (warning)
^ (983) storage class redeclared
^ (984) type redeclared
^ (239) identifier "PORTAbits" redefined (from line 3900)
^ (314) ";" expected
So no it does substitute it correctly but I get a compiler warning telling me that I redefine PORTAbits which I cannot understand. I just wanted preprocessor to change PORTchange(var) to PORTxbits.Rvar where x is A or B. But instead it seems that I'm redeclaring something.
I don't get it.
If I preprocess (tried with several gcc versions and sun cc)
#define LED_1 A1
#define LED_2 B1
#define __A1 AX
#define __B1 BX
#define ___change_PORT(var,var2) PORT##var2##bits.R##var
#define __change_PORT(var,var2) ___change_PORT(var,var2)
#define _change_PORT(var) __change_PORT(var,__##var)
#define change_PORT(var) _change_PORT(var)
change_PORT(LED_1);
change_PORT(LED_2);
I get
PORTAXbits.RA1;
PORTBXbits.RB1;
which is apparently what you are wanting. A bug in your compiler?
Related
I'm compiling someone else's code written in C using gcc ARM compiler for STM32F4
#define ESC_CSR_CMD_BUSY BIT(31)
#define ESC_CSR_CMD_READ (BIT(31) | BIT(30))
#define ESC_CSR_CMD_WRITE BIT(31)
and I get an error as it appears to not know what BIT(n) is.
warning: implicit declaration of function 'BIT'; did you mean
'__RBIT'?
is there a stdint file somewhere that defines what BIT is...? or an alternate way of writing this please.
Although the code should ship with a definition of BIT, I would guess that this is a suitable definition:
#define BIT(n) (1UL << (n))
I'm looking for a way of making a macro that expands to extra arguments:
int constant1=2, constant2=3;
#define add_three_arguments(x,y,z) x+y+z
#define extra_arguments ,constant1,constant2
#define make_value(A) add_three_arguments(A extra_arguments)
int r = make_value(5);
The closest solution I have found is this:
int constant1=2, constant2=3;
#define _add_three_arguments(x,y,z) x+y+z
#define add_three_arguments(...) _add_three_arguments(__VA_ARGS__)
#define extra_arguments ,constant1,constant2
#define make_value(A) add_three_arguments(A extra_arguments)
int r = make_value(5);
Which is of course not a solution to the problem I stated. So the current answer seems to be, "this is not possible." But maybe a new version of clang/gcc will somehow enable this. I will leave the question open.
Try the following:
#define EMPTY
#define EVAL(X) X
#define add_three_arguments(x,y,z) x+y+z
#define extra_arguments ,constant1,constant2
#define make_value(A) EVAL(add_three_arguments EMPTY (A extra_arguments))
make_value(5);
However, if you redesign your macros you may get a nicer solution not requiring such constructs.
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.
My issue is this: I have some macros that look like this:
#define _EI_PORTLETTER 'D'
...code...
#if _EI_PORTLETTER == 'C'
#define _EI_VECTOR PORTC_VECT
if _EI_PORTLETTER == 'D'
#define _EI_VECTOR PORTD_VECT
#endif
Then later in my code I have:
ISR(_EI_VECTOR, ISR_NAKED) {
...code...
}
What I would like to be able to do is define _EI_PORTLETTER and not have to rewrite my macros just because of the single letter changing (because there are a body of 6 of them, and I have more _EI_PORTLETTERS than just 'C' and 'D'). Is it possible? That is, something like this:
#define _EI_PORTLETTER 'D'
...code...
#define _EI_VECTOR PORT _EI_PORTLETTER _VECT
or
#define _EI_VECTOR(x) PORT x _VECT
Such that the _EI_VECTOR, or _EI_VECTOR_(x), resolves to:
PORTD_VECT
(without any spacing around the D).
Is this possible using C macros?
It seems simple in my mind but I'm unable to do it. Yes, I have scoured Google and Stack Overflow, read the GCC docs. I have been unable to figure out how to do what I want, or even know if it's possible.
Yes, this is possible:
#define EI_PORTLETTER D
#define EI_VECTOR_(x) PORT ##x ##_VECT
#define EI_VECTOR2_(x) EI_VECTOR_(x)
#define EI_VECTOR EI_VECTOR2_(EI_PORTLETTER)
The EI_VECTOR_ macro uses the token-pasting operator ## to build the desired identifier.
The EI_VECTOR2_ macro serves to indirect EI_PORTLETTER so that it is expanded as D instead of just being pasted as EI_PORTLETTER.
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.