Перейти к содержанию
    

совместное использование исходников IAR и GCC

Есть многопроцесорная система. Часть кода написана в IAR. Часть кода надо написать на WinAVR. Имеется несколько заголовочных файлов, описывающие нечто общее для всей системы, например структуры, которыми идет обмен по системной шине. Поскольку в системе используются и ARM и AVR приходится использовать упакованные структуры. Но этим двум компиляторам требуется описывать упаковку по-разному. Итого имеем:

IAR:
#pragma pack (push,1)
struct tmp_t
{
    uint8_t     A;
    uint16_t    B;
};
#pragma pack (pop)

WinAVR:
struct tmp_t
{
    uint8_t     A;
    uint16_t    B;
}__attribute__((__packed__, __aligned__ (1)));
или 
struct tmp_t __attribute__((__packed__, __aligned__ (1)));
struct tmp_t
{
    uint8_t     A;
    uint16_t    B;
};

Кто нибудь знает каким образом можно это объединить?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У каждого компилятора есть предопределенное макро, его описывающее. Ну и дальше по типу:

 

#if defined(__ICCAVR__) // IAR C Compiler

#define FLASH_DECLARE(x) __flash x

#endif

#if defined(__GNUC__) // GNU Compiler

#define FLASH_DECLARE(x) x __attribute__((__progmem__))

#endif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Совсем красиво не получится. В одном комплекте исходников я видел следующее:

#if __packed_pragma
#pragma pack(1)
#endif

typedef __packed struct
{
int aaa;
char bbb;
} __packed_gnu T_AB;

#if __packed_pragma
#pragma pack()
#endif

 

Дефайны для __packed_pragma, __packed и __packed_gnu генерятся в зависимости от компилятора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто нибудь знает каким образом можно это объединить?

Например, вариации по мотивам недавненого обьяснения http://electronix.ru/forum/index.php?showt...321&hl=pack

паковки структур в lwIP:

#include packon
struct tmp_t
{
    uint8_t     A;
    uint16_t    B;
}PACK_STRUCT;
#include packoff

PACK_on_off.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

у IAR, в соответсвии со стандартом С99 есть директива _Pragma, которая позволяет запихать #pragma в #define

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

есть директива _Pragma, которая ...

Оператор _Pragma() штука безусловно хорошая, только не для случаев, когда надо писать максимально переносимый код - тут банальный #include вне конкуренции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо всем за идеи!

Оператор _Pragma() штука безусловно хорошая, только не для случаев, когда надо писать максимально переносимый код - тут банальный #include вне конкуренции.
#include-решение мне не нравится - оно неочевидно, легко забыть включить завершающий #include, в проекте появляются мелкие файлы, которые собственно исходником не являются.

 

Ваши советы и макрос ATOMIC_CODE имени ReAl натолкнули меня на такое решение:

#if        defined( __GNUC__ )
    #define PACKED(_struct_)    \
    _struct_ __attribute__((__packed__, __aligned__(1)));
#elif   defined( __IAR_SYSTEMS_ICC__ )
    #define PACKED(_struct_)    \
    _Pragma("pack (push,1)") _struct_; _Pragma("pack (pop)")
#endif

PACKED(
    struct test_t
    {
        uint8_t     A;
        uint16_t    B;
    }
)

Что-то подобное я пытался сделать перед тем, как задать вопрос, но я хотел дополнительно передавать параметр выравнивания, и если для GCC мне легко удалось его засунуть в __aligned__(N), то ИАР требует чтобы параметр _Pragma() был в кавычках и вот тут я застрял. А ваши ответы натолкнули на мысль, что нужны всего две упаковки - "побайтная" и "по умолчанию = без упаковки". Хотя если кто-то подскажет как из #define PACKED(pack_val, _struct_) вставить значение pack_val в _Pragma("pack (push,1)") вместо '1', буду очень благода.

 

P.S. макрос имени ReAl выглядит так:

#define    ATOMIC_CODE(_code_) do {    \
    uint8_t sreg = SREG;            \
    __disable_interrupt();            \
    { _code_ }                        \
    SREG = sreg;                    \
} while(0)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#include-решение мне не нравится - оно неочевидно,

Зато оно не несет никаких следов конкретных компиляторов - вся нюансировка вообще вынесена, не мозолит глаза и не требует вообще никаких правок многочисленных исходникое проекта при добавлении очередного порта. Про независимость от C99 тоже ясно.

легко забыть включить завершающий #include,

Не аргумент - "забыть" можно многое :)

