STM32F4 IAP 跳转 APP问题

2023-11-17

1. 概念

  IAP 的作用,网上其他资料已经有很多介绍了,这里放一个链接,不进行深入的介绍。本文的关注重点是Bootloader在跳转APP程序中出现的问题。
IAP的实现原理讲解以及中断向量表的偏移

2. 程序

  本人主要做应用层的开发,所有Bootloader和APP程序使用的是STM32CubeMX工具生成代码后,然后进行修改。

2.1 Bootloader 程序

  1. CubeMX 配置
  步骤1:使用的芯片为STM32F407ZGT6
在这里插入图片描述
  步骤2:选择时钟源(根据自己的板子进行选择)
在这里插入图片描述
  步骤3:时钟配置
在这里插入图片描述
  步骤4:项目配置
在这里插入图片描述
  2. 代码(只介绍跳转函数)

  完整代码

void IAP_ExecuteApp ( uint32_t ulAddr_App )
{
	int i = 0;
	pIapFun_TypeDef pJump2App; 

	
	if ( ( ( * ( __IO uint32_t * ) ulAddr_App ) & 0x2FFE0000 ) == 0x20000000 )	 //@1 //检查栈顶地址是否合法.
	{ 
		
		HAL_SPI_MspDeInit(&hspi1);	//@2
		__HAL_RCC_GPIOB_CLK_DISABLE();
		__HAL_RCC_GPIOG_CLK_DISABLE();
		
		
		 /* 设置所有时钟到默认状态,使用HSI时钟 */
		HAL_RCC_DeInit();		//@3
		
		__set_BASEPRI(0x20);		//@4
		__set_PRIMASK(1);
        __set_FAULTMASK(1);
		
		/* 关闭所有中断,清除所有中断挂起标志 */
		for (i = 0; i < 8; i++)		//@5
		{
			NVIC->ICER[i]=0xFFFFFFFF;
			NVIC->ICPR[i]=0xFFFFFFFF;
		}
		
		SysTick->CTRL = 0;		//@6
		SysTick->LOAD = 0;
		SysTick->VAL = 0;

		__set_BASEPRI(0);		//@7
		__set_PRIMASK(0);
		__set_FAULTMASK(0);
 		
 		//@8
        /*
        1)不使用OS时: 只用到MSP(中断和非中断都使用MSP);
        2)使用OS时(如UCOSII): main函数和中断使用MSP; 各个Task(线程)使用PSP(即任务栈);
        */
        __set_MSP(*(uint32_t*)ulAddr_App);//当带操作系统从APP区跳转到BOOT区的时候需要将SP设置为MSP,否则在BOOT区中使用中断将会引发硬件错误!
        __set_PSP(*(uint32_t*)ulAddr_App);
        __set_CONTROL(0);  /* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
        __ISB();//指令同步隔离。最严格:它会清洗流水线,以保证所有它前面的指令都执行完毕之后,才执行它后面的指令。
		//@9
		pJump2App = ( pIapFun_TypeDef ) * ( __IO uint32_t * ) ( ulAddr_App + 4 );	//用户代码区第二个字为程序开始地址(复位地址)		
		pJump2App ();								                                    	//跳转到APP.
	}
}	

  @1 代码作用:检查栈顶地址是否合法.0x20000000是sram的起始地址,也是程序的栈顶地址;

if ( ( ( * ( __IO uint32_t * ) ulAddr_App ) & 0x2FFE0000 ) == 0x20000000 )

  @2 代码作用:下面这几个关闭的是在Bootloader中初始化过的外设,如果没有初始化过其他外设,则不需要;

HAL_SPI_MspDeInit(&hspi1);	
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOG_CLK_DISABLE();

  @3 代码作用:PLL在Bootloader中已经配置启动了,在APP程序中如果想再进行配置启动的话会返回错误。
问题现象
  将Bootloader和APP程序分别下载到板子上,Bootlader程序可以正常运行,而APP程序会死在Error_Handler()的while(1)循环中。具体调试发现程序是在执行HAL_RCC_OscConfig()函数的PLL 配置部分检测到当前PLL已经被配置为了系统时钟而返回了HAL_ERROR的返回值导致进入了Error_Handler()。
方案一: 网上有人的建议是不使用PLL,使用HSI作为系统的时钟源,经过测试可以正常运行;但是这样会有个问题是,使用STM32F4的HSI是16M,这显然和通过PLL倍频之后使用的168M不在一个数量级上。
方案二: 通过查找资料发现,可以在Bootloader启动的时候配置PLL倍频到168M,然后在跳转程序之前将RCC的配置反初始化为默认设置(使用HSI时钟)。

HAL_RCC_DeInit();	

  @4 代码作用:关闭所有的中断;此处的特殊寄存器设置值,可以看如下链接: 嵌入式–Keil5–调试状态下Registers界面解析(nrf52832–Cortex-M4内核)

__set_BASEPRI(0x20);
__set_PRIMASK(1);
 __set_FAULTMASK(1);

  @5 代码作用:清除所有中断挂起标志,防止在APP中触发该中断,导致运行错误;

	/* 关闭所有中断,清除所有中断挂起标志 */
		for (i = 0; i < 8; i++)		//@5
		{
			NVIC->ICER[i]=0xFFFFFFFF;
			NVIC->ICPR[i]=0xFFFFFFFF;
		}

  @6 代码作用:关闭掉系统滴答定时器,该定时器会在APP的程序中重新启动,调用HAL_Init();函数会启动;
注意:@6 的代码一定要放到@3 之后,因为HAL_RCC_DeInit();函数会再次开启滴答定时器。

SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

  @7 代码作用:重新启动中断开关;

	__set_BASEPRI(0);
	__set_PRIMASK(0);
	__set_FAULTMASK(0);

注意:必须重新启动中断的开关,本人调试过程中没有开启__set_FAULTMASK(0) ;的中断,导致滴答定时器(SysTick)无法正常运行,执行HAL_Delay();,死循环在了延时中,耽误了一天的时间查找问题。

  @8 和@9 代码都有详细的注释;

注意: __set_PSP((uint32_t)ulAddr_App); 和 __set_CONTROL(0); 函数是使用RTOS(实时操作系统的读者必须要添加的)

2.2. APP程序

  CubeMX 配置基本和Bootloader 基本相同,不赘述。本人使用的FreeRTOS的实时操作系统。

  1. Keil 配置
    步骤1:配置程序的起始位置(根据自己的需要修改),配置的时候发现只配置这块没用,需要配置步骤2才行
在这里插入图片描述
    步骤2:Linker 中修改ScatterFile 文件;

在这里插入图片描述
  这是本人的配置,每个人的可能都不一样,本人是需要用ccmram,所以使用自己的ScatterFile 文件,修改的内容如下图。
在这里插入图片描述
    步骤2:设置APP的中断向量表的位置;
  首先找到 startup_stm32f407xx.s 文件中调用 SystemInit 函数的地方,找到SystemInit 函数的实现,然后 找到 USER_VECT_TAB_ADDRESS 的宏定义的地方,取消注释。先修改下图 1的位置,然后修改 2的位置,2的位置根据自己的APP偏移位置来修改。
在这里插入图片描述
  2. 代码
   在main 函数的一开始添加如下代码。

  /* USER CODE BEGIN 1 */
	HAL_DeInit();
	HAL_RCC_DeInit();
  /* USER CODE END 1 */

在这里插入图片描述
HAL_DeInit(); HAL库反初始化;
HAL_RCC_DeInit(); RCC配置反初始化;

  注意: 如果直接查找HAL_RCC_DeInit() 的实现,发现是个空函数,实际这是HAL库的一个机制,实际编译使用的另外一个文件中的,如下图1和2

在这里插入图片描述
在这里插入图片描述

4. 其他问题

4.1 可能导致APP死机的原因

  1. Bootloader启动的外设比APP的多,导致死机,需要在跳转到APP时清理不需要的外设配置;
  2. Bootloader开启了某个终端,在APP中没有配置相应的处理函数,导致死机;该问题可通过Bootloader程序的@4 @5 @7来解决;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F4 IAP 跳转 APP问题 的相关文章

  • tensorflow如何更新到最新的版本

    背景 前面在anaconda中使用tensorflow时 在深度学习目标检测的那方面出现了问题 提示 no op 当你在百度上百度这个错误的时候 很多的CSDN博主会告诉你是因为你的tensorflow版本过低 准备 那就是更新tensor

随机推荐

  • MySQL——习题:每个部门当前员工最高薪水

    有一个员工表dept emp简况如下 有一个薪水表salaries简况如下 获取所有部门中员工薪水最高的相关信息 给出dept no emp no以及其对应的salary 按照部门编号升序排列 以上例子输出如下 解法1 SELECT d1
  • 移植Qt4.8.4项目到QT5.2上时遇到的一些问题

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 问题1 Qt 5 2 使用原来的QT4 8 4项目时QWebView QWebFrame等类无法编译通过 出现原因 QWebView QWebFrame QWebPage
  • OJ: 蛇形矩阵 螺旋矩阵

    题目描述 题目说明 在一个N N的方阵中 填入1 2 N共N个数 并要求构成如下的格式 N lt 10 例 输入描述 多组数据 每行读入一个N 输出描述 对应输出N N的蛇形矩阵 每个数字占3格子 每个蛇形矩阵之间用空行分割 输入样例 3
  • 【Git】git pull总是要输入账号和密码

    git config global credential helper store 之后再次执行git push 或者git pull这时候只需要在输入一次用户名和密码下次就不需要了 这个命令则是在你的本地生成一个账号密码的记录 这样就不用
  • Python中执行MySQL语句, 遇到同时有单引号, 双引号处理方式 !r, repr()

    SQL语句 insert cmd INSERT INTO 0 SET 1 format db conn firmware info table join 0 1 r format k str v for k v in info dict i
  • linux读取按行读写文本文件

    include
  • 迪杰斯特拉算法浅析

    所谓的迪杰斯特拉算法 就是一个用来求一个图中某点到其它点的最短路径的算法 大致方法 遍历所有节点 找到离起点最近的一个点 那么这个点到起点的最小距离肯定是起点到这个点的这条边的权值 然后标记这个点被使用过了 以1中的那个点为中继 更新其它节
  • 进程和线程的区别

    简介 进程 进程是计算机中运行程序的实例 是操作系统进行资源分配和调度的基本单位 每个进程都有独立的内存空间和系统资源 不同进程之间相互独立 彼此不能直接访问对方的内存 进程之间的通信需要通过操作系统提供的特定机制 如管道 共享内存等 个人
  • nginx 之安全配置

    前言 看官网官网 一 控制并发连接数 1 在默认发布目录新建一个目录并保存一张图片 传送文件到server1 打开浏览器就能看到图片 2 测试 查看日至情况 cat usr local nginx logs access log http状
  • 时间计时android程序,Android实现时间倒计时功能

    本文实例为大家分享了Android实现时间倒计时功能展示的具体代码 供大家参考 具体内容如下 效果展示 MainActivity 主页面代码 public class MainActivity extends Activity privat
  • Nacos配置中心落地与实践

    一 背景 目前 我们公司各团队配置中心使用各异 电商使用的是 Spring Cloud Config 支付使用的是 Apollo APP 团队使用的是 Apollo Nacos 为了更好地应对公司业务的发展 统一基础设施技术栈必不可少 图片
  • ChatGPT-Next-Web:Vercel 和 Cloudflare 的快速部署

    项目地址 GitHub Chanzhaoyu chatgpt web 用 Express 和 Vue3 搭建的同时支持 openAI Key 和 网页 accessToken 的 ChatGPT 演示网页 依赖安装 1 安装node cur
  • BI-SQL丨行列转换

    行列转换 行列转换 在SQL Server中属于常见的基本操作 无论是搭建数仓 还是通过PowerBI进行数据分析 我们总会接触到各式各样的数据源 而在这些数据源中 除了标准的大型数仓外 我们很少能够拿到标准规范的数据表结构 接触最多的 往
  • 最熟悉的陌生人:ListView 中的观察者模式

    http blog csdn net u011240877 article details 52683711 RecyclerView 得宠之前 ListView 可以说是我们用的最多的组件 之前一直没有好好看看它的源码 知其然不知其所以然
  • tar分卷压缩解压

    1 使用tar分卷压缩 格式 tar cvzf filedir split d b 50m filename 样例 tar cvzf dir split d b 10m dirname tar gz 将 dir 打包 并切割为 10m 的包
  • python——*和**

    python中 和 的使用分两个方面 一个是计算 另一个是参数传递过程中元素的打包和解包 计算中的运用 和 在python中最常见的作用分别是 相乘 和 乘幂 如下 gt gt gt a 2 gt gt gt b 3 gt gt gt c
  • 20个Android游戏源码,…

    原文地址 分享20个Android游戏源码 希望大家喜欢哈 作者 我算哪根葱 分享20个 Android 游戏源码 希望大家喜欢哈 http www apkbus com android 21834 1 1 html Android 疯狂足
  • 凸优化学习(三)——凸函数

    注意 本文内容来自于吴恩达老师cs229课堂笔记的中文翻译项目 https github com Kivy CN Stanford CS 229 CN 中的凸优化部分的内容进行翻译学习 3 凸函数 凸优化的一个核心要素是凸函数的概念 定义
  • vtm配置以及编码示例

    vtm配置以及编码示例 下载VTM源码 网址 VTM源码 选择对应的版本下载 版本从2 0到最新的版本 1 0版本的VTM需要使用HM的工具svn下载 VTM 1 0源码地址 https jvet hhi fraunhofer de svn
  • STM32F4 IAP 跳转 APP问题

    1 概念 IAP 的作用 网上其他资料已经有很多介绍了 这里放一个链接 不进行深入的介绍 本文的关注重点是Bootloader在跳转APP程序中出现的问题 IAP的实现原理讲解以及中断向量表的偏移 2 程序 本人主要做应用层的开发 所有Bo