Reputation: 75
I am attempting to alter an IAR specific header file for a lpc2138 so it can compile with Visual Studio 2008 (to enable compatible unit testing).
My problem involves converting register definitions to be hardware independent (not at a memory address)
The "IAR-safe macro" is:
#define __IO_REG32_BIT(NAME, ADDRESS, ATTRIBUTE, BIT_STRUCT) \
volatile __no_init ATTRIBUTE union \
{ \
unsigned long NAME; \
BIT_STRUCT NAME ## _bit; \
} @ ADDRESS
//declaration
//(where __gpio0_bits is a structure that names
//each of the 32 bits as P0_0, P0_1, etc)
__IO_REG32_BIT(IO0PIN,0xE0028000,__READ_WRITE,__gpio0_bits);
//usage
IO0PIN = 0x0xAA55AA55;
IO0PIN_bit.P0_5 = 0;
This is my comparable "hardware independent" code:
#define __IO_REG32_BIT(NAME, BIT_STRUCT)\
volatile union \
{ \
unsigned long NAME; \
BIT_STRUCT NAME##_bit; \
} NAME;
//declaration
__IO_REG32_BIT(IO0PIN,__gpio0_bits);
//usage
IO0PIN.IO0PIN = 0xAA55AA55;
IO0PIN.IO0PIN_bit.P0_5 = 1;
This compiles and works but quite obviously my "hardware independent" usage does not match the "IAR-safe" usage.
How do I alter my macro so I can use IO0PIN the same way I do in IAR? I feel this is a simple anonymous union matter but multiple attempts and variants have proven unsuccessful. Maybe the IAR GNU compiler supports anonymous unions and vs2008 does not.
Thank you.
Upvotes: 2
Views: 1945
Reputation: 75
Ok folks here's what ended up working for me:
#define __IO_REG32_BIT(NAME, BIT_STRUCT)\
volatile union\
{\
unsigned long NAME;\
BIT_STRUCT NAME##_bit;\
} NAME##_type;
__IO_REG32_BIT(IO0PIN,__gpio0_bits);
#define IO0PIN IO0PIN_type.IO0PIN
#define IO0PIN_bit IO0PIN_type.IO0PIN_bit
Now I can use the following in my code for unit testing:
IO0PIN = 0xFFFFFFFF;
IO0PIN_bit.P0_5 = 1;
And the preprocessor will replace it with:
IO0PIN_type.IO0PIN = 0xFFFFFFFF;
IO0PIN_type.IO0PIN_bit.P0_5 = 1;
Upvotes: 1
Reputation: 1575
I know this isn't an answer but I don't have enough reputation to edit the question. I hope this might be helpful for clarification. If you take all of the macros out of the picture, what Alan_m wants to end up with is an anonymous union like the following:
volatile union {
u32 IO0PIN;
u16 IO0PIN_bit;
};
That can be referenced like this:
void test( void )
{
IO0PIN = 0x0xAA55AA55;
IO0PIN_bit.P0_5 = 0;
}
This works O.K. with the IAR compiler but causes a compiler error on the VC++ compiler
error C2646: global anonymous unions must be declared static
Note that this is from VS2005 so it might be slightly different than VS2008.
I would imagine all of Alan_m's code is already written to IAR standards and would have to be modified to use named unions which he wants to avoid.
Upvotes: 0
Reputation: 400304
The usual way of doing this is with a macro that just casts the desired address to the appropriate type:
#define __IO_REG32_BIT(NAME, BIT_STRUCT) \
typedef volatile union \
{ \
unsigned long NAME##_value: \
BIT_STRUCT NAME##_bit; \
} NAME##_type
__IO_REG32_BIT(IO0PIN, __gpio0_bits);
#define IO0PIN (*(IO0PIN_type *)0xE0028000)
Now IO0PIN
can be used just as you described. However, note that I had to rename the internal field and type name to avoid conflicting with the macro name IO0PIN
. You can of course rename things to your liking.
Upvotes: 0