IAR EW ARM: выравнивание полей в структурах
Написал microsin   
17.03.2009

По умолчанию для ARM все поля в структурах компилятор C выравнивает на границу 4 байта - это позволяет оптимизировать код, который поддерживает обращение к полям структуры. Если об этом забыть и не учитывать в программе (например, при работе со всеми полями структуры как одним блоком данных), то могут возникать неожиданные ошибки.

Выравнивание - это просто обеспечение кратности адресов определенному числу. Например, "выравнивание полей структуры на 4 байта" означает, что физический адрес каждого поля структуры делится нацело на 4.

По умолчанию в IAR для всех объектов памяти размером от 4 байт и более выравнивание включено. Это очень важно для буферов, работающих с прямым доступом к памяти (PDC) периферии ARM. Начальный адрес буфера памяти, работающий с PDC, должен быть обязательно выровнен на 4.

Устранить поведение по умолчанию и убрать выравнивание позволяет ключевое слово __packed при объявлении структуры или директивы #pragma pack и #pragma data_alignment для модуля. В этом случае "пустоты", связанные с выравниванием, в структуре исчезают (экономится память, и не надо помнить о выравнивании), но несколько увеличивается код обработки структур. Пример использования __packed:
typedef __packed struct _Params
{
    u32 paramseed;
    u32 versionARM;
    u32 versionDSP;
    u8  backlight;
    u8  contrast;
    u8 minContrast;
    u8 maxContrast;
    char ProducerName[15];
    char ProducerURL[15];
    char ProducerEmail[15];
    u32 usbProdID;
    u32 usbVendorID;
    u16 CRC;
} TParams;

Будьте внимательными с рамещением буферов в упакованной (__packed) структуре, если эти буфера работают с прямым доступом к памяти, лучше этого избегайте (определяйте буфер отдельно от упакованной структуры). Если все-таки решили поместить буфер в структуру с атрибутом __packed, то размещайте буфер в начале структуры, что гарантирует выравнивание его адреса на 4. Тогда прямой доступ к памяти будет всегда работать корректно.

Последнее обновление ( 21.10.2010 )