如何从XC16自定义部分中删除不需要的数据填充

huangapple go评论65阅读模式
英文:

How to remove unwanted data padding from custom sections on XC16

问题

It seems you're dealing with some alignment and padding issues when trying to place data in a specific section in your PIC24F firmware using XC16. Unfortunately, XC16 and the underlying toolchain have their own behavior when it comes to alignment and padding, and it can be challenging to control them entirely.

You've already explored various methods like #pragma pack, __attribute__((packed(1))), and different project configurations. Since you're still encountering issues, it's possible that XC16 has its own internal mechanisms that may override these settings.

Without detailed knowledge of the specific toolchain behavior beyond my last training data in September 2021, it's challenging to provide a guaranteed solution. You may want to consult the XC16 documentation or seek help on relevant forums or communities where developers have experience with this specific toolchain and its quirks.

It's possible that there have been updates or insights in the XC16 community since my last update, so reaching out to fellow developers who specialize in PIC microcontrollers and XC16 might be your best approach to resolving this issue.

英文:

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 ?

答案1

得分: 2

以下是您要翻译的内容:

为了将此线程标记为已解决,我将发布此答案,但不归功于我。

正如@thebusybee所指出的,问题是因为我使用的图片使用了24位字。

正如@pmacfarlane所说,解决方案在这个数据表中。

对于16位设备,在Flash存储器中使用了24位字。该架构支持将Flash的部分区域映射到数据空间中,但这种映射仅有16位宽,以适应数据空间的尺寸,除非使用__pack_upper_byte修饰符

因此,通过以下方式声明我的结构体:

__pack_upper_byte 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 }
};

我得到了


objdump -s -j my_section binary.elf

binary.elf:     file format elf32-little

Contents of section my_section :
 0000 bababa00 bababa00 bababa00 bababa00  ................
 0010 bababa00 bababa00 bababa00 bababa00  ................
 0020 bababa00 bababa00 baba0000 

这比以前好多了,非常感谢您的帮助!

英文:

In order to mark this thread as resolved, I will post this answer, but the credit is not for me.

As pointed out by @thebusybee, the issue was coming from the fact that the pic I was using, uses 24bits words.

And as @pmacfarlane said, the solution was in this datasheet.

> For 16-bit devices, a 24-bit word is used in Flash memory. The architecture supports the
mapping of areas of Flash into the data space, but this mapping is only 16 bits wide to
fit in with data space dimensions, unless the __pack_upper_byte qualifier is used

So by declaring my struct as follows :

__pack_upper_byte 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 }
};

I ended up with


objdump -s -j my_section binary.elf

binary.elf:     file format elf32-little

Contents of section my_section :
 0000 bababa00 bababa00 bababa00 bababa00  ................
 0010 bababa00 bababa00 bababa00 bababa00  ................
 0020 bababa00 bababa00 baba0000 

Which is way better than before, thank you very much for your help !

huangapple
  • 本文由 发表于 2023年5月10日 23:42:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220363.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定