I have an array of structs that I need to initialize at compile-time (no memset) to 0xFF. This array will be written as part of the program over erased flash. By setting it to 0xFF, it will remain erased after programming, and the app can use it as persistent storage. I've found two ways to do it, one ugly and one a workaround. I'm wondering if there's another way with syntax I haven't found yet. The ugly way is to use a nested initializer setting every field of the struct. However, it's error prone and a little ugly. My workaround is to allocate the struct as an array of bytes and then use a struct-typed pointer to access the data. Linear arrays of bytes are much easier to initialize to a non-zero value.
To aid anyone else doing the same thing, I'm including the gcc attributes used and the linker script portion.
Example struct:
struct BlData_t {
uint8_t version[3];
uint8_t reserved;
uint8_t markers[128];
struct AppData_t {
uint8_t version[3];
uint8_t reserved;
uint32_t crc;
} appInfo[512] __attribute__(( packed ));
} __attribute__(( packed ));
Initialize to 0xFF using the best way I know:
// Allocate the space as an array of bytes
// because it's a simpler syntax to
// initialize to 0xFF.
__attribute__(( section(".bootloader_data") ))
uint8_t bootloaderDataArray[sizeof(struct BlData_t)] = {
[0 ... sizeof(struct BlData_t) - 1] = 0xFF
};
// Use a correctly typed pointer set to the
// array of bytes for actual usage
struct BlData_t *bootloaderData = (struct BlData_t *)&bootloaderDataArray;
No initialization necessary because of (NOLOAD):
__attribute__(( section(".bootloader_data") ))
volatile const struct BLData_t bootloader_data;
Addition to linker script:
.bootloader_data (NOLOAD):
{
FILL(0xFF); /* Doesn't matter because (NOLOAD) */
. = ALIGN(512); /* start on a 512B page boundary */
__bootloader_data_start = .;
KEEP (*(.bootloader_data)) /* .bootloader_data sections */
KEEP (*(.bootloader_data*)) /* .bootloader_data* sections */
. = ALIGN(512); /* end on a 512B boundary to support
runtime erasure, if possible */
__bootloader_data_end = .;
__bootloader_data_size = ABSOLUTE(. - __bootloader_data_start);
} >FLASH
How to use the starting address, ending address and size in code:
extern uint32_t __bootloader_data_start;
extern uint32_t __bootloader_data_end;
extern uint32_t __bootloader_data_size;
uint32_t _bootloader_data_start = (uint32_t)&__bootloader_data_start;
uint32_t _bootloader_data_end = (uint32_t)&__bootloader_data_end;
uint32_t _bootloader_data_size = (uint32_t)&__bootloader_data_size;
Update:
It turns out that I was asking the wrong question. I didn't know about the (NOLOAD) linker section attribute which tells the program loader not to burn this section into flash. I accepted this answer to help others realize my mistake and possibly theirs. By not even programming the section, I don't have to worry about the initialization at all.
I've upvoted the union answers since they seem to be a good solution to the question I asked.
I would use a union of your struct together with an array of the correct size, then initialize the array member.
union {
struct BlData_t data;
uint8_t bytes[sizeof(struct BlData_t)];
} data_with_ff = {
.bytes = {
[0 ... sizeof(struct BlData_t) - 1] = 0xff
}
};
You can then access your struct as data_with_ff.data, defining a pointer or macro for convenience if you wish.
Try on godbolt
(Readers should note that the ... in a designated initializer is a GCC extension; since the question was already using this feature and is tagged gcc I assume that is fine here. If using a compiler that doesn't have it, I don't know another option besides .bytes = { 0xff, 0xff, 0xff ... } with the actual correct number of 0xffs; you'd probably want to generate it with a script.)
The sensible way to do this is to find the command in the linker script telling it to back off from touching that memory in the first place. Because why would you want it do be erased only to filled up with 0xFF again? That only causes unnecessary flash wear for nothing.
Something along the lines of this:
.bootloader_data (NOLOAD) :
{
. = ALIGN(512);
*(.bootloader_data *)
} >FLASH
If you truly need to do this initialization and in pure standard C, then you can wrap your inner struct inside an anonymous union (C11), then initialize that one using macro tricks:
struct BlData_t {
uint8_t version[3];
uint8_t reserved;
uint8_t markers[128];
union {
struct AppData_t {
uint8_t version[3];
uint8_t reserved;
uint32_t crc;
} appInfo[512];
uint8_t raw [512];
};
};
#define INIT_VAL 0xFF, // note the comma
#define INIT_1 INIT_VAL
#define INIT_2 INIT_1 INIT_1
#define INIT_5 INIT_2 INIT_2 INIT_1
#define INIT_10 INIT_5 INIT_5
/* ... you get the idea */
#define INIT_512 INIT_500 INIT_10 INIT_2
const struct BlData_t bld = { .raw = {INIT_512} };
This method could also be applied on whole struct basis, if you for example want to initialize a struct array with all items set to the same values at compile-time.
I am writing a program to read a bmp header. I've written some code that was working when it was all in main. How to implement this code as a function of its own and then implementing it onto main?
Here is the whole code :
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdin.h>
struct bmp_header {
uint16_t type;
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
uint32_t dib_size;
uint32_t width;
uint32_t height;
uint16_t planes;
uint16_t bpp;
uint32_t compression;
uint32_t image_size;
uint32_t x_ppm;
uint32_t y_ppm;
uint32_t num_colors;
uint32_t important_colors;
};
void read_bmp(FILE *BMPFile,struct bmp_header* Header) {
fread(&(Header->type), 2, 1, BMPFile);
fread(&(Header->size),4,1,BMPFile);
fread(&(Header->reserved1),2,1,BMPFile);
fread(&(Header->reserverd2),2,1,BMPFile);
fread(&(Header->offset),4,1,BMPFile);
fread(&(Header->dib_size),4,1,BMPFile);
fread(&(Header->width),4,1,BMPFile);
fread(&(Header->height),4,1,BMPFile);
fread(&(Header->planes),2,1,BMPFile);
fread(&(Header->bpp),2,1,BMPFile);
fread(&(Header->compression),4,1,BMPFile);
fread(&(Header->image_size),4,1,BMPFile);
fread(&(Header->x_ppm),4,1,BMPFile);
fread(&(Header->y_pp),4,1,BMPFile);
fread(&(Header->num_colors),4,1,BMPFile);
fread(&(Header->important_colors),4,1,BMPFile);
}
int main() {
FILE *BMPFile = fopen("image.bmp","rb");
if(BMPFile == NULL)
{
return;
}
struct bmp_header* Header;
read_bmp(BMPFile,Header);
fclose(BMPFile);
return 0;
}
The relevant parts of the version of the program with all reading action in main, that worked as expected, is reported below
int main( void )
{
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
{
return 0;
}
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
fread(&Header.size),4,1,BMPFile);
fread(&Header.reserved1),2,1,BMPFile);
fread(&Header.reserverd2),2,1,BMPFile);
fread(&Header.offset),4,1,BMPFile);
fread(&Header.dib_size),4,1,BMPFile);
fread(&Header.width),4,1,BMPFile);
fread(&Header.height),4,1,BMPFile);
fread(&Header.planes),2,1,BMPFile);
fread(&Header.bpp),2,1,BMPFile);
fread(&Header.compression),4,1,BMPFile);
fread(&Header.image_size),4,1,BMPFile);
fread(&Header.x_ppm),4,1,BMPFile);
fread(&Header.y_pp),4,1,BMPFile);
fread(&Header.num_colors),4,1,BMPFile);
fread(&Header.important_colors),4,1,BMPFile);
/* Header fields print section */
/* ... */
}
Whenever a working code stops working, it is useful to focus on the changes between the two versions of the code. So, why does your original code work correctly? It looks like this:
int main( void )
{
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
{
return 0;
}
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
...
}
You declare Header, of type struct bmp_header, in main's stack (as local variable). In this way the structure will be for sure allocated during all program's lifetime.
You memset it to 0
You pass Header's fields addresses directly to fread
In the new version of the program you have a function defined as
void read_bmp(FILE *BMPFile,struct bmp_header* Header);
so you need a pointer to struct bmp_header to be passed to it. For this reason you declare
struct bmp_header* Header;
and call read_bmp(BMPFile,Header);.
What is the different with the working version? Well, the pointer! Declaring a pointer you say to the compiler that it contains an address, in this case the address of the structure required by read_bmp().
But you never say to the compiler what the address is, so that freads within read_bmp() will write to random location causing a segmentation fault.
What to do
You need to pass to read_bmp() a valid struct bmp_header address, and you have two options.
You can allocate Header in the stack like you did before, and pass its address to read_bmp(), through & operator. It should have been your first attempt, since it was really similar to your working solution.
struct bmp_header Header;
read_bmp(BMPFile, &Header);
You can declare Header as a pointer, but you will need to dynamically allocate its memory through malloc:
struct bmp_header * Header = malloc(sizeof(struct bmp_header));
read_bmp(BMPFile, Header);
You have to create struct bmp_header* type function. Next create struct bmp_header pointer in your function & allocate memory (header size == 54B) for returned reference.
I am working with the function
int max30205_write_trip_low_thyst(float temperature)//, I2C &i2c_bus)
{
max30205_raw_data raw;
temperature /= MAX30205_CF_LSB;
raw.swrd = int16_t(temperature); // here -> expected expression before 'int16_t'
return max30205_write_reg16(raw.swrd, MAX30205_REG_THYST_LOW_TRIP);//, i2c_bus);
}
and when I try to compile I get the following error
expected expression before 'int16_t'
Why is this?
looking the header file I see that
#define MAX30205_CF_LSB (0.00390625F)
typedef union max30205_raw_data {
struct {
uint8_t lsb;
uint8_t msb;
};
struct {
uint16_t magnitude_bits:15;
uint16_t sign_bit:1;
};
uint16_t uwrd;
int16_t swrd;
} max30205_raw_data;
Because int16_t(temperature); is not valid C syntax. You need to do (int16_t)temperature.
I was working with some (of what I thought was) bad code that had a union like:
union my_msg_union
{
struct message5;
char buffer[256]
} message;
The buffer was filled with 256 bytes from comms. The struct is something like:
struct message5 {
uint8 id;
uint16 size;
uint32 data;
uint8 num_ids;
uint16 ids[4];
} message5d
The same code was being compiled on heaps of architectures (8bit AVR, 16bit phillips, 32bit arm, 32bit x86 and amd64).
The problem I thought was the use of the union: The code just a blob of serial recieved bytes into the buffer, then reads the values out through the struct, without considering alignment/padding of the struct.
Sure enough, a quick look at sizeof(message5d) on different systems gave different results.
What surprised me however is that whenever the union with the char [] existed, all instances of all structs of that type, on all systems, dropped their padding/alignment, and made sure to be sequential bytes.
Is this a C standard or just something that compiler authors have put in to 'help'?
This code demonstrates the opposite behaviour from the one you describe:
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
struct message5
{
uint8_t id;
uint16_t size;
uint32_t data;
uint8_t num_ids;
uint16_t ids[4];
};
#if !defined(NO_UNION)
union my_msg_union
{
struct message5 msg;
char buffer[256];
};
#endif /* NO_UNION */
struct data
{
char const *name;
size_t offset;
};
int main(void)
{
struct data offsets[] =
{
{ "message5.id", offsetof(struct message5, id) },
{ "message5.size", offsetof(struct message5, size) },
{ "message5.data", offsetof(struct message5, data) },
{ "message5.num_ids", offsetof(struct message5, num_ids) },
{ "message5.ids", offsetof(struct message5, ids) },
#if !defined(NO_UNION)
{ "my_msg_union.msg.id", offsetof(union my_msg_union, msg.id) },
{ "my_msg_union.msg.size", offsetof(union my_msg_union, msg.size) },
{ "my_msg_union.msg.data", offsetof(union my_msg_union, msg.data) },
{ "my_msg_union.msg.num_ids", offsetof(union my_msg_union, msg.num_ids) },
{ "my_msg_union.msg.ids", offsetof(union my_msg_union, msg.ids) },
#endif /* NO_UNION */
};
enum { NUM_OFFSETS = sizeof(offsets) / sizeof(offsets[0]) };
for (size_t i = 0; i < NUM_OFFSETS; i++)
printf("%-25s %3zu\n", offsets[i].name, offsets[i].offset);
return 0;
}
Sample output (GCC 4.8.2 on Mac OS X 10.9 Mavericks, 64-bit compilation):
message5.id 0
message5.size 2
message5.data 4
message5.num_ids 8
message5.ids 10
my_msg_union.msg.id 0
my_msg_union.msg.size 2
my_msg_union.msg.data 4
my_msg_union.msg.num_ids 8
my_msg_union.msg.ids 10
The offsets within the union are the same as the offsets within the structure, as the C standard requires.
You would have to give a complete compiling counter-example based on the code above, and specify which compiler and platform you are compiling on to get your deviant answer — if indeed you can reproduce the deviant answer.
I note that I had to change uint8 etc to uint8_t, but I don't think that makes any difference. If it does, you need to specify which header you get the names like uint8 from.
Code updated to be compilable with or without union. Output when compiled with -DNO_UNION:
message5.id 0
message5.size 2
message5.data 4
message5.num_ids 8
message5.ids 10