STM32F4 IAP 跳转 APP问题

这篇具有很好参考价值的文章主要介绍了STM32F4 IAP 跳转 APP问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 概念

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

2. 程序

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

2.1 Bootloader 程序

  1. CubeMX 配置
  步骤1:使用的芯片为STM32F407ZGT6
stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
  步骤2:选择时钟源(根据自己的板子进行选择)
stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
  步骤3:时钟配置
stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
  步骤4:项目配置
stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
  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才行
stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
    步骤2:Linker 中修改ScatterFile 文件;

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

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

stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
HAL_DeInit(); HAL库反初始化;
HAL_RCC_DeInit(); RCC配置反初始化;

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

stm32程序跳转,STM32,stm32,单片机,嵌入式硬件
stm32程序跳转,STM32,stm32,单片机,嵌入式硬件文章来源地址https://www.toymoban.com/news/detail-679140.html

4. 其他问题

4.1 可能导致APP死机的原因

  1. Bootloader启动的外设比APP的多,导致死机,需要在跳转到APP时清理不需要的外设配置;
  2. Bootloader开启了某个终端,在APP中没有配置相应的处理函数,导致死机;该问题可通过Bootloader程序的@4 @5 @7来解决;

到了这里,关于STM32F4 IAP 跳转 APP问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    说明:此篇为学习记录。可能存在错误或者不足。如有问题请指出。 主控芯片:STM32F411CEU6 主控开发板:WeAct STM32F411CEU6最小系统板 TFT-LCD屏幕:合宙1.8寸TFT-LCD,驱动为ST7735s MDK版本:5,32 HAL库版本:1.27.1 STM32CubeMX版本:6.7.0 ST7735s支持8080并口,3线和4线串行接口,模块的驱动方

    2024年02月03日
    浏览(49)
  • 使用STM32F103的串口实现IAP程序升级功能

    🎬IAP程序烧录全过程演示: ✨这几天折腾IAP升级功能,狂补了很多相关BootLoader相关的知识。本来最想实现IAP升级程序的方式是,基于SPI通讯的SD卡,借助挂载的FatFS文件系统,来实现对目标stm32芯片的自身程序的升级,奈何没有实现,只能求其次,先来通过官方现有的串口实

    2024年02月10日
    浏览(46)
  • 关于STM32F4系列中printf重定向问题详解

    前言 关于 printf函数 和 fputc函数 联系和区别 联系: 1.共同目标: printf 函数和 fputc 函数都用于将字符 输出到指定的输出流中 。 2.字符输出: 两个函数都可以用于输出一个字符,但在实际使用时, printf 函数 通常用于输出 格式化的数据 ,而 fputc 函数 更常用于 单个字符的直

    2024年02月03日
    浏览(33)
  • (第48-59讲)STM32F4单片机,FreeRTOS【事件标志、任务通知、软件定时器、Tickless低功耗】【纯文字讲解】【】

    【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】 (第1-8讲)STM32F4单片机,FreeRTOS基础知识总结【视频笔记、代码讲解】【正点原子】【原创】 (第9-10讲)STM32F4单片机,FreeRTOS任务创建和删除(动态方

    2024年02月01日
    浏览(49)
  • stm32 在线升级程序 bost IAP程序 + app程序

    机器内 bootloader程序 启动默认程序 默认程序有 串口判断 是否收到 升级命令 收到升级命令后 接受串口发送过来的 更新程序 接受完成后 跳转到新程序位置开始执行 https://www.zhihu.com/people/lian-zhu-50 首先arm单片机控制程序运行是通过PC指针完成的,PC指到哪里,程序就运行到哪里

    2024年02月10日
    浏览(39)
  • GD32F4移植STM32F4

    近期在项目中采用了GD32F407VET6替换原项目中的STM32F407VET6,网传GD的兼容性很好,之前也用F1系统的替换了一下,按照CSND各位大佬的经验一步步改进了代码,测试直接通过,现在也一直在项目中实际应用了,一直没有出问题。 所以这SMT时,嘉立创没有STM的货果断换成了GD,可换时

    2024年02月16日
    浏览(54)
  • STM32F4使用高级定时器(TIM1和TIM8)输出PWM问题

    STM32F4使用高级定时器(TIM1和TIM8)输出PWM时要使用TIM_CtrlPWMOutputs使能PWM输出,否则不会输出PWM波形,这一点是和通用定时器输出PWM不一样的地方,通用定时器是不用配置TIM_CtrlPWMOutputs函数的。、

    2024年02月15日
    浏览(33)
  • STM32F0实现IAP升级固件

    好几年前写过一篇关于 STM32 bootloader 升级固件的博客,但是使用的芯片是 STM32 F4 系列,升级固件的方式是在外部 flash 的 fat32 文件系统中存入固件文件,reset 后通过特定按键进入 IAP 程序。 最近需要在 STM32 上实现同样的 IAP 功能,但是方式不太一样,也发现一些芯片的差别,

    2024年02月14日
    浏览(37)
  • 【STM32】STM32F4 GPIO详解与配置

    GPIO是通用输入输出端口的简称,为STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32芯片的GPIO被分成很多组,每组有16个引脚,所有的GPIO引脚都有基本的输入输出功能。 其中保护二极管使GPIO能够5V电压容忍。在

    2024年02月07日
    浏览(39)
  • [GD32F4]基于GD32固件库移植cherryusb[STM32F4]

    [GD32F4]基于GD32固件库移植cherryusb[STM32F4] 使用开发板是淘宝买的不知名开发板,没什么好说的,具体的型号是GD32F450VET6。 使用的cherryusb版本是0.9.0版本。 使用的GD32官方固件库版本是:GD32F4xx_Firmware_Library_V3.0.4 cherryusb最牛的地方在于抛弃掉所有的依赖,只需要知道芯片的usb中断

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包