lpc 1768 辅助引导加载程序错误
lpc 1768 Secondary Boot Loader error
我正在研究 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();
}
它运行正常,没有任何错误。在代码中加入一些堆内存后,机器就卡住了。我为堆尝试了不同的值。他们中的一些人正在工作。经过一些深入的调试,我发现当应用程序 bin 文件的第一个位置有一个可以被 64 整除的值时,机器没有卡住。
即
当我select 堆内存为 0x00002E90 时,它生成堆栈基为 0x10005240 。然后堆栈基址 + 堆栈大小 (0x2900) 给出一个值 = 0x10007B40。
我发现这是在应用程序 bin 文件的第一个位置加载的。这个值可以被64整除,代码是运行没有卡死
但是,当我 select 堆内存为 0x00002E88 时,它生成的堆栈基数为 0x10005238。然后堆栈基址 + 堆栈大小 (0x2900) 给出一个值 = 0x10007B38。
这个值不能被64整除,代码卡死
本例反汇编如下
从地址 0x0000 2000 步进时,它会转到硬故障处理程序。但在较早的情况下,它不会成为硬错。它继续并且也有效。
我无法理解指令 DCW 以及它为什么会出现硬故障。
谁能告诉我这背后的原因?
执行向量 table 是你在较旧的 ARM7/ARM9 部件(或更大的 Cortex-A 部件)上执行的操作,其中向量是指令,第一个条目将跳转到重置处理程序,但在 Cortex-M 上,向量 table 是纯数据 - 第一个条目是您的初始堆栈指针,第二个条目是重置处理程序的 地址 -所以尝试执行它很容易出错..
碰巧,在这种情况下,您 可以 实际上完全偶然地执行了该向量的大部分 table,因为内存布局导致每个半字的闪存地址变成相当无害的指令:
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 的低字节是基址寄存器的编码位置,因此通过改变地址,您可以确定是哪个寄存器,此外,其中留下的任何垃圾值是否也恰好是有效的要加载的地址。你觉得幸运吗?
总之,总结一下:与其直接调用向量 table 的地址,不如从中加载第二个字,然后调用任何地址 that包含。
我正在研究 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();
}
它运行正常,没有任何错误。在代码中加入一些堆内存后,机器就卡住了。我为堆尝试了不同的值。他们中的一些人正在工作。经过一些深入的调试,我发现当应用程序 bin 文件的第一个位置有一个可以被 64 整除的值时,机器没有卡住。
即
当我select 堆内存为 0x00002E90 时,它生成堆栈基为 0x10005240 。然后堆栈基址 + 堆栈大小 (0x2900) 给出一个值 = 0x10007B40。 我发现这是在应用程序 bin 文件的第一个位置加载的。这个值可以被64整除,代码是运行没有卡死
但是,当我 select 堆内存为 0x00002E88 时,它生成的堆栈基数为 0x10005238。然后堆栈基址 + 堆栈大小 (0x2900) 给出一个值 = 0x10007B38。 这个值不能被64整除,代码卡死
本例反汇编如下
从地址 0x0000 2000 步进时,它会转到硬故障处理程序。但在较早的情况下,它不会成为硬错。它继续并且也有效。
我无法理解指令 DCW 以及它为什么会出现硬故障。 谁能告诉我这背后的原因?
执行向量 table 是你在较旧的 ARM7/ARM9 部件(或更大的 Cortex-A 部件)上执行的操作,其中向量是指令,第一个条目将跳转到重置处理程序,但在 Cortex-M 上,向量 table 是纯数据 - 第一个条目是您的初始堆栈指针,第二个条目是重置处理程序的 地址 -所以尝试执行它很容易出错..
碰巧,在这种情况下,您 可以 实际上完全偶然地执行了该向量的大部分 table,因为内存布局导致每个半字的闪存地址变成相当无害的指令:
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 的低字节是基址寄存器的编码位置,因此通过改变地址,您可以确定是哪个寄存器,此外,其中留下的任何垃圾值是否也恰好是有效的要加载的地址。你觉得幸运吗?
总之,总结一下:与其直接调用向量 table 的地址,不如从中加载第二个字,然后调用任何地址 that包含。