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. Тогда прямой доступ к памяти будет всегда работать корректно. [Ссылки] |