背景
我正在尝试在 STM32F1 微 Controller 上实现应用程序之间的跳转。我正在使用 qemu(由 GNU MCU Eclipse 提供)来模拟使用 STM32F103RBT6 微 Controller 的 Olimex-H103 板。我正在使用在 ebay 上购买的“蓝色药丸”在实际硬件上进行测试。蓝色药丸配备了STM32F103C8T6微 Controller 。这两个微 Controller 非常相似,甚至共享某些来源的数据表。
我的应用程序是一个主应用程序,它将第二个应用程序加载到内存中,然后跳转到它。主应用程序由 GNU MCU Eclipse 作为默认的 STM32F1 项目编译和链接,而第二个应用程序是使用链接脚本编译和链接的 C 程序(仅指定内存位置和大小),因此没有对齐 vector 表。第二个应用程序与主应用程序捆绑在一起,作为一个 char 数组,它被复制到内存中。主应用程序还有一个查找表,用于要向辅助应用程序公开的应用程序。
void hello_world();
unsigned int lookup_table[] = {
(unsigned int)&hello_world
};
在次要应用程序被放入内存中(并验证它已被正确复制)后,主应用程序跳转到它并传递一个对其查找表的引用:
typedef int(*AppFunc)(unsigned int);
// Application is compiled with -mthumb, hence the +1 to the address
AppFunc appFunc = (AppFunc)(((uint32_t)0x20003000) + 1);
appFunc((unsigned int)&lookup_table);
然后,辅助应用程序应该能够从查找表中的引用调用函数。
void start(unsigned int *lookup_table)
{
typedef void(*void_f)();
static void_f hello_func = (void_f)*(lookup_table);
hello_func();
}
当应用程序完成时,执行应该返回到主应用程序(因为返回地址在堆栈上?)。
澄清一下:我(目前)没有更改 vector 表或堆栈指针,因为我希望它们保持一致(如果可能)。
问题
这一切都适用于 qemu,但不适用于真正的硬件。在 qemu 中,它跳转到第二个应用程序,在主应用程序中执行函数,完成后跳回到主应用程序。但是,在实际硬件上,如果 start() 从查找表调用方法,它会在跳转后停止,否则它工作正常(空 start()),但我希望能够跳回到主应用程序并在那里执行功能。
这是使它工作的 qemu 中的错误吗?是硬件问题还是代码问题?我真的不明白问题出在哪里,因为 qemu 可以完美地运行应用程序。
提前致谢!
最佳答案
第二个应用程序的链接器是否知道它在内存中的位置?您不能链接它,就好像它将从闪存中运行一样,然后将它复制到不同的地址空间并期望它正常工作。
vector 表中的第一个位置是堆栈顶部的地址。您需要将 AppFunc appFunc = (AppFunc)(((uint32_t)0x20003000) + 1);
更改为 AppFunc appFunc = (AppFunc)(((uint32_t)0x20003004));
获取重置处理程序的地址。
您不需要为地址 +1,这是由编译器为您处理的。您拥有的地址是指向重置 vector 所在位置的指针。
关于c - 在 STM32F1 上的应用程序之间跳转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50107353/