我目前正在尝试使用整个微芯片堆栈(xc 16,mcc,mplab X IDE等)为PIC 24 F开发固件(不一定相关,但我在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的my_section
部分,并填充0xBA。因此,我尝试使用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 ................
但是看起来XC 16为每个数据字节添加了一个00
填充,并且它使节的大小增加了一倍。
我知道填充是为了保持数据对齐以达到优化的目的,但对于这个特定的情况,我真的需要将这些数据打包,并且大小需要为32。
这个问题不仅存在于file.o
中,即使我一直到编译过程结束,我设法将节定位在我想要的位置(感谢更新的链接器脚本),但它仍然包含不需要的填充。所以我很确定问题不是关于链接器,而是关于编译过程本身
我尝试了很多东西,真的。
我尝试使用以下方法打包结构:#pragma pack(1)
(有或没有push/pop)我还尝试使用__packed
或__atribute__((packed(1)))
我尝试添加aligned(1)
关键字,或者volatile
说明符,我甚至尝试使用一些uint32_t arr[8]
,uint16_t arr[16]
和uint8_t arr[32]
来代替结构。
我尝试了很多mplab项目配置(我不记得是哪些,可能是所有的)我分别和一起尝试了所有这些选项...
但是输出没有任何变化。我查了所有的文件,但是我不能让它工作。这在xc 16下是可能的还是我应该给予?
===编辑===
感谢@pmacfarlane和@thebusybee,我进一步挖掘,这是我发现的:
我声明了两个相同的结构
- 一个(
s1
)与__attribute__((used, section("my_section"))
, - 另一个(
s2
)没有属性
当我编译并检查file.o
时
对于my_section
输出,我得到了与之前相同的输出,来自s1
。
一些数据已经添加到.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 ................
所以这里没有什么新的,但如果我检查最后一个精灵,有一个区别:
$ 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 ................
请注意,我在这个例子中使用了默认的链接器脚本。
我试图在其中添加一些代码,甚至完全修改它,但由于没有任何预期的工作,我回到了默认的。
为了最小化可复制性,我甚至最终删除了关于节管理的所有内容,结果保持不变。因此,我认为这些行为来自xc 16链接器的默认行为,而不是链接器脚本。
我很乐意将链接器脚本添加到问题中,但它有3 k行长。
因此,看起来链接过程是将ba 00 ba 00打包到baba 0000中,用于内置节(如.const
),而不是用于我的自定义节。
不知道这是否相关,但我认为这会带来更多信息。有什么提示吗?
1条答案
按热度按时间bvn4nwqk1#
为了将此帖子标记为已解决,我将发布此答案,但功劳不是我的。
正如@thebusybee所指出的,这个问题来自于我使用的图片,使用24位字。
正如@pmacfarlane所说,解决方案就在这个datasheet中。
对于16位器件,闪存中使用24位字。该体系结构支持将闪存区域Map到数据空间中,但除非使用__pack_upper_byte限定符,否则该Map只有16位宽以适应数据空间维度
我的struct声明如下:
最后我得到了
比以前好多了,非常感谢您的帮助!