I've got a list of definitions: MASTER, SLAVE0, SLAVE1, ... SLAVE9 to control which array of audio data is programmed into a microcontroller. The micro can hold no more than one sound file, so I have included the following definitions at the top of my main.c file:
#define MASTER
#define SLAVE0
#define SLAVE1
....
#define SLAVE9
Then, I write the following in my audio array:
#if defined(MASTER)
uint8_t sound[4096] PROGMEM = {127,126, ... }
#elif defined(SLAVE0)
uint8_t sound[4096] PROGMEM = {126,128, ... }
....
#else
#ERROR "One of MASTER-SLAVE9 must be defined!"
#endif
The person wishing to compile must then go through and comment out one and only one of the #define lines. This is not only tedious, but also error-prone. So, I'm looking to simplify the process. Any pointers for any of the following tasks would be helpful:
How can I test a list of macros for the presence of one and only one of these options? A simple if defined(MASTER) && !(defined(SLAVE0) || defined(SLAVE1) ...) would require 11 such tests, each with 11 subtly different conditions. It's a one time expense, but it's kinda ugly. It feels like this might be a common need, and that there ought to be a better way.
How can I simplify the compilation process? I've been using AVRStudio with WinAVR t0 compile. It has an 'export makefile' option, but I have no experience with it. I'm stuck doing this on Windows. An ideal process would build all 11 configurations in a single command, and then I could go through and program each one to the microcontroller individually. The current, very much less-than-ideal build process involves editing the source each time I want to build, and renaming/moving the output file.
You can use a single test to ensure that only one of the macros is defined.
#if (defined(MASTER) + defined(SLAVE1) + defined(SLAVE2)) != 1
#error "Too many macros defined"
#endif
As for the definition itself, most compilers allow you to define a macro using a command line option; this might be cleaner than a file with a "configurable options list." You would then be able to create multiple build configurations, each of which defines a different macro, and build them each in sequence (I'm not familiar with your build system to be able to explain how exactly you need to do that).
I would just make a block comment with the name of all possible constants, and follow it with a single define. Who wants to compile just writes what he wants. First time he will check the comment to see the list, then he will just write.
Or even better, keep this list in a comment (for reference) and use the -D option that most compilers have (-DMASTER to define master for example) and if your tool supports it, make a build configuration for each where you change the -D value. Using a different build configuration i guess you could also change the output file name, so that would kill two birds with a stone.
Why not something like:
#define ARRAY_NAME (SLAVE0)
...
#if (ARRAY_NAME == MASTER)
// blah
#elif (ARRAY_NAME == SLAVE0)
// blah
// etc.
or even better, just:
#define ARRAY_MASTER { 1, 2, 3, 4 }
#define ARRAY_SLAVE0 { 5, 6, 7, 8 }
// etc.
...
const uint8_t sound[] = ARRAY_MASTER;
You are need an error message when you deined mre than one macro? Well, just write:
#ifdef MASTER
uint8_t sound = { ... };
#endif
#ifdef SLAVE0
uint8_t sound = { ... };
#endif
#ifdef SLAVE1
uint8_t sound = { ... };
#endif
And compiler will complain that one identifier defined multiple times.
Also why not use this?
#define SLAVE <n>
uint8_t sound_master = { ... };
uint8_t sound_slave_0 = { ... };
uint8_t sound_slave_1 = { ... };
uint8_t sound_slave_2 = { ... };
#define XCAT(a,b) a##b
#define CAT(a,b) XCAT(a,b)
#ifdef SLAVE
#define sound CAT(sound_slave_,SLAVE)
#endif
#ifdef MASTER
#ifdef sound
/* warnin or so. but if you need an error just remove this ifdef **/
#endif
#define sound sound_master
#endif
Related
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
Short story: I want to enforce a run-time condition check in certain conditionally-compiled code blocks, but not others.
Long story:
Our C code base relies heavily on profiling.
We have lots of different profiles, and almost each module has #ifdefs for at least 5-6 different profiles, wrapping large segments of code.
We have added a new requirement - for certain profiles (Let's say <A> and <B>), the conditionally-compiled code will only be run if a specific condition is met. For the other profiles (Let's say <C>) this is not required.
i.e., this is how the code looks now:
#ifdef <A>
/* Profiled code… */
#endif /* <A> */
#ifdef <B>
/* Profiled code… */
#endif /* <B> */
#ifdef <C>
/* Profiled code… */
#endif /* <C> */
This is how we need it to look:
#ifdef <A>
if (new_condition)
{
/* Profiled code… */
}
#endif /* <A> */
#ifdef <B>
if (new_condition)
{
/* Profiled code… */
}
#endif /* <B> */
#ifdef <C>
/* Profiled code… */
#endif /* <C> */
So far, so good.
However, with the above implementation the new requirement isn't really maintainable.
It doesn't stop anyone not familiar with the requirement to add a new profiled code block, without adding the check for new_condition.
So I want to force our engineers to check for this condition whenever adding new blocks that are profiled under <A> and <B>, but not for code profiled under <C>.
Theoretically, the best solution would probably be a way to fail the build process, if there exists an #ifdef <A> or #ifdef <B> that isn't directly followed by if (new_condition).
Thing is, I have no idea to do that. Do any of you have?
I'm reasonably sure it can't be done as described. It would seem that your engineers get to write all the code from the #ifdef to the #endif and the only 'hooks' you have are the conditional symbols and condition. That isn't enough. Some semi-random thoughts:
You could turn the 'condition' into a function call and count how often it gets called.
You could demand certain 'null behaviour' when all the conditions are set to false.
You could create some function your engineers have to call inside their block to get access to something, and check at runtime that it doesn't get called if the condition is false.
Ultimately I think you'd be better to use source code analysis tools to analyse the source code and report on coding style breaches. That would be CppCheck or one of these: http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis.
Bit hard to answer this, since everything is so fuzzy :) But I would suggest to use somekind of wrapper, which the person editing the code isn't allowed to change:
typedef void(*stuff_ptr)(void);
inline void do_stuff (stuff_ptr stuff)
{
#if defined(A) || defined(B)
if (!new_condition)
{
return ;
}
#endif
stuff();
}
#ifdef A
do_stuff(A_stuff);
#endif
#ifdef B
do_stuff(B_stuff);
#endif
#ifdef C
do_stuff(C_stuff);
#endif
This will not fail to build, but instead prevents incorrect builds from happening in the first place.
do_stuff() can be implemented as a function-like macro if needed, but avoid that if you can. The "new_condition" could be passed as another parameter, if needed.
One idea that maintains your current begin macro, end macro style blocks might be something like the following:
#include <stdio.h>
#define FOO 1
#define BAZ 1
int condition_a = 1;
int condition_b = 0;
#ifdef FOO
# define FOO_BEGIN if (condition_a) {
# define FOO_END }
#else
# define FOO_BEGIN if (0) {
# define FOO_END }
#endif
#ifdef BAR
# define BAR_BEGIN if (condition_b) {
# define BAR_END }
#else
# define BAR_BEGIN if (0) {
# define BAR_END }
#endif
#ifdef BAZ
# define BAZ_BEGIN if (1) {
# define BAZ_END }
#else
# define BAZ_BEGIN if (0) {
# define BAZ_END }
#endif
int main (int argc, char ** argv)
{
FOO_BEGIN
printf("in foo\n");
FOO_END
BAR_BEGIN
printf("in bar\n");
BAR_END
BAZ_BEGIN
printf("in baz\n");
BAZ_END
}
prints
in foo
in baz
You're going to have to either update the macros that define entering and exiting blocks or require something inside of those ifdefs.
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 have a series of #defines from a library file header of this sort:
typedef int Lib_error;
#define LIB_ERROR_A ((Lib_error) 0x0000)
#define LIB_ERROR_D ((Lib_error) 0x0100)
#define LIB_ERROR_F ((Lib_error) 0x0200)
#define LIB_ERROR_K ((Lib_error) 0x0300)
#define LIB_ERROR_O ((Lib_error) 0x0400)
#define LIB_ERROR_P ((Lib_error) 0x0500)
#define LIB_ERROR_R ((Lib_error) 0x0600)
#define LIB_ERROR_X ((Lib_error) 0x0700)
#define LIB_ERROR_Y ((Lib_error) 0x0800)
#define LIB_ERROR_M ((Lib_error) 0x0900)
/* and so on */
Is there any way apart I can print these values so if for example
uint MyError;
/* printf("Error = %s",MyError); It should print the string LIB_ERROR_F instead of say 0x200 */
I could use lot's of if else for this but I was wondering if there was a cleverer way. Please note that I can't change the contents of library header file in anyway.
People seem to have mixed feelings about them, but X-macros are one possible solution.
But if you can't change the header, then your only two options (AFAIK) are:
Doing it manually
Some form of code generation step in your build process. In your case, it should probably be possible by parsing the header file with sed (assuming you're working on Linux).
There isn't a simple or automatic way to do it. You have to generate the list of numbers and names yourself, and provide a lookup function to map between number and name.
You might take a look at the ideas in the blog post 'Enums, Strings and Laziness'; it has some ideas that might help you. (That's closely related to the X-Macros at Dr Dobbs mentioned by Oli Charlesworth; the article there claims the technique goes back to the 60s, albeit that it must have been in a language other than C since C didn't exist back then.)
Warning: The below code piece is just a sample. It can be improvised a lot which is for you to do. : )
Define a structure like below:
typedef struct ErrorStorage
{
Lib_error err;
char err_string[100];
}ErrNoStore;
ErrNoStore arrErr[25];
arrErr[0].err = LIB_ERROR_A;
strcpy(arrErr[0].err_string, "LIB_ERROR_A");
/... and so on .../
and later down in the code define a function like this and call it
void display_error(Lib_error errnum)
{
int i = 0;
for(i=0; i<25;i++)
{
if(errnum == arrErr[i].err)
{
printf("%s\n", arrErr[i].err_string);
}
}
}
}
Just generate a table by parsing those defines in some scripting language. Should be easy-ish to translate those defines to the declaration of a constant array of code, string structs which you can then iterate.
Assuming the library doesn't change often, you'll only need to do this once so you don't need to bother much with script corectness etc.
I'm writing firmware in C for an embedded processor. I want to have all the configuration information in one header file called config.h. This is causing problems with the ADC initialization, where simple #defines won't do the trick. Right now the code is like so:
config.h
#define NUMBER_OF_POTS 1
#define POT_1_CHANNEL 27
adc.c
#define MAKE_CSS(channel) _CSS##channel
#define CALL_MAKE_CSS(channel) MAKE_CSS(channel)
void initialize_adc() {
CALL_MAKE_CSS(POT_1_CHANNEL);
}
What I want to do is not have to touch adc.c if I change config.h to:
#define NUMBER_OF_POTS 2
#define POT_1_CHANNEL 27
#define POT_2_CHANNEL 29
adc.c should just automatically add a second CALL_MAKE_CSS with some macro trickery.
I guess the question is: is there a trick that gives you for loop capability with a macro?
Thanks,
Steve.
I didn't test this:
// config.h
#define NUMBER_OF_POTS 2
extern int pots[];
// config.c
int pots[NUMBER_OF_POTS] = {
27,
29
};
// adc.c
void initialize_adc() {
for (int i = 0; i < NUMBER_OF_POTS; i++) {
CALL_MAKE_CSS(pots[i]);
}
}
You don't have to rely entirely on macros. Just define your 'magic numbers' as #defines.
For example:
In config.h:
#define NUMBER_OF_POTS 2
#define POT_1_CHANNEL 27
#define POT_2_CHANNEL 29
unsigned int PotChannelList[NUMBER_OF_POTS] = {POT_1_CHANNEL, POT_2_CHANNEL};
In adc.c:
for(i = 0; i < NUMBER_OF_CHANNELS; i++)
{
initialize_adc(PotChannelList[i]);
}
You still define the setup in config.h and don't have to change adc.c when you add a channel. You just add it to the list. The list order also defines the order of initialization.
EDIT: Sorry about the formatting mess...
Have a look at boost.preprocessor. Although boost is usually for C++, the preprocessor metaprogramming lib works, well, just with the CPP, so it may do what you want. It provides a few datastructures (lists, tuples) and iteration macros.
Sorry, I can't give you any example if it really does what you want, or at least provides another way, because I seldom needed it, and it's too long ago.
Note Just saw Schroeder's answer. Not relying on the PP if it is not necessary is still the best option...
The C preprocessor cannot do loops. You'll either have to do the looping in C code, or if you really need to do something loop-like at compile time, you can write your own preprocessor (which can just be a simple shell script, e.g.) that generates the necessary code.
Although you can't do loops with the preprocessor, you can do unrolled loops. So if you know you're never going to have more than 4 pots you could do this;
void initialize_adc() {
#if NUMBER_OF_POTS > 0
CALL_MAKE_CSS(POT_1_CHANNEL);
#endif
#if NUMBER_OF_POTS > 1
CALL_MAKE_CSS(POT_2_CHANNEL);
#endif
#if NUMBER_OF_POTS > 2
CALL_MAKE_CSS(POT_3_CHANNEL);
#endif
#if NUMBER_OF_POTS > 3
CALL_MAKE_CSS(POT_4_CHANNEL);
#endif
}
The only benefit of this compared to other solutions here is that there is no runtime overhead at all. Extra inline code "magically" appears if and only if another channel is added, just as the questioner wanted. To extract the ugliness from within the function call (at the cost of putting it earlier in your code instead), define 4 new macros each using the same #if NUMBER_OF_POTS > x technique. Then you'd be able to go simply;
void initialize_adc() {
INIT_CSS_1();
INIT_CSS_2();
INIT_CSS_3();
INIT_CSS_4();
}