в проекте появляются мелкие файлы, которые собственно исходником не являются.

Обычно такие файлы закидываются район системных \SYS а не в каждый проект.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зато оно не несет никаких следов конкретных компиляторов - вся нюансировка вообще вынесена, не мозолит глаза и не требует вообще никаких правок многочисленных исходникое проекта при добавлении очередного порта. Про независимость от C99 тоже ясно.

Вам _Pragma не нравится, что-ли? Ну, в том смысле, что непереносимая фича. Вообще, это штука давно стандартная и в С, и в С++. Современных компиляторов, которые бы ее не поддерживали, еще поискать.

 

Не аргумент - "забыть" можно многое :)

Вполне аргумент - такие места, где можно забыть, надо сводить к минимуму, в пределе к нулю, а не плодить их.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вам _Pragma не нравится, что-ли?

Ну прагма это достаточно нормально, а вот 8 строчек вместо одной c #include, причем многократно повторенные во многих файлах, да и еще с учетом того, что все эти места придется менять при добавлении портов, мне точно не нравятся :(

Вполне аргумент - такие места, где можно забыть, надо сводить к минимуму, в пределе к нулю, а не плодить их.

В данном случае не аргумент, поскольку количество мест не меняется. Будет закрыватся секция с паковкой #pragma или #include не принципиально. Причем в общем случае #pragma будет не единственной строкой :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну прагма это достаточно нормально, а вот 8 строчек вместо одной c #include, причем многократно повторенные во многих файлах, да и еще с учетом того, что все эти места придется менять при добавлении портов, мне точно не нравятся :(
Стоп. Но
#if        defined( __GNUC__ )
    #define PACKED(_struct_)    \
    _struct_ __attribute__((__packed__, __aligned__(1)));
#elif   defined( __IAR_SYSTEMS_ICC__ )
    #define PACKED(_struct_)    \
    _Pragma("pack (push,1)") _struct_; _Pragma("pack (pop)")
#endif

точно также вносится в один #include-файл в котором и так живет куча полезных вещей. Только этот файл и правится при добавлении портов. Этот файл имеет право жить в /SYS (хотя в этом случае начинаются проблемы с системой контроля версий, но это не принципиально - пусть будет папка /sys в репозитории).

В данном случае не аргумент, поскольку количество мест не меняется. Будет закрыватся секция с паковкой #pragma или #include не принципиально. Причем в общем случае #pragma будет не единственной строкой :(
Нет, как раз. Тут открывание и закрывание секции в одном макросе. И вместо PACK_STRUCT после объявления в вашем варианте надо писать PACKED в начале и после структуры - ')'. И не нужно думать, что для всех компиляторов кроме GCC играет рояль пара #include (даже если мы забудем PACK_STRUCT), а для GCC они и еще PACK_STRUCT. И если мы забудем закрывающую скобку в моем варианте, компилятор грязно выругается на дальнейший текст, а это уже большой плюс (тут я полностью согласен с dxp).

 

Современных компиляторов, которые бы ее не поддерживали, еще поискать.
Как говорится в известной поговорке "свинья всегда грязь найдет". Это я про себя. В смысле нашел - не знаю как _Pragma(), а #pragma pack GCC игнорирует. И толку теперь с этой _Pragma()? :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Стоп.

Ну так дело хозяйское. На то, что сделан макрос с подстановкой структуры, я, каюсь, просто не обратил внимания, посему свои слова на счет одинакового количества строк с #include и твоим #define беру обратно :).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...если кто-то подскажет как из #define PACKED(pack_val, _struct_) вставить значение pack_val в _Pragma("pack (push,1)") вместо '1', буду очень благодарен.

#define PACKED(pack_val, _struct_)          _Pragma("pack (push," #pack_val ")") _struct_; _Pragma("pack (pop)")

попробуйте так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#define PACKED(pack_val, _struct_)          _Pragma("pack (push," #pack_val ")") _struct_; _Pragma("pack (pop)")

попробуйте так.

 

Сергей Борщ, получилось? У меня IARа нет, проверить не могу. Но работать должно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но работать должно.

 

Не, не совсем так. Вот так надо

#define PACKED_QUOTED(V1) #V1
#define PACKED(pack_val, _struct_)          _Pragma(PACKED_QUOTED(pack(push,pack_val))); _struct_; _Pragma("pack (pop)")

PACKED(1,
       typedef struct
       {
     char a;
     char b;
       }C
       );

 

И результат

_Pragma("pack(push,1)"); typedef struct { char a; char b; }C; _Pragma("pack (pop)");

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...