当前位置: 首页 > news >正文

STM32 APP跳转后无法进入中断

前几天在做STM32的在线升级功能,参考了很多博主的demo程序,也成功进入跳转到的App但跳转后APP程序无法进入终端,单独下载是好的。

分享一下需要注意的几点
1 bootloader工程设置
在这里插入图片描述
stm32运行的首地址就是0x08000000,因此bootloader必须是这个,Size可按照生成的bin文件大小来设置,也可直接指定该扇区长度。

2 App工程设置
在这里插入图片描述
我的APP是放到了第2个扇区,因此我这里需要填写第二个扇区的首地址。

3 跳转思路
在这里插入图片描述

我共用到了三个扇区,有人会说这个有点浪费flash空间,我使用的是STM32H743ZIT6芯片,有2兆的空间,支持块擦除和扇区擦除,在写flash之前必须要擦除,为了方便我将这三个扇区进行了这样的划分。
在这里插入图片描述
App1区域是我程序正常执行的区域,App2区域是升级备份区域。
在Bootloader区域中会对App2进行识别,如果App2区域程序有用,则会将App2区域的程序写入到App1中,再回读对比确保App2的程序与App1程序一致,然后再去将App2区域进行擦除。

4 跳转代码

//bootloader main代码
int main(void)
{bsp_Init();		/* 硬件初始化 */if(IsUpdateFlagSet())	//升级标识置位{Go2Update();}else{Go2Application();}while(1){//App1和App2均不可用,可以正常读取版本号,进行升级业务PcTransaction();ResTransaction();}
}
/*******************************************************************
* 名称:	IsUpdateFlagSet
* 功能:	判断App2空间是否有程序
* 参数:	
* 返回:	false:没有升级程序
*		true:有升级程序
*******************************************************************/
bool IsUpdateFlagSet(void)
{bool bUpdate = false;uint32_t nFlag = *((__IO uint32_t *)UPDATE_FLAG_ADDRESS);	//读取RAM中升级标识地址内容#ifdef _DEBUGprintf("UpdateFlag Data:%08x\n",nFlag);
#endif//判断从RAM中读出的内容是否为升级标识if (UPDATE_FLAG == nFlag){
#ifdef _DEBUGprintf("It is necessary to upgrade App2 to App1!\n");
#endifbUpdate = true;}
#ifdef _DEBUGprintf("\n");
#endifreturn bUpdate;
}
/*******************************************************************
* 名称:	Go2Update
* 功能:将App2的内容写入到App1中
* 参数:	
* 返回:true 转移成功
*		false 转移失败
*******************************************************************/
bool Go2Update(void)
{uint32_t *App2Data;				//app2数据uint32_t *App1Data;				//app1数据uint32_t CycleCnt = 0;			//周期计数值 uint32_t i = 0;bool flag = true;App2Data = (uint32_t *) malloc(ONCE_READ_WRITE_BYTE); //申请内存App1Data = (uint32_t *) malloc(ONCE_READ_WRITE_BYTE); //申请内存bool App2EqualApp1Flag = true;uint8_t FailCnt = 0;#ifdef _DEBUGprintf("***********************Start moving the memory of App2 to that of App1***********************\n");
#endifdo{App2EqualApp1Flag = true;//1.擦除App1STMFLASH_EraseSector(APPLICATION_SECTOR);							//2.读app2数据,写到app1中
#ifdef _DEBUGprintf("***********************Start Read App2 and Write App1***********************\n");
#endiffor(CycleCnt = 0; CycleCnt <READ_WRITE_CYCLE_MAX; CycleCnt++)		{STMFLASH_Read(BACKUP_PARTITION_ADDRESS + ONCE_READ_WRITE_BYTE * CycleCnt,App2Data,ONCE_READ_WRITE_BYTE/4);			//读App2STMFLASH_Write(APPLICATION_PARTITION_ADDRESS + ONCE_READ_WRITE_BYTE * CycleCnt,App2Data,ONCE_READ_WRITE_BYTE/4);	//写app1	}//3.App1和App2空间是否一直for(CycleCnt = 0; CycleCnt <READ_WRITE_CYCLE_MAX; CycleCnt++){STMFLASH_Read(BACKUP_PARTITION_ADDRESS + ONCE_READ_WRITE_BYTE * CycleCnt,App2Data,ONCE_READ_WRITE_BYTE/4);			//读App2STMFLASH_Read(APPLICATION_PARTITION_ADDRESS + ONCE_READ_WRITE_BYTE * CycleCnt,App1Data,ONCE_READ_WRITE_BYTE/4);		//读App1for(i = 0; i < ONCE_READ_WRITE_BYTE/4; i++){if(App2Data[i] != App1Data[i]){App2EqualApp1Flag = false;FailCnt++;
#ifdef _DEBUGprintf("Err:App1 and App2 Memory values are not equal!\n");printf("INFO:App1 addr:%08x, Data:%08x.\n",APPLICATION_PARTITION_ADDRESS + ONCE_READ_WRITE_BYTE * CycleCnt + 4*i,App1Data[i]);printf("INFO:App2 addr:%08x, Data:%08x.\n",BACKUP_PARTITION_ADDRESS + ONCE_READ_WRITE_BYTE * CycleCnt + 4*i,App2Data[i]);
#endifbreak;}}}
#ifdef _DEBUGprintf("moving the memory of App2 to that of App1 Completed!\n\n");
#endif}while((App2EqualApp1Flag == false)&&(FailCnt < MAX_UPDATE_CNT));if(App2EqualApp1Flag == false){return false;}//4.擦除App2STMFLASH_EraseSector(BACKUP_SECTOR);	free(App1Data);	// 释放分配的内存free(App2Data);	// 释放分配的内存NVIC_SystemReset(); // 触发系统复位return true;
}
void Go2Application(void)
{uint32_t jumpAddr;		//跳转地址,程序开始地址pFunc Jump2App;			//跳转函数uint8_t i;//检查栈顶地址是否合法if (((*(__IO uint32_t *)APPLICATION_PARTITION_ADDRESS) & 0x2FFE0000) == 0x20000000){//屏蔽所有中断,防止在跳转过程中,中断干扰出现异常//__disable_irq();//__set_FAULTMASK(1);__set_PRIMASK(1);SysTick->CTRL = 0X00;//禁止SysTickSysTick->LOAD = 0;SysTick->VAL = 0;NVIC_DisableIRQ(USART1_IRQn);NVIC_DisableIRQ(EXTI2_IRQn);NVIC_ClearPendingIRQ(USART1_IRQn);NVIC_ClearPendingIRQ(EXTI2_IRQn);for(i=0;i<8;i++)//适用于中断编号是16~255{NVIC->ICER[i] = 0xFFFFFFFF;//写1清除中断使能NVIC->ICPR[i] = 0xFFFFFFFF;//写1清除中断挂起状态}__set_PRIMASK(0);//应用代码区第二个字节为程序开始地址(复位地址)jumpAddr = *(__IO uint32_t *)(APPLICATION_PARTITION_ADDRESS + 4);//初始化堆栈指针(程序代码区第一个字用于存放栈顶地址)__set_MSP(* (__IO uint32_t *)APPLICATION_PARTITION_ADDRESS);//转换为函数指针Jump2App = (pFunc)jumpAddr;SCB->VTOR = 0x08020000;__set_CONTROL(0);//执行跳转函数Jump2App();/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */while (1){}}
}

