我正在尝试使用Atmel Studio 7附带的ARM GNU工具链(arm-none-eabi?)为Cortex-M0 +创建一个位置无关的二进制文件。我看了很多地方了解如何做到这一点,但我没有成功。这将有助于在低高闪存区域中创建用于OTA更新的乒乓图像,而无需知道或关心更新是否是该单元的ping或pong图像。
我有一个驻留在0x0000的8 kB引导加载程序,我可以通过UART进行通信,如果它在那里检测到二进制(即不是0xFFFF擦除闪存),它将在复位后跳转到0x6000(24 kB)。这个SAM-BA引导加载程序允许我转储内存并使用指定地址的.bin文件擦除和编程Flash。
在应用程序项目(简单的LED闪烁)中,除了将-section-start = .text = 0x6000添加到链接器命令行之外什么也不做,导致LED闪烁代码在引导加载程序被编程为0x6000后工作。我也在hex文件中看到它从0x6000开始。
在我尝试创建与位置无关的二进制文件时,我删除了上面的链接器项,并将-fPIC标志添加到编译器,链接器和汇编器的命令行中。但是,我认为我仍然在反汇编中看到绝对分支地址,例如:
28e:d001 beq.n 294
结果是我在0x6000加载的LED闪烁二进制文件没有执行,除非我特意告诉链接器把它放在0x6000,这违背了目的。请注意,我也看到在反汇编的其他部分看起来像相对分支:
21c:4b03 ldr r3,[pc,#12]; (22c)
21e:58d3 ldr r3,[r2,r3]
220:9301 str r3,[sp,#4]
222:4798 blx r3
SRAM始终位于相同的地址(0x20000000),我只需要能够重新定位可执行文件。我没有修改链接器命令文件,它没有.got(例如(.got)或类似的)部分。
任何人都可以向我解释我需要对编译器/汇编器/链接器标志进行的具体更改,以便在此设置中创建与位置无关的二进制文件吗?提前谢谢了。
你需要仔细查看你的反汇编。对于0xd001,我得到这个:
0x00000000: d001 .. BEQ {pc}+0x6 ; 0x6
在您的情况下,工具链试图提供帮助。显然,16位操作码不能编码具有32位地址空间的绝对地址。所以你比想象的更接近解决方案。