Программирование ARM IAR EW ARM: выравнивание полей в структурах Sat, June 24 2017  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


IAR EW ARM: выравнивание полей в структурах Печать
Добавил(а) microsin   

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

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

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

В разных версиях IAR Embedded Workbench синтаксис для управления выравниванием может быть устроен по разному. В этой статье рассматриваются два варианта синтаксиса: для IAR версии 4.41A и для IAR версии 5.50.

[IAR 4.41A]

Для управления выравниванием используется специальная директива управления компилятором #pragma pack. По умолчанию, если #pragma pack не указано, то включено выравнивание на границу 32-битного слова (4 байта). Могут быть следующие варианты использования pack:

#pragma pack()  //восстанавливает состояние по умолчанию (выравнивание на 32 бита)
#pragma pack(n) //выравнивание на 1, 2, 4, 8 или 16 байт (указывается вместо n)
#pragma pack({push|pop}[,name] [,n])

[IAR 5.50]

Устранить поведение по умолчанию и убрать выравнивание позволяет ключевое слово __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) структуре, если эти буфера работают с прямым доступом к памяти (DMA), лучше этого избегайте (определяйте буфер отдельно от упакованной структуры). Если все-таки решили поместить буфер в структуру с атрибутом __packed, то размещайте буфер в начале структуры, что гарантирует выравнивание его адреса на 4. Тогда прямой доступ к памяти будет всегда работать корректно.

[Ссылки]

1. Как выровнять (align) размер памяти на 4 байта?

 

Добавить комментарий


Защитный код
Обновить

Top of Page