重点
网上很多教程给了类似上述代码,同样我使用了上述代码成功跳转到App中,但中断无法进行。
这里VTOR需要设置到App区域
在这里插入图片描述
其次在system_stm32h7xx.c文件中也需要修改
bootloader 设置0即可
App区域需要设置成下一个扇区
在这里插入图片描述
后面在void SystemInit (void)函数会用到
在这里插入图片描述

http://www.dtcms.com/a/317838.html

相关文章:

  • QT----不同线程中信号发送了槽函数没反应QObject::connect: Cannot queue arguments of typeXXX
  • C++编程语言:标准库:工具类(Bjarne Stroustrup)
  • Python赋能气象与气候数据分析的生态构建与实战路径
  • Linux中systemd与systemctl管理指南
  • LlaMA_Factory实战微调VL大模型
  • 【数据分享】西藏土壤类型数据库
  • AlphaEarth模型架构梳理及借鉴哪些深度学习领域方面的思想
  • [AI 生成] Spark 面试题
  • 【深度学习】Graph Transformer Networks(GTN,图变换网络)
  • Linux 中 Git 操作大全
  • 测试单节点elasticsearch配置存储压缩后的比率
  • cacti
  • 深入理解C++中的stack、queue和priority_queue
  • 部署 Zabbix 企业级分布式监控笔记
  • C语言高级编程技巧与最佳实践
  • 学习bug
  • R4周打卡——Pytorch实现 LSTM火灾预测
  • 人工智能——深度学习——认识Tensor
  • 工业禁区人员闯入识别准确率↑29%:陌讯动态融合算法实战解析
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘gensim’问题
  • 股票T0程序化交易,高频交易
  • 队列很多时,为什么RocketMQ比Kafka性能好?
  • 河南萌新联赛2025第四场-河南大学
  • 【PZSDR P201MINI】 P201Mini 软件无线电开发板:紧凑型射频系统的性能标杆
  • OpenSCA用户访谈第二期:互联网科技公司如何用OpenSCA“锁”住开源风险?
  • 模块--继电器
  • 进阶向:Python开发简易QQ聊天机器人
  • 013 HTTP篇
  • 网络原理——初识
  • 【Go】P3 Go语言程序结构