#define xxxxxx BIT(0) linker error - c

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))

Related

Variadic Macro Expansion: Expected primary expression before ) when __VA_ARGS__ is used

I have the following code:
#define TRACE_NONE 0
#define TRACE_ERROR 1
#define TRACE_WARNING 2
#define TRACE_INFORMATIONAL 3
#define TRACE_DEBUG 4
#define TINFO(str,cat,...) trace(TRACE_INFORMATIONAL,str,cat,__VA_ARGS__)
#define TWARN(str,cat,...) trace(TRACE_WARNING,str,cat,__VA_ARGS__)
#define TERROR(str,cat,...) trace(TRACE_ERROR,str,cat,__VA_ARGS__)
#define TDEBUG(str,cat,...) trace(TRACE_DEBUG,str,cat,__VA_ARGS__)
On the #define TINFO line I'm getting
error: expected primary-expression before ')' token
When I use it like this
TINFO("Session start","SES");
Edit: But if i supply a 3rd argument, like
TINFO("Session start","SES","");
everything works.
I want the first variant to work
My function signature for trace is this:
void trace(int level,const char* sz,const char* cat,...);
If it matters
I don't really use __VA_ARGS__ - the last time I used it was years ago, and I just can't seem to find what I'm doing wrong here, after looking at several examples. I'm missing something easy - I know I am - but I don't know what it is for the life of me.
This code can be GCC specific.
After some experimentation, I found I needed to use ##
#define TINFO(str,cat,...) trace(TRACE_INFORMATIONAL,str,cat, ##__VA_ARGS__ )
#define TWARN(str,cat,...) trace(TRACE_WARNING,str,cat, ##__VA_ARGS__ )
#define TERROR(str,cat,...) trace(TRACE_ERROR,str,cat, ##__VA_ARGS__ )
#define TDEBUG(str,cat,...) trace(TRACE_DEBUG,str,cat, ##__VA_ARGS__ )
That worked. I had tried VA_OPT but it wasn't working because apparently my toolchain uses an old compiler (I'm cross compiling for a microcontroller and i'm not used to the toolchain yet)

Why does avr-gcc tell me about missing argument while expanding my [fancy] macro?

