之前有写过一篇关于IAP的博文,也顺利的启动过好多次,但是昨天用华大的芯片做boot发现始终跳转不到APP中。
现对调试做个总结:
1)调试方法问题
调试方法很重要,调试过程中需要理清思路,这一步会发生什么,下一步会发生什么,去掉冗余的步骤,尽可能的去简化,直到最直接能达到目的的方法。调试bootloader的时,可以先省掉代码搬移,直接烧录进指定地址的代码,然后直接用bootloader去跳转,不用做其他事。先确定最简单的能否实现。
2)无法跳转的原因
先上段跳转代码:
void execute_firmware(uint32_t addr)
{
#ifdef __UART_EN__
printf("execute_firmware\r\n");
#endif
__disable_irq();
//if(((*(uint32_t*)addr)&0x2FFE0000)==0x20000000) //0001 1111 1111 1110 0000 0000 0000 0000
{
JumpAddress = *(uint32_t*)(addr);
#ifdef __UART_EN__
printf("JumpAddress1 = %x\r\n",JumpAddress);
#endif
__set_MSP(JumpAddress);
#ifdef __UART_EN__
printf("MSP_Address = 0x%x xxxx\r\n",JumpAddress);
#endif
JumpAddress = *(uint32_t*) (addr + 4);
Jump_To_Application = (pFunction) JumpAddress;
// *((volatile uint32_t*) 0xE000ED08) = addr;//矢量偏移
SCB->VTOR = 0x0000E000;
Jump_To_Application();
}
}
调试现象:
(1)中断有全部关闭,但现象依旧
(2)矢量偏移,我也是有偏移的,偏移地址正确,但现象依旧
(3)APP程序在代码中的准确性,用keil调试比对过,也是正确的,但现象依旧
(4)APP程序中中断有开启,但现象依旧
原因解释:
(1)在APP程序中的.S文件中,华大的启动文件和其他mcu有区别
;reset NVIC if in rom debug
LDR R0, =0x20000000
LDR R2, =0x0
MOVS R1, #0 ; for warning,
ADD R1, PC,#0 ; for A1609W,
CMP R1, R0
BLS RAMCODE
; ram code base address.
ADD R2, R0,R2
RAMCODE
; reset Vector table address.
LDR R0, =0xE000ED08 //矢量地址
STR R2, [R0]
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
在SystemInit前,有对矢量进行了重置。所以代码始终跳转不到想要的地址中。
解决方法就是在APP代码中,再次对矢量进行偏移相应的地址:
int main(void)
{
SCB->VTOR = 0x0000E000;
__enable_irq();
....
}