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

STM32分区跳转问题

项目场景:

在OTA中,FLASH通常被划分为以下几种类型

  • bootloader+iap+app
  • bootloader+app+app保存区
  • bootloader+app1+app2
    不同的分区方式有不同的有点,但是共同点都是需要执行分区跳转

问题1描述

但在分区跳转过程中遇到过使用不同的编译器不能跳转的情况,例如在keil中使用v5编译器可以正常跳转,但是使用v6编译器就无法跳转了。

void JumpToCode(uint32_t addr) {uint32_t *inputAddr = (uint32_t *)addr;uint32_t jumpAddr  = *(uint32_t *)(addr + 4);if ((*inputAddr & 0x2FFE0000) == 0x20000000) {__set_MSP(*inputAddr);((void (*)(void))jumpAddr)();}
}

问题1原因分析:

发现v6和v5的编译优化不一样,v6编译执行__set_MSP后,跳转地址变量jumpAddr被释放,就不能正确跳转了。把地址相关的变量声明为全局变量就可以正常跳转了

uint32_t *inputAddr;  // !声明为全局变量,防止执行__set_MSP后,变量被释放
uint32_t jumpAddr;    // !设置MSP后改变了栈底地址,导致原来的局部变量范围出了新栈的空间,被系统释放void JumpToCode(uint32_t addr) {inputAddr = (uint32_t *)addr;jumpAddr  = *(uint32_t *)(addr + 4);if ((*inputAddr & 0x2FFE0000) == 0x20000000) {__set_MSP(*inputAddr);((void (*)(void))jumpAddr)();}
}

问题2描述

裸机时可以正常跳转,但是开启freertos后分区无法相互跳转,度娘说要跳转前需要关闭全局中断、关闭外设。我采用的分区方式是bootloader+iap+app,boot跳转前关闭中断和外设后,跳转freertos的app分区没有问题,而跳转裸机的iap分区时无法运行,发现卡在初始化中。为什么跳freertos就ok呢?最后发现MX_FREERTOS_Init的时候自动把中断打开了,原来跳转后在main函数中需要重新开启中断,在其他所有裸机的main函数的while前添加__set_FAULTMASK(0)开启中断即可,freertos不需要。修改后的跳转代码如下:

uint32_t *inputAddr;  // !声明为全局变量,防止执行__set_MSP后,变量被释放
uint32_t jumpAddr;    // !设置MSP后改变了栈底地址,导致原来的局部变量范围出了新栈的空间,被系统释放void JumpToCode(uint32_t addr) {inputAddr = (uint32_t *)addr;jumpAddr  = *(uint32_t *)(addr + 4);if ((*inputAddr & 0x2FFE0000) == 0x20000000) {HAL_RCC_DeInit();HAL_DeInit();__set_FAULTMASK(1);__set_MSP(*inputAddr);((void (*)(void))jumpAddr)();}
}

问题3描述

boot可以跳iap和app了,但是!但是app无法跳iap,最后发现FREERTOS运行在PSP模式,而裸机运行在MSP模式,尝试跳转前设定MSP就正常了,添加__set_CONTROL(0),最终的跳转如下:

uint32_t *inputAddr;  // !声明为全局变量,防止执行__set_MSP后,变量被释放
uint32_t jumpAddr;    // !设置MSP后改变了栈底地址,导致原来的局部变量范围出了新栈的空间,被系统释放void JumpToCode(uint32_t addr) {inputAddr = (uint32_t *)addr;jumpAddr  = *(uint32_t *)(addr + 4);if ((*inputAddr & 0x2FFE0000) == 0x20000000) {HAL_RCC_DeInit();HAL_DeInit();__set_FAULTMASK(1);__set_CONTROL(0);__set_MSP(*inputAddr);((void (*)(void))jumpAddr)();}
}

相关文章:

  • docker-compose 服务编排
  • 企业微信身份验证
  • 2023全球数字贸易创新大赛-人工智能元宇宙-11-12,数据二十条,数字产业化和产业数字化
  • 【bug】uniapp的image组件渲染gif图,只有第一次点击的时候有动效,需要每次点击都有gif效果,已解决
  • 【音视频-FFMPEG相关命令使用】
  • SELinux零知识学习二十五、SELinux策略语言之类型强制(10)
  • 微信小程序面试题【100道】
  • ORA-28003: password verification for the specified password failed,取消oracl密码复杂度
  • 【开源】基于JAVA的高校实验室管理系统
  • Web 自动化神器 TestCafe(三)—用例编写篇
  • 免费图书教材配套资料:Spark大数据技术与应用(第2版)
  • 基于opencv+ImageAI+tensorflow的智能动漫人物识别系统——深度学习算法应用(含python、JS、模型源码)+数据集(一)
  • 【ARM 嵌入式 编译 Makefile 系列 18 -- Makefile 中的 export 命令详细介绍】
  • C++学习之路(二)C++如何实现一个超简单的学生信息管理系统?C++示例和小项目实例
  • 4G5G智能执法记录仪在保险公司车辆保险远程定损中的应用
  • Angular 4.x 动态创建组件
  • CSS实用技巧
  • CSS中外联样式表代表的含义
  • Java 网络编程(2):UDP 的使用
  • JavaScript新鲜事·第5期
  • passportjs 源码分析
  • sessionStorage和localStorage
  • Spring-boot 启动时碰到的错误
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 基于HAProxy的高性能缓存服务器nuster
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 前端技术周刊 2019-01-14:客户端存储
  • 悄悄地说一个bug
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 手机端车牌号码键盘的vue组件
  • 用element的upload组件实现多图片上传和压缩
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • zabbix3.2监控linux磁盘IO
  • #laravel 通过手动安装依赖PHPExcel#
  • (2)Java 简介
  • (a /b)*c的值
  • (MATLAB)第五章-矩阵运算
  • (附源码)ssm高校实验室 毕业设计 800008
  • (七)Java对象在Hibernate持久化层的状态
  • (十六)串口UART
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转)Linq学习笔记
  • .net mvc 获取url中controller和action
  • .NetCore项目nginx发布
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • .NET序列化 serializable,反序列化
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • @AliasFor注解
  • @selector(..)警告提示
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [<事务专题>]
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [20190401]关于semtimedop函数调用.txt
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