I'm developing code for Atmel, which defines consistent register names to program port pins. For instance:
PORTC is traditionally used to set (high or low) any pin on port C
PINC is used to read the state of a particular pin on port C
DDRC is used to read/write the direction (0=input, 1=output) of any pin on port C
So I found some code — which I fully understand — that defines a PIN macro like this:
#define LED_PIN C,7
Then the following macros (restricted to the use case I'm talking about here):
#define _BV(bit) (1 << bit)
...
#define _SET(type, name, bit) type ## name |= _BV(bit)
#define _CLEAR(type, name, bit) type ## name &= ~ _BV(bit)
#define _TEST(type, name, bit) ( type ## name & _BV(bit) )
...
#define OUTPUT(pin) _SET(DDR, pin)
#define INPUT(pin) _CLEAR(DDR, pin)
...
#define HIGH(pin) _SET(PORT, pin)
#define LOW(pin) _CLEAR(PORT, pin)
So I can write a function main() as follows:
main() {
OUTPUT(LED_PIN);
HIGH(LED_PIN);
}
While it is very convenient and prevents from defining three macros (e.g. PINC7, PORTC7 and DDRC7) for just one LED, my main concern about this is that is imposes to also redefine AVR macros to account for that kind of notation, bearing in mind AVR macros use SFR registers as arguments (from sfr_defs.h):
#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
Also, AVR defines macros to convert from [what I'd call] bare registry names to actual memory-mapped special-function register names (sfr) for avr-gcc:
#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
and _SFR_ADDR() adds an offset 0 or 20 according to the target Atmel CPU. So in order to enhance compatibility with those AVR library functions, which take an SFR register plus an optional argument, I decided to rewrite the initial code and tried the following:
#define _SFR_BIT(type, name, bit) type ## name, bit
#define _PORT(pin) _SFR_BIT(PORT, pin)
#define _PIN(pin) _SFR_BIT(PIN, pin)
#define _DDR(pin) _SFR_BIT(DDR, pin)
#define set_bit(sfr, bit) _SFR_BYTE(sfr) |= _BV(bit)
#define set_output(pin) set_bit(_PIN(pin))
but then I face a compiler error message as soon as I write something like this in function main():
set_output(LED_PIN);
main.cpp:72:19: error: macro "set_bit" requires 2 arguments, but only 1 given
I get the same error if I try this, too:
#define set_output(pin) set_bit(_SFR_BIT(DDR, pin))
Why is that macro OUTPUT(), which passes only two out of of three arguments to _SET() compiles fine and my macro doesn't?
As Jens Gustedt pointed to, the generic explanation lies in the order of which the compiler resolves macros.
To transform an arbitrary number of arguments to be passed to a function with a fixed number of arguments using a macro, the function name can be made an argument to the macro:
#define EXPAND(f, ...) f(__VA_ARGS__)
#define _SFR_BIT(type, name, bit) type ## name, bit
...
#define set_bit(sfr, bit) _SFR_BYTE(sfr) |= _BV(bit)
...
#define set_output(pin) EXPAND(set_bit, _SFR_BIT(PIN, pin))
How many and which arguments are passed to the function (first argument) is resolved without any "argument missing" compiler error.
A refined version:
#define _SFR_X(f, type, name, bit) f(type ## name, bit)
...
#define set_bit(sfr, bit) _SFR_BYTE(sfr) |= _BV(bit)
...
#define set_output(pin) _SFR_X(set_bit, PIN, pin)
DISCLAIMER
The code is not yet in production. The code may be ugly, of course. It's mostly some base work under construction. Hence not yet finalized.
The decomposition of the arguments for set_bit into several takes place before the _SFR_BIT macro is expandend. So when it then sees the comma that resulted from the expansion of the latter, it is already too late.
A common trick is to expand the argument once more
#define set_bit0(...) set_bit(__VA_ARGS__)
#define set_output(pin) set_bit0(_PIN(pin))
Here _PIN(pin) is expanded and passt to set_bit0. When passing the arguments from set_bit0 to set_bit it sees the already expandend sequence, including the comma.

strange #define statements in C

I have an embedded C source code. In it's definitions, it has a lot of #define lines like following:
#define XNV_SPI_TX(x) st(U1CSR &= 0xFD; U1DBUF = (x);)
any idea what does
st( )
means and does?
I am using IAR as compiler and toolchain.
Thanks to comments, here is what I found:
/* (The while condition below evaluates false without generating a
* constant-controlling-loop type of warning on most compilers.)
*/
#define st(x) do { x } while (__LINE__ == -1)
This construct is used to prevent if/else conditionals show unexpected behavior.
For example if you have something like
#define assign() a=1;b=0;
it would not behave as expected in if/else statement.

C: How to enable __<Flag_Name>__

I have the following piece of code:
#ifdef __SYM_TRACE__
#define SYM_TRACE( L, F ) { SETTRACE_LEVEL(L); tracefunc F; }
#define SYM_TRACE2( F ) { SETTRACE_LEVEL(SYM_MODULE); tracefunc F; }
#else
#define SYM_TRACE( L, F )
#define SYM_TRACE2( F )
#endif
Now the issue is that where would I find the SYM_TRACE flag and how do I enable it? There is no macro in the code by the name of SYM_TRACE, so where is this getting picked from?
Also, another beginner question. Could someone please explain the significance of __ before and after the macro name.
Thanks,
Sunny
Answer is already there so consider it just as addition
You can do following option to enable __SYM_TRACE__
write #define __SYM_TRACE__ in header file which is getting used with shown piece of code.(Do not forget to guard it with #ifndef endif)
You can add it in Makefile as suggested by #Ishmeet using -D__SYM_TRACE__
Now if you are talking about _Name_ then it is a way to make difference between standard(or predefined) macros with user defined.For example GCC predefined macros like __WCHAR_TYPE__ and __WINT_TYPE_ having underscore before and after.
__SYM_TRACE__
is probably defined in your make file, and __ is just the name, I dont think that has a significance, maybe it does during porting on other platforms.
Most C compilers accept the option -D to define a symbol:
gcc -D__SYM_TRACE__ file.c

Advanced Preprocesor Tokenization in C

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?

Resources