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

标签 c embedded microchip pic24 xc16

我目前正在尝试使用整个微芯片堆栈(xc16、mcc、mplab X IDE 等)为 PIC24F 开发固件(不一定相关,但我在 debian 22 上工作)

并不重要,但我想将一些数据放置在我将放置在固件上特定位置的特定部分。

假设我在 file.h 中定义了一个结构体 my_struct ,如下所示:

#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)

然后在我的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 }
};

当我创建目标文件file.o时, 我期望有一个大小为 32 并填充 0xBA 的 my_section 部分。因此,我尝试使用 objdump 检查生成的 file.o 以确保数据是我想要的数据

$ 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  ................

但 XC16 似乎为每个数据字节添加了 00 填充,并且该部分的大小增加了一倍。

我知道填充是为了保持数据对齐以达到优化目的,但对于这种特定情况,我确实需要打包这些数据,并且大小需要为 32。

问题不仅仅出现在 file.o 中,即使我一直到编译过程结束,我也设法将该部分放置在我想要的位置(感谢更新的链接器脚本)但它仍然包含不需要的填充。所以我很确定问题不在于链接器,而在于编译过程本身

我真的尝试了很多东西。

我尝试使用以下方式打包结构: #pragma pack(1)(带或不带推送/弹出) 我还尝试使用__packed__atribute__((packed(1)))

我尝试添加 aligned(1) 关键字或 volatile 说明符 我什至尝试使用一些 uint32_t arr[8]uint16_t arr[16]uint8_t arr[32] 而不是结构。< br/> 我尝试了很多mplab项目配置(我不记得是哪些,可能是全部) 我分别和一起尝试了所有这些选项......

但是输出没有任何改变。我检查了文档或任何我能找到的东西,但我无法让它工作。 这在 xc16 下是否可能,还是我应该放弃?

===编辑===

感谢@pmacfarlane 和@thebusybee,我进一步挖掘,这是我发现的:

我声明了两个相同的结构

  • 一个 (s1) 与 __attribute__((used,section("my_section")),
  • 另一个 (s2) 没有属性

当我编译并检查file.o

对于来自 s1my_section 输出,我得到了与之前相同的输出。
一些数据已添加到 .const 部分,来自 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  ................

所以这里没什么新东西,但如果我检查最终的 Sprite ,就会发现有区别:

$ 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  ................

请注意,我在本示例中使用默认链接描述文件。

我尝试在其中添加一些代码,甚至完全修改它,但由于没有按预期工作,所以我回到了默认代码。
为了最小的可重复性目的,我什至最终删除了有关部分管理的所有内容,结果保持不变。所以我认为这些行为来自 xc16 链接器默认行为,而不是来自链接器脚本。
我很乐意将链接器脚本添加到问题中,但它有 3k 行长。
因此,看起来链接过程正在将 ba00ba00 打包到 baba0000 中,用于内置部分,例如 .const,但不是我的自定义部分。

不知道它是否相关,但我认为这会带来更多信息。有什么提示吗?

最佳答案

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

正如 @thebusybee 所指出的,问题出在我使用的图片使用 24 位字这一事实。

正如 @pmacfarlane 所说,解决方案就在这个 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

因此,通过如下声明我的结构:

__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 

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

关于c - 如何从 XC16 上的自定义部分删除不需要的数据填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76220363/

相关文章:

c - 如何对数字进行降序排序

c++ - const 对象的代码大小

memory-management - 适用于无需动态内存分配的开发的语言

embedded - 使用定时器计时会中断嵌入式微 Controller

c - 在 C 中 float 或 double 类型到底如何工作?

c - 如何在 Eclipse 中运行 cunit 测试?

c++ - 使用 procf/<pid>/status 了解进程状态

embedded - 充分利用糟糕的 "checksum"算法

在 C 中创建文件

security - 从嵌入式芯片中提取 secret