lpc 1768辅助引导加载程序错误

时间:2016-03-07 13:04:36

标签: arm startup bootloader keil lpc

我正在使用lpc 1768 SBL,其中包含以下代码以跳转到用户应用程序。

#define NVIC_VectTab_FLASH           (0x00000000)
#define USER_FLASH_START             (0x00002000)
void NVIC_SetVectorTable(DWORD NVIC_VectTab, DWORD Offset)
{ 
   NVIC_VECT_TABLE = NVIC_VectTab | (Offset & 0x1FFFFF80);
}
void execute_user_code(void)
{


    void (*user_code_entry)(void);
    /* Change the Vector Table to the USER_FLASH_START 
    in case the user application uses interrupts */
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, USER_FLASH_START);


    user_code_entry = (void (*)(void))((USER_FLASH_START)+1);
    user_code_entry();

}

它没有任何错误。将一些堆内存添加到代码后,机器卡住了。我为堆尝试了不同的值。他们中的一些人正在工作。经过一些深度调试后,我发现当一个可被64整除的值位于应用程序bin文件的第一个位置时,机器没有卡住。

当我选择堆内存为0x00002E90时,它会生成堆栈基址为0x10005240。然后堆栈基址+堆栈大小(0x2900)给出一个值= 0x10007B40。 我发现这是在应用程序bin文件的第一个位置加载的。该值可被64整除,代码运行时不会卡住。

但是,当我选择堆内存为0x00002E88时,它会生成堆栈基址为0x10005238。然后堆栈基址+堆栈大小(0x2900)给出一个值= 0x10007B38。 该值不能被64整除,代码卡住了。

在这种情况下,反汇编如下。

enter image description here

当从地址0x0000 2000步进时,它转到硬故障处理程序。但在早先的情况下,它并没有发生严重的错误。它继续并且也有效。

我无法理解DCW指令以及它为什么会出现故障。 有人能告诉我这背后的原因吗?

1 个答案:

答案 0 :(得分:1)

执行向量表是您在较旧的ARM7 / ARM9部件(或更大的Cortex-A部件)上执行的操作,其中向量是指令,第一个条目是跳转到重置处理程序,但在Cortex-M上,向量表是纯数据 - 第一个条目是您的初始堆栈指针,第二个条目是重置处理程序的地址 - 因此尝试执行它可能会出现可怕的错误..

碰巧,在这种情况下,可以实际上完全逃脱执行大部分的向量表,因为内存布局导致闪存地址的每个半字变为相当无害的指令:

2: 1000    asrs  r0, r0, #32
4: 20d9    movs  r0, #217    ; 0xd9
6: 0000    movs  r0, r0
8: 20f5    movs  r0, #245    ; 0xf5
a: 0000    movs  r0, r0
...

直到你最终将所有剩余的NOP绊倒到0x20d8,你才能获得真正的入口点。然而,杀手是初始堆栈指针,因为由于RAM更高,你得到这个:

0: 7b38    ldrb  r0, [r7, #12]

0x7bxx的低字节是基址寄存器的编码位置,因此通过改变地址,您可以了解哪个寄存器,以及是否留下任何垃圾值也恰好是一个有效的地址。从...加载。你觉得幸运吗?

无论如何,总结:不是直接调用向量表的地址,而是需要从中加载第二个单词,然后调用包含的