首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >STM32F1上应用程序之间的跳转

STM32F1上应用程序之间的跳转
EN

Stack Overflow用户
提问于 2018-04-30 19:56:25
回答 2查看 563关注 0票数 2

背景

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

STM32F103RBT6 Olimex头板

STM32F103C8T6 BluePill

我的应用程序是一个主要的应用程序,它将第二个应用程序加载到内存中,然后跳转到它。主应用程序由GNU作为默认的STM32F1项目编译和链接,而第二个应用程序是用链接脚本编译和链接的C程序(仅指定内存位置和大小),因此向量表不对齐。第二个应用程序与主应用程序捆绑在一起,一个char数组被复制到内存中。主应用程序还具有要公开给辅助应用程序的应用程序的查找表。

代码语言:javascript
复制
void hello_world();

unsigned int lookup_table[] = {
      (unsigned int)&hello_world
};

在将辅助应用程序放入内存(并经验证已正确复制)之后,主应用程序跳转到它,并将一个引用传递给它的查找表:

代码语言:javascript
复制
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);

然后,辅助应用程序应该能够从查找表中的引用调用函数。

代码语言:javascript
复制
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完美地运行了应用程序。

提前感谢!

EN

回答 2

Stack Overflow用户

发布于 2018-05-01 07:56:37

第二个应用程序的链接器知道它放在内存中的位置吗?您不能像从闪存中运行一样链接它,然后将其复制到不同的地址空间,并期望它正常工作。

向量表中的第一个位置是堆栈顶部的地址。您需要将AppFunc appFunc = (AppFunc)(((uint32_t)0x20003000) + 1);更改为AppFunc appFunc = (AppFunc)(((uint32_t)0x20003004));以获取重置处理程序的地址。

您不需要+1地址,这是由编译器为您处理的。您拥有的地址有一个指向重置向量所在位置的指针。

票数 1
EN

Stack Overflow用户

发布于 2018-05-02 10:18:13

我对皮质使用以下功能

代码语言:javascript
复制
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));
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50107353

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档