Alignment of C structure in Internal FLASH memory
Asked Answered
C

4

7

I have a configuration structure I would like to save on the internal flash of ARM cortex M3. According to the specifications, the data save in the internal flash, must be aligned to 32bit. Because I have lot's of boolean, and chars in my structure,I don't want to use 32bits to store 8 bits... I decided to pack the structure using the __packed preprocessor pragma, Then When I save it as a whole structure, I just have to make sure that the structure size is divisible by 4 (4 bytes = 32bits), I do it by adding padding bytes if needed. Currently, during development I alter the structure a lot, and to make it aligned with the 32 bits, I need to change the padding bytes all the time. Currently, the structure look slike this

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;

Is there a better way to achieve what I'm doing ? I'm quite new in Embedded programming, and I want to make sure that I'm not doing mistakes.

Edit: Please note. The data is persisted in the end of the internal-flash, so omitting the padding will not work...

Compensate answered 15/12, 2011 at 7:58 Comment(1)
I believed that your understanding is not correct. Instructions in the flash memory may have to be aligned and that will be guaranteed by compiler. But data stored in flash even unaligned can be managed by arm cortex m3 cores. Which company's MCU do you use?Silvie
B
4

Perhaps this is an idea:

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;
Botulism answered 15/12, 2011 at 8:19 Comment(1)
Actually when I think of it. If it's already aligned then we add 4 bytes for nothingCompensate
I
5

Firstly, packed alignment is usually to be avoided, if you end up with data not aligned to their natural boundaries, some CPUs will just issue a trap when you try to access them.

First, store the members in an order so the compiler doesn't add gaps for alignment (or if it does, it adds it at the end). If you can, have the 1. member have the alignment requirement you desire - as that forces the compiler to at least give the struct that much alignment.

This requires some knowledge on how the alignment requirements of your platform and compiler, e.g. get rid of the padding array, and change

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

to

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

Then tell the compiler that this struct needs 4 byte aligment (in this case it likely already will as the first member has 4 byte or more alignment requirement). e.g. with gcc use attribute((__aligned__(4))

Then write a small test program that validates the alignment requirements you have (which is just a small program that uses sizeof() and alignof() on your struct), this'll even tell you if you need to add instruction for the struct to be aligned. Run that program as part of the build/packaging.

Inconformity answered 15/12, 2011 at 8:54 Comment(1)
Excellent answer and well stated. The sample test program is critical to your success or failure, you CANNOT skip this step if you want to do what you are trying to do with structs across compile domains (consider hardware to be a compile domain).Entrails
B
4

Perhaps this is an idea:

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;
Botulism answered 15/12, 2011 at 8:19 Comment(1)
Actually when I think of it. If it's already aligned then we add 4 bytes for nothingCompensate
N
4

Solution 1: You could put it inside a union containing your structure and an array of characters:

union
{
  CONFIG config;
  uint8_t total_size[32];
} my_union;
Novosibirsk answered 15/12, 2011 at 8:28 Comment(2)
That's interesting, let's say that the sizeof(CONFIG) is less than the size of total_size. and I set the config in the union. what will be the sizeof(my_union) ?Compensate
If CONFIG is smaller than total_size then sizeof(my_union) will be the size of total_size, concretely 32.Novosibirsk
N
1

Solution 2: You could use the IAR-specific feature #pragma location to place the config data at a specific location, like 32 from the end of the flash. That way you would not need to pad the structure in any way:

/* Fictitious end of flash location. */ 
#pragma location=0x1234FFE0
struct [... your struct goes here ...]
Novosibirsk answered 15/12, 2011 at 8:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.