跳转到重置向量

时间:2016-06-16 10:53:38

标签: c embedded

我试图跳回到重置向量并从main运行我的程序。这是我的代码,但它不起作用。这有什么不对吗?

 typedef void (*reset_vector_jump)(void); 
 ((reset_vector_jump)RESET_VECTOR_ADDRESS)();

2 个答案:

答案 0 :(得分:3)

您正在尝试运行在处于未处于重置状态的处理器状态时从重置状态运行的代码。除了最简单的处理器外,这很可能会失败。如果直到你进行此跳转的代码已经完成了诸如配置存储器管理单元,启用中断,启动看门狗定时器或配置PLL之类的操作,则重置代码将在不具有此功能的环境中运行。期望的。

你应该至少禁用中断。您可能只是逃避它,但这取决于处理器的复杂性以及可能已启用且处于活动状态的硬件或外围设备。特别是如果已启用MMU,则复位向量可能不再是有效地址。

x86处理器特有的一个问题是,为了向后兼容,它们以16位实模式启动。如果当您尝试跳转时,处理器处于保护模式,则复位向量处的代码将毫无意义。切换回实模式必然要求处理器复位。

更安全的方法是强制进行真正的重置。如果处理器具有看门狗定时器,则启用它但不对其进行维护是一种方法。一些架构具有软复位指令,而其他架构具有可以直接执行该操作的复位控制器外设。您的电路板可能与复位引脚有GPIO连接以允许此操作。

答案 1 :(得分:2)

所有这些评论都是相关的,但是如果您绝对需要从有时需要的任何地方跳转到重置处理程序,特别是在您进行引导加载程序和重新编程时,这就是您的工作方式,您非常接近。

在我的情况下,目标Micro是Kinetis ARM cortex4,我的复位向量在位置0x00000004进行硬编码。见下文:

/* Interrupt vector table */
__attribute__ ((section (".vectortable"))) const tVectorTable __vect_table = {
    /* ISR name                    No.   Address    Pri Name                          Description */
    &__SP_INIT,                 /* 0x00  0x00000000 -   ivINT_Initial_Stack_Pointer   used by PE */
    (tIsrFunc)&__thumb_startup, /* 0x01  0x00000004 -   ivINT_Initial_Program_Counter used by PE */ 
};

因此,位置0x00000004包含重置处理程序的地址,即&__thumb_startup。所以这就是我所做的:

typedef void (*reset_vector_jump)(void); //exactly as you've done  
#define RESET_VECTOR_ADDRESS ((uint32_t *) 0x00000004) // a pointer to uint32_t

((reset_vector_jump)*RESET_VECTOR_ADDRESS)();//CALL IT

这对我有用。所以基本上你错过了一个额外的解除引用级别。 希望这可以帮助。