背景
我试图在STM32F1微控制器上实现应用程序之间的跳转。我使用qemu (由GNU单片机提供的Eclipse)来模拟使用STM32F103RBT6微控制器的Olimex 103板。我用我在ebay上买的“蓝色药丸”在实际硬件上测试它。蓝色药丸配有STM32F103C8T6微控制器。这两个微控制器是非常相似的,甚至共享一些来源的数据表。

STM32F103RBT6 Olimex头板

STM32F103C8T6 BluePill
我的应用程序是一个主要的应用程序,它将第二个应用程序加载到内存中,然后跳转到它。主应用程序由GNU作为默认的STM32F1项目编译和链接,而第二个应用程序是用链接脚本编译和链接的C程序(仅指定内存位置和大小),因此向量表不对齐。第二个应用程序与主应用程序捆绑在一起,一个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();
}当应用程序完成后,执行应该返回到主应用程序(因为返回地址在堆栈上?)。
澄清:I(目前)不更改向量表或堆栈指针,因为我希望它们保持一致(如果可能的话)。
问题
对于qemu来说,这一切都很好,但对于真正的硬件则不是这样。在qemu中,它跳到第二个应用程序,在主应用程序中执行函数,完成后跳回主应用程序。但是,在实际的硬件上,如果start()从查找表调用方法,则在跳转后它会停止运行,否则它会正常工作(空start()),但我希望能够跳回主应用程序并在那里执行函数。
这是qemu中的一个bug使其工作吗?是硬件问题还是代码问题?我真的不明白问题在哪里,因为qemu完美地运行了应用程序。
提前感谢!
发布于 2018-05-01 07:56:37
第二个应用程序的链接器知道它放在内存中的位置吗?您不能像从闪存中运行一样链接它,然后将其复制到不同的地址空间,并期望它正常工作。
向量表中的第一个位置是堆栈顶部的地址。您需要将AppFunc appFunc = (AppFunc)(((uint32_t)0x20003000) + 1);更改为AppFunc appFunc = (AppFunc)(((uint32_t)0x20003004));以获取重置处理程序的地址。
您不需要+1地址,这是由编译器为您处理的。您拥有的地址有一个指向重置向量所在位置的指针。
发布于 2018-05-02 10:18:13
我对皮质使用以下功能
typedef void (application_t)(void);
typedef struct vector
{
uint32_t stack_addr; // intvec[0] is initial Stack Pointer
application_t* func_p; // intvec[1] is initial Program Counter
} vector_t;
void jump_to(const uint32_t addr)
{
const vector_t* vector_p = (vector_t*)addr;
// TODO peripheral deinit
/* Disable interrupt */
NVIC->ICER[0]=0xFFFFFFFF;
NVIC->ICPR[0]=0xFFFFFFFF;
#if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
NVIC->ICER[1]=0xFFFFFFFF;
NVIC->ICPR[1]=0xFFFFFFFF;
#endif
/* Set new vector table */
SCB->VTOR = (uint32_t)addr;
/* Jump, used asm to avoid stack optimization */
asm("\n\
msr msp, %0; \n\
bx %1;" : : "r"(vector_p->stack_addr), "r"(vector_p->func_p));
}https://stackoverflow.com/questions/50107353
复制相似问题