Определение / объявление анонимного объединения в макросе GNU vs VS2008 - PullRequest
2 голосов
/ 23 апреля 2010

Я пытаюсь изменить специальный заголовочный файл IAR для lpc2138, чтобы он мог компилироваться с Visual Studio 2008 (чтобы включить совместимое модульное тестирование).

Моя проблема заключается в преобразовании определений регистров в аппаратно-независимые (не по адресу памяти)

"IAR-безопасный макрос" - это:

#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;

Это мой сопоставимый «аппаратно-независимый» код:

#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;

Это компилируется и работает, но совершенно очевидно, что мое «аппаратно-независимое» использование не соответствует «IAR-safe» использованию.

Как изменить макрос, чтобы я мог использовать IO0PIN так же, как в IAR? Я чувствую, что это простое анонимное объединение, но многочисленные попытки и варианты оказались безуспешными. Возможно, компилятор IAR GNU поддерживает анонимные объединения, а vs2008 - нет.

Спасибо.

Ответы [ 3 ]

1 голос
/ 28 апреля 2010

Хорошо, ребята, вот что у меня получилось:

#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

Теперь я могу использовать в своем коде следующее для модульного тестирования:

IO0PIN = 0xFFFFFFFF;
IO0PIN_bit.P0_5 = 1;

И препроцессор заменит его на:

IO0PIN_type.IO0PIN = 0xFFFFFFFF;
IO0PIN_type.IO0PIN_bit.P0_5 = 1;
0 голосов
/ 24 апреля 2010

Я знаю, что это не ответ, но у меня недостаточно репутации, чтобы редактировать вопрос. Я надеюсь, что это может быть полезно для разъяснения. Если вы уберете все макросы из картинки, Alan_m захочет закончить анонимным объединением, подобным следующему:

volatile union {
   u32 IO0PIN;
   u16 IO0PIN_bit;
};

На это можно ссылаться так:

void test( void )
{
   IO0PIN = 0x0xAA55AA55;
   IO0PIN_bit.P0_5 = 0;
}

Это работает О.К. с компилятором IAR, но вызывает ошибку компилятора на компиляторе VC ++

ошибка C2646: глобальные анонимные союзы должен быть объявлен статическим

Обратите внимание, что это из VS2005, поэтому он может немного отличаться от VS2008.

Я бы предположил, что весь код Alan_m уже написан в соответствии со стандартами IAR, и его придется изменить, чтобы использовать именованные объединения, которых он хочет избежать.

0 голосов
/ 23 апреля 2010

Обычный способ сделать это с помощью макроса, который просто приводит желаемый адрес к соответствующему типу:

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

Теперь IO0PIN можно использовать так же, как вы описали. Однако обратите внимание, что мне пришлось переименовать внутреннее поле и имя типа, чтобы избежать конфликта с именем макроса IO0PIN. Конечно, вы можете переименовать вещи по своему вкусу.

...