我正在使用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整除,代码卡住了。
在这种情况下,反汇编如下。
当从地址0x0000 2000步进时,它转到硬故障处理程序。但在早先的情况下,它并没有发生严重的错误。它继续并且也有效。
我无法理解DCW指令以及它为什么会出现故障。 有人能告诉我这背后的原因吗?
答案 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的低字节是基址寄存器的编码位置,因此通过改变地址,您可以了解哪个寄存器,以及是否留下任何垃圾值也恰好是一个有效的地址。从...加载。你觉得幸运吗?
无论如何,总结:不是直接调用向量表的地址,而是需要从中加载第二个单词,然后调用包含的 。