I am working on HW programming. I created below Varidic macro.
#define UPDATE_DATA(bit,...) { \
do { \
int i; \
int j = 0; \
int _args[] = {__VA_ARGS__};\
int *addr = (int *) ADDR ; \
for (i = 0; i < (sizeof(_args)/sizeof(_args[0])); i++) {\
*(int *) (DATA_ADDR - j) |= _args[i];\
j = j + 0x4; \
}\
*addr |= 1 << bit;\
}while (0); \
}
its working if I use like UPDATE_DATA(1,2,3);
But if use this macro inside for loop like,
msg_id = MSG_1;
for(j=0; j<15 ; j++)
{
msg_id = msg_id +1;
l_data = data_array[j];
UPDATE_DATA(msg_id,l_data,(SYSTEM_BASE_ADDR6+offset));
offset = (offset + 0x4);
}
I am getting
Error: #28: expression must have a constant value
LOGGER_UPDATE_DATA(msg_id,l_data,(SRAM0_SYSTEM_BASE_ADDR6+offset));
i am not getting what did i do wrong here!!
My suggestion is to not use a variadic macro. They expand code size and make maintenance difficult.
Assuming that you won't need to pass -1 as a value, you can use stdarg.h
#include <stdio.h> // for test output, not actually needed when you do the I/O
#include <stdarg.h>
#define LOGGER ((volatile int *)0x1234)
#define LOGGER_DATA ((volatile int *)0x5678)
void sendToLoggerV(int bit, va_list ap)
{
int i, value;
for (i = 0; ; ++i)
{
// do your write here...
value = va_arg(ap, int);
if (value == -1)
break;
// Can't really write it in this test, but this is what you would do:
//LOGGER_DATA[-i] = value;
printf("Pretending to write %d to %p\n", value, (void*)&LOGGER_DATA[-i]);
}
//*LOGGER |= 1 << bit;
printf("Pretending to OR %d to %p\n", 1<<bit, (void*)LOGGER);
}
void sendToLogger(int bit, ...)
{
va_list ap;
va_start(ap,bit);
sendToLoggerV(bit, ap);
va_end(ap);
}
#define SEND_TO(bit, ...) sendToLogger(bit, __VA_ARGS__, -1)
int main()
{
SEND_TO(1, 16, 17, 18, 19);
SEND_TO(2, 30, 31);
}
Since this will be running in an embedded system, my test case just prints messages to say what it would do. The lines commented out would do the actual memory writes. I have used contrived addresses (0x1234 and 0x5678) for your memory mapped I/O addresses.
This code outputs the following, which meets your specifications:
Pretending to write 16 to 0x5678
Pretending to write 17 to 0x5674
Pretending to write 18 to 0x5670
Pretending to write 19 to 0x566c
Pretending to OR 2 to 0x1234
Pretending to write 30 to 0x5678
Pretending to write 31 to 0x5674
Pretending to OR 4 to 0x1234