I am currently trying to dev a firmware for a PIC24F using the whole microchip stack (xc16, mcc, mplab X IDE, etc ...) (not necessarily relevant but i work on a debian 22)
Doesn't really matter why but i want to place some data on a specific section that i will place at specific location on my firmware.
Let's imagine i have a struct my_struct defined in file.h as follow :
#pragma pack(push, 1) // using pragma pack to pack the struct and avoid padding
typedef struct {
uint16_t magic;
uint32_t length;
uint32_t crc;
uint16_t word_1;
uint16_t word_2;
uint8_t byte_1;
uint8_t byte_2;
uint8_t byte_3;
uint8_t array[15];
} my_struct;
#pragma pack(pop)
then in my file.c :
const my_struct __attribute__((section("my_section"))) instance = {
.magic = 0xbaba,
.crc = 0xbabababa,
.length = 0xbabababa,
.byte_1 = 0xba,
.byte_2 = 0xba,
.byte_3 = 0xba,
.word_1 = 0xbaba,
.word_2 = 0xbaba,
.array = {0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba }
};
When I create the object file file.o,
I expect having a section my_section of size 32 and filled with 0xBA. So I try to inspect the produced file.o using objdump to ensure that the data are the one that I want
$ size -A file.o
section size addr
[...]
my_section 64 0
$ objdump -s -j my_section file.o
Contents of section my_section:
0000 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0010 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0020 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0030 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
But it seems like XC16 added a 00 padding for each data byte and that it doubled the size of the section.
I know that padding is to keep data aligned for optimization purpose, but for this specific case, I really need those data to be packed and the size needs to be 32.
The issue is not only in file.o, even if I go until the end of the compilation process, I manage to have the section located where i want (thanks to an updated linker script) but it still contains the unwanted padding. So i'm pretty sure the issue is not about linker, but about the compilation process itself
I tried a loooot of things, really.
I tried to pack the structure using :
#pragma pack(1) (with or without push/pop)
I also tried to use __packed
or __atribute__((packed(1)))
I tried to add the aligned(1) keyword, or the volatile specifier
I even tried to use some uint32_t arr[8], uint16_t arr[16] and uint8_t arr[32] instead of a struct.
I tried a lot of mplab project configuration (i can't remember which ones, probably all of them)
I tried all those options separately and together ...
But nothing changes the output. I checked documentation or anything i could, but i can't make it work. Is this even possible under xc16 or should i give up?
=== EDIT ===
Thanks to @pmacfarlane and @thebusybee, I dug a little further and here is what i found:
I declared two identical structs
- one (
s1) with the__attribute__((used, section("my_section")), - the other (
s2) with no attribute
when i compile and inspect file.o
I got the same output as before for the my_section output, coming from s1.
And some data has been added to the .const section, coming from s2:
$ objdump -s -j .const file.o
Contents of section .const:
0000 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0010 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0020 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0030 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
So nothing new here, but if I inspect the final elf, there is a difference :
$ objdump -s -j .const firmware.elf
Contents of section .const:
82cc baba0000 baba0000 baba0000 baba0000 ................
82dc baba0000 baba0000 baba0000 baba0000 ................
82ec baba0000 baba0000 baba0000 baba0000 ................
82fc baba0000 baba0000 baba0000 baba0000 ................
$ objdump -s -j my_section firmware.elf
Contents of section my_section:
0000 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0010 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0020 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
0030 ba00ba00 ba00ba00 ba00ba00 ba00ba00 ................
Please note that i am using the default linker script for this example.
I tried to add some code in it , even to modify it entirely but, as nothing worked as expected, I went back to the default one.
For minimal reproducible purpose, i even ended up removing everything about section management, and the result stays the same. So i think the behaviors is coming from the xc16 linker default behavior and not from the linker script.
I would gladly add the linker script to the question but it is 3k lines long.
So, it looks like the linking process is packing ba00ba00 into baba0000 for built-in section such as .const but not for my custom section.
Don't know if it's relevant, but I assumed that this would bring more information. Any hints ?