Выравнивание структуры C во внутренней флэш-памяти - PullRequest
5 голосов
/ 15 декабря 2011

У меня есть структура конфигурации, которую я хотел бы сохранить на внутренней флэш-памяти ARM Cortex M3. Согласно спецификации, данные, сохраняемые во внутренней флэш-памяти, должны быть выровнены до 32 бит. Поскольку в моей структуре много логических значений и символов, я не хочу использовать 32 бита для хранения 8 битов ... Я решил упаковать структуру, используя прагму препроцессора __packed, Затем, когда я сохраняю ее целиком структура, я просто должен убедиться, что размер структуры делится на 4 (4 байта = 32 бита), я делаю это, добавляя байты заполнения, если это необходимо. В настоящее время, во время разработки, я сильно изменяю структуру, и чтобы привести ее в соответствие с 32 битами, мне нужно постоянно менять байты заполнения. В настоящее время структура выглядит примерно так

typedef __packed struct
{
uint8_t status;
uint16_t delay;
uint32_t blabla;
uint8_t foo[5];
uint8_t padding[...] // this has to be changed every time I alter the structure.
} CONFIG;

Есть ли лучший способ добиться того, что я делаю? Я довольно новичок во встроенном программировании и хочу убедиться, что я не делаю ошибок.

Редактировать: Обратите внимание. Данные сохраняются в конце внутренней флеш-памяти, поэтому пропуск заполнения не будет работать ...

Ответы [ 4 ]

4 голосов
/ 15 декабря 2011

Решение 1: Вы можете поместить его в объединение, содержащее вашу структуру и массив символов:

union
{
  CONFIG config;
  uint8_t total_size[32];
} my_union;
4 голосов
/ 15 декабря 2011

Возможно, это идея:

typedef __packed struct {
    uint8_t status;
    uint16_t delay;
    uint32_t blabla;
    uint8_t foo[5];
} CONFIG;

typedef __packed struct {
    CONFIG cfg;
    uint8_t padding[4 - (sizeof(CONFIG) % 4)]
} CONFIGWRAPPER;
3 голосов
/ 15 декабря 2011

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

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

Это требует некоторых знаний о том, как требования к выравниванию вашей платформы икомпилятор, например, избавиться от массива заполнения и изменить

typedef struct
{
uint8_t status;
uint16_t delay;
uint32_t blabla;
uint8_t foo[5];
uint8_t padding[...];
} CONFIG;

на

typedef struct
{
uint32_t blabla;
uint16_t delay;
uint8_t status;
uint8_t foo[5];
} CONFIG;

Затем скажите компилятору, что для этой структуры требуется 4-байтовое значение (в этом случае оно, вероятно, ужетак как первый элемент имеет 4-байтовое или более требование выравнивания).например, с использованием gcc attribute((__aligned__(4))

Затем напишите небольшую тестовую программу, которая проверяет ваши требования к выравниванию (это просто небольшая программа, которая использует sizeof () и alignof () в вашей структуре), этодаже сказать вам, если вам нужно добавить инструкцию для структуры для выравнивания.Запустите эту программу как часть сборки / упаковки.

1 голос
/ 15 декабря 2011

Решение 2. Вы можете использовать особенность IAR #pragma location, чтобы разместить данные конфигурации в определенном месте, например, 32 от конца флэш-памяти.Таким образом, вам не нужно дополнять структуру:

/* Fictitious end of flash location. */ 
#pragma location=0x1234FFE0
struct [... your struct goes here ...]
...