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

Я пытаюсь изменить специальный файл заголовка 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" использованию.

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

Спасибо.


person Alan_m    schedule 23.04.2010    source источник
comment
Вы можете не удалять модификатор типа __no_init. Если это удалить, периферийные регистры будут инициализированы нулем при запуске, что, вероятно, приведет к нежелательным результатам (я не могу себе представить, что все регистры имеют значение по умолчанию 0). Вместо этого вы можете определить пустой макрос (#define __no_init) в своем проекте VS2008.   -  person semaj    schedule 24.04.2010


Ответы (3)


Хорошо, ребята, вот что в итоге сработало для меня:

#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;
person Alan_m    schedule 28.04.2010
comment
Спасибо @Adam Rosenfield и @semaj за то, что помогли мне добраться до этого! - person Alan_m; 28.04.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. Вы, конечно, можете переименовывать вещи по своему вкусу.

person Adam Rosenfield    schedule 23.04.2010
comment
Я пробовал этот код, и мне пришлось использовать: IO0PIN.IO0PIN_value = 0xAA55AA55; IO0PIN.IO0PIN_bit.P0_5 = 1; Я хочу иметь возможность просто использовать: IO0PIN = 0xAA55AA55; IO0PIN_bit.P0_5 = 1; Не важно, чтобы IO0PIN указывал на адрес 0xE0028000. Я просто хочу использовать простую старую переменную для высокоуровневого модульного тестирования. - person Alan_m; 23.04.2010
comment
Если этот макрос используется на ПК для модульного тестирования, это вызовет сбой при попытке присвоить значение фиксированному адресу (0xE002800) ... или я что-то упустил? - person semaj; 24.04.2010
comment
Он скомпилирован отлично, но да, я не уверен в поведении. Опять же, мне не нужно использовать этот адрес. - person Alan_m; 24.04.2010
comment
@Alan_m: Тогда я не понимаю, что вы пытаетесь сделать. Что не так с вашим текущим аппаратно-независимым кодом? - person Adam Rosenfield; 24.04.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 и должен быть изменен для использования именованных объединений, которых он хочет избежать.

person semaj    schedule 23.04.2010