我已成功在 STM32 上构建并运行位置无关的代码。向量表和 GOT 已修补。一切正常,但我对这样的代码有问题。
double myAdd(double x) {
return x + 0.1;
}
double (*ptrmyAdd)(double) = &myAdd;
char* myString = "foo bar";
int main() {
...
printf("%s %2.2f\n", myString, ptrmyAdd(0.1));
...
}
我仅在应用程序没有偏移量(相对于闪存基地址)时工作。原因显而易见,myString
and ptrmyAdd
指向 .rodata 和 .text 没有正确的偏移量。
我能做些什么?我可以在运行时重新初始化指针。
int main() {
...
myString = "foo bar";
ptrmyAdd = &myAdd;
printf("%s %2.2f\n", myString, ptrmyAdd(0.1));
...
}
它适用于任何偏移量。
为了修复指向 .rodata 的指针,我可以腾出一些 RAM 并将 .rodata 移动到 RAM,但我无法将 .text 移动到 RAM。
我还可以在启动时运行 .data 部分并更新所有看起来像闪存地址的值,但这很危险。
有没有办法在 main() 之前修复这些指针?
为什么我需要位置无关的代码。系统看起来像这样...
*--------*
| |
| |
| APP2 | Application bank 2
| |
| |
*--------* 0x08084000
| |
| |
| APP1 | Application bank 1
| |
| |
*--------* 0x08008000
| |
| INFO | Application info area
| |
*--------* 0x08007800
| |
| LDR | Bootloader area
| |
*--------* 0x08000000
引导加载程序通过 y-modem 协议将应用程序映像下载到标记为“未激活”的第一个可用库。引导加载程序将新的存储体设置为“活动”和“有效”,并将先前的“活动”存储体设置为“不活动”。重置引导加载程序后,从“活动”库启动应用程序。在应用程序启动之前,引导加载程序会激活 IWDG。
如果重置来自 IWDG,则引导加载程序会检查“非活动”存储区是否有有效应用程序。如果它包含“有效”应用程序,引导加载程序会将活动组标记为“无效”并交换活动组。
执行更新的用户不知道哪个银行是免费的。引导加载程序决定使用哪个银行。