Принудительное выравнивание членов структуры (с помощью компилятора IAR) - PullRequest
0 голосов
/ 19 сентября 2019

Рассмотрим этот typedef:

#pragma pack(4)
typedef struct
{
  uint8  dataArea0[11];
  uint8  dataArea1[12];
  uint8  dataArea2[13];
  uint8  dataArea3[14];

} myStruct;

У меня есть массивы не 2 ^ n размера, которые я хотел бы использовать из других библиотек.Из этих библиотек эти данные могут быть получены как, например, структуры или все, что мне нужно.Проблема возникает, когда один из этих членов структуры попадает на не 4-байтовый выровненный адрес И содержит типы данных, которые не удовлетворены их выравниванием адреса.

Поэтому я хотел бы принудительно выровнять с прагмой пакета, но это не помогает (по крайней мере, в компиляторе IAR - из руководства: Используйте эту директиву pragma, чтобы указать максимальное выравнивание элементов struct и union. ).Я также пытался использовать прагму data_alignment, но, похоже, это для переменных, а не для членов структуры.

Кто-нибудь знает хороший трюк с компилятором для принудительного выравнивания элементов структуры?

Быстрая ссылка на руководство по компилятору для заинтересованных: IAR AVR32 Compiler Ref

Редактировать: В итоге я использовал это в качестве альтернативы

#define ROUND_UP_NEXT_FOUR(x) ((x + 3) & ~0x03)

typedef struct
{
  uint8  dataArea0[ROUND_UP_NEXT_FOUR(11)];
  uint8  dataArea1[ROUND_UP_NEXT_FOUR(12)];
  uint8  dataArea2[ROUND_UP_NEXT_FOUR(13)];
  uint8  dataArea3[ROUND_UP_NEXT_FOUR(14)];

} myStruct;

Таким образом, я уверен, что заполнение будет происходить в 4-выровненный адрес.

Edit2:

Пример того, как это может пойти не так:

struct otherStruct
{
  uint16 dataBuf0;
  uint32 dataBuf1;
  uint32 dataBuf2;
  uint32 dataBuf3;
  uint32 dataBuf4[10];
};

myStruct* myStructInstance = 0x00000000; //some address
//address of this is 0x0B
struct otherStruct* oS = (struct otherStruct*) myStructInstance.dataArea1;
//we assign to a 2 byte variable that is 
//located at address that is not 2 byte aligned -> error!
os->dataBuf0 = 10; 

В этом случае мы получаем ошибку времени выполнения (худший (или лучший?) Случай, сбой).

1 Ответ

1 голос
/ 23 сентября 2019

К сожалению, компилятор IAR AVR32 не поддерживает ключевое слово _Alignas.Однако, когда расширения языка IAR включены, он поддерживает анонимные объединения, и это может использоваться для принудительного выравнивания отдельных полей структуры.Хитрость в том, что выравнивание объединения - это самое строгое (наибольшее) выравнивание любого из его полей.Таким образом, оборачивая каждое поле dataArea? в анонимный союз фиктивным полем с 32-битным выравниванием, можно принудительно настроить выравнивание каждого поля dataArea? на 32-битное.Пример показан ниже.Он включает в себя как необработанные объявления анонимных объединений, так и макромагию, чтобы упростить объявление при большом количестве полей.

#include <stdint.h>

#define GLUE_B(x,y) x##y
#define GLUE(x,y) GLUE_B(x,y)

#define ALIGNED(FIELD, ALIGN_TYPE) union { FIELD; ALIGN_TYPE GLUE(a,__LINE__); }
#define ALIGNED32(FIELD) ALIGNED(FIELD, uint32_t)

typedef struct
{
  ALIGNED(uint8_t dataArea0[11], uint32_t);
  ALIGNED32(uint8_t dataArea1[12]);
  union { uint8_t dataArea2[13]; uint32_t a2;};
  union { uint8_t dataArea3[12]; uint32_t a3;};
} myStruct;
...