STM32 BOOT跳转到APP后初始化完后成死机 用了FREERTOS
[复制链接]
本帖最后由 liyancao001 于 2024-11-26 15:57 编辑
芯片时STM32F767ZGT6,以前同样芯片的另一个板子做过CAN的IAP,是测试通了的,现在又不行了。。
使用STM32CUBEMX建的工程,BOOT和APP都是用了FREERTOS,然后跳转到APP是正常的,但是死在MX_FREERTOS_Init();
求指点啊,之前做过CAN的IAP,运行正常,现在弄串口结果不行了。。。
我在MX_FREERTOS_Init();里面加了串口打印,函数下面也加了,发现里面需要打印的数据都是输出正常的,但是到函数下面就不行了。
MX_FREERTOS_Init();//这个函数体里面的最后加了一句串口打印,打印是正常的。。
printf("ADECU_APP_2,0x%X\r\n",SCB->VTOR);//这句一直打印不出来。
/* Start scheduler */
osKernelStart();
其中BOOT跳转前把中断也都关了
APP相比没做IAP之前,就增加了2项:(没做IAP之前程序运行正常)
1)MAIN开头的中断向量偏移
int main(void)
{
/* USER CODE BEGIN 1 */
SCB->VTOR = FLASH_BASE | 0x80000;//设置偏移量
2)option for target里把IROM1的起始地址改为了0x8080000,start改为了0x40000
而BOOT跳转函数如下:
void iap_load_app(uint32_t appxaddr)// 调用时参数为0x08080000
{
if(((*(vu32*)appxaddr)&0x2FF00000)==0x20000000) { //检查栈顶地址是否合法.
HAL_RCC_DeInit();
INTX_DISABLE();
SysTick->CTRL = 0X00;//卡死后新增的,但是没有用,跟上面应该是功能重复的
SysTick->LOAD = 0;//卡死后新增的,但是没有用,跟上面应该是功能重复的
SysTick->VAL = 0;//卡死后新增的,但是没有用,跟上面应该是功能重复的
__disable_irq();//卡死后新增的,但是没有用,跟上面应该是功能重复的
jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app(); //跳转到APP.
}
}
241126上午又做了一些测试:
改了一版APP程序,把FREERTOS给关掉了,其他程序给屏蔽了,WHILE主循环只保留两个功能:
1)延时并且打印999,
2)查询1ms定时器累加变量值,超过1000则清零并打印888.
结果实测只打印了999,没有打印888,因此就是中断没有打开,所以BOOT的程序不能只关不开?
于是重新改写BOOT程序:
HAL_Init();
INTX_DISABLE();
/* 关闭所有中断,清除所有中断挂起标志 */
for (i = 0; i < 8; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
__set_PRIMASK(0);//开启总中断
__set_CONTROL(0);
jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app(); //跳转到APP.
结果:
999和888都打印正常了。。。于是乎很高兴的回到原始APP(有freertos)中。发现跳转过去立刻死掉。。。悲剧了
用在线调试查看死掉的位置,发现卡在SPI_WaitFifoStateUntilTimeout中,一直等待flag。
于是乎把SPI的几个初始化都注释掉,发现又一直卡在__HAL_TIM_GET_FLAG里,等于定时器初始化一直没过。倒是没有进硬件错误。
简单来说BOOT最后把中断关了的话APP里初始化正常,不是进不去中断,而BOOT最后把中断打开的话APP连初始化都过不了。
不明白原因,然后把APP的偏移和option for target都去掉,回归普通的程序,下载程序发现freertos中任务里串口1s间隔打印的数据都是正常的。
更迷糊了,我这问题到底是出在BOOT上还是APP上。。。
APP必须自己开中断吗?以前做CAN刷写时,BOOT只用以下语句:
HAL_RCC_DeInit();
INTX_DISABLE();
jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app();
而APP也不用管开中断的事。。
|