问题记录远程烧录和看门狗冲突

文章目录

目录

文章目录

问题描述

1.问题分析

2.结论

二、IAP简介

2.1.正常情况下代码执行流程

2.2 IPA之后代码运行情况

2.3 远程烧录功能实现流程图

2.4. APP程序起始地址设置方法

2.5 中断向量表的偏移量设置方法

2.6.生成bin文件

2.7 指针跳转函数

总结



问题描述

使用内部FLASH暂时保存IAP升级时的程序数据,在IAP升级的过程中,需要首先擦除内部FLASH中一块空间写入跳转标志,然后跳入IAP, 工程中有使用到IWDG,喂狗间隔大约2S,同样的看门狗时间旧版不能跳转IAP。

1.问题分析

使用旧版复现不能跳转IAP程序情况,主要代码如图1:

开始认为是跳转之前没有关闭所有中断的问题,在收到跳转命令之后关闭所有中断经过测试问题没有得到解决。

图2 关闭所有中断

从跳转为什么需要这么长时间,经过测试发现在跳转没完成之前,没有及时喂狗,导致驱动器复位,在初始化过程中加入printf打印 Reset 具体结果如图:

图3 看门狗导致系统复位

发现在发送完跳转指令之后系统又进行了一次系统复位。

图4 扇区擦除

需要擦除的扇区起始地址为0x080C0000查阅F407手册,了解到该扇区大小为128KB,
查阅F407VET6手册发现


                                                                                          图5 扇区地址分布图

图6  F407数据手册节选图

在PSIZE=x 8 时,典型擦除时间为2S,最大时间为4S,经过测试FLASH擦除时间为2.284S与数据手册基本符合。

图7 示波器测试擦除时间图

2.结论

新版驱动器的2S定时时间也在跳转bootloader需要的时间边缘,经过验证将新版的2S看门狗下调,新版也会发生不能跳转bootloader的问题,将FLSASH擦除PSIZE=x 8改为PSIZE=x 32可以节约1S左右的时间。

二、IAP简介

IAP(In Application Programming)即在应用编程,IAP 是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。 通常实现 IAP 功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如 USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。

图1 STM32加入IAP后代码运行流程

APP程序,不仅可以放到 FLASH 里面运行,也可以放到 SRAM 里面运行

2.1.正常情况下代码执行流程

从 0X08000004 地址取出复位中断向量的地址,并跳转到复位中断服务程序,如图标号①所示;在复位中断服务程序执行完之后,会跳转到我们的 main 函数,如图标号②所示;而我们的 main 函数一般都是一个死循环,在 main 函数执行过程中,如果收到中断请求(发生中断),此时 STM32F4 强制将 PC 指针指回中断向量表处,如图标号③所示;然后,根据中断源进入相应的中断服务程序,如图标号④所示;在执行完中断服务程序以后,程序再次返回 main 函数执行,如图标号⑤所示。

2.2 IPA之后代码运行情况

与正常情况不同的是,在执行完IAP函数之后(即将执行APP函数),跳转至新APP程序的复位向量表开始执行,然后进入APP函数的死循环,在APP函数中发生中断请求之后,C 指针仍强制跳转到地址0X08000004 也就是Bootloader代码的中断向量表处,而不是APP代码的中断向量表,如图标号④所示;再根据APP函数当中的中断向量表偏移量,跳转到APP函数的中断向量表,如图标号⑤所示。

2.3 远程烧录功能实现流程图

前提是已经将Bootloader和APP两部分代码烧录进去,Bootloader程序首次需要通过烧录器进行烧录,APP函数可以通过烧录器烧录,也可以直接通过Bootloadr写入。

2.4. APP程序起始地址设置方法

此处设置的是APP代码的烧录地址和大小,只给IAP代码留了64K的代码空间,一般情况下Bootloader代码比较小,这个空间根据实际情况进行调整。通过串口或者其他协议接收到的新代码bin文件缓存在SRAM当中或者FLAS当中。(需要确保SRAM或者FLASh空间够用)

u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X20001000))); //绝对定位

其中的USART_REC_LEN决定缓冲区的大小,根据代码大小确定。

可以通过绝对定位来决定新代码的存储位置。

2.5 中断向量表的偏移量设置方法

在系统启动的时候,会首先调用 SystemInit 函数初始化时钟系统,同时SystemInit 还完成了中断向量表的设置

#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
/* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
/* Vector Table Relocation in Internal FLASH. */
#endif

VTOR 寄 存 器 存 放 的 是 中 断 向 量 表 的 起 始 地 址,默认情况下VECT_TAB_OFFSET未定义,我们设置的偏移量为0x10000,在 FLASH APP 的 main 函数最开头处添加如下代码实现中断向量表的起始地址的重设。

SCB->VTOR = FLASH_BASE | 0x10000; //FLASH 情况下的地址偏移
SCB->VTOR = SRAM_BASE | 0x1000;  //SRAM 情况下的地址偏移

2.6.生成bin文件

方法1:绝对路径方式

方法2:相对路径方式

$K\ARM\ARMCC\bin\fromelf.exe --bin --output=@L.bin !L 

更换电脑之后不需要任何更改在编译操作后,在xxx.uvprojx当前目录下,可看到生成的bin文件。

2.7 指针跳转函数

//iap跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)  //检查栈顶地址是否合法.{ jump2app=(iapfun)*(vu32*)(appxaddr+4);     //用户代码区第二个字为程序开始地址(复位地址)        MSR_MSP(*(vu32*)appxaddr);      //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)jump2app();                                 //跳转到APP.}
}//应用程序段跳转到iap
//appxaddr:用户代码起始地址.
void app_load_iap(u32 appxaddr)
{ if(((*(vu32*)appxaddr)&0x2FF00000)==0x20000000) //检查栈顶地址是否合法.{ Close_Devicer_Iint();jump2iap=(iapfun)*(vu32*)(appxaddr+4);    //用户代码区第二个字为程序开始地址(复位地址)        MSR_MSP(*(vu32*)appxaddr);          //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)jump2iap();                     //跳转到APP.}
}

2.8 写FLASH过程

//appxaddr:应用程序的起始地址
//appbuf:应用程序CODE.
//appsize:应用程序大小(字节).
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
{u16 t;u16 i=0;u16 temp;u32 fwaddr=appxaddr;//当前写入的地址u8 *dfu=appbuf;for(t=0;t<appsize;t+=2){                           temp=(u16)dfu[1]<<8;temp+=(u16)dfu[0];   dfu+=2;//偏移2个字节iapbuf[i++]=temp;     if(i==1024){i=0;STMFLASH_Write(fwaddr,iapbuf,1024);  fwaddr+=2048;//偏移2048  16=2*8.所以要乘以2.}}if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.
}

其余的通讯协议可以自定义,包括控制指令以及响应指令。


总结

问题记录!

问题记录远程烧录和看门狗冲突相关推荐

  1. 学习记录:使用STM32F1看门狗

    目录 前言 一.独立看门狗 1.1. IWDG主要性能 1.2.IWDG功能描述 1.3.寄存器访问保护 1.4.配置独立看门狗的步骤 二.窗口看门狗 2.1.WWDG主要特性 2.2.WWDG功能描 ...

  2. GD32F30x系列---看门狗基础配置

    GD32F30x系列内部有独立看门狗和窗口看门狗2种: 独立看门狗: 有独立的时钟源(IRC40K),不受主时钟的影响,如下图所示: 手册中提供了独立看门狗的最大最小超时时间,可以根据这个选择看门狗的 ...

  3. 基于RT1052 Awroks 使能看门狗记录(二)

    本文主要是通过迁移的思维,记录本人初次使用周立功的Aworks框架进行BSP开发 1. 首先阅读原理图 正常来说看门狗超时,CPU会直接复位,有时会要求输出复位脉冲.这个功能可以使能,也可以不使能. ...

  4. SP706看门狗使用记录

    "你喂狗了吗?"当你听到这句话时,不要以为是喂狗,闹笑话就不好了,这里说的喂狗是指给MCU加看门狗电路,看门狗不是"狗",是一种MCU监控电路 什么是看门狗 在 ...

  5. (3)看门狗 WDT:基于GD32F303RCT6单片机在RT-Thread下的零基础学习记录

    使用看门狗功能,一如既往地需要先使用ENV工具,打开看门狗功能,如下图 开启后重新编译工程, 然后当我开开心心地去粘贴官方的demo(WATCHDOG设备 (rt-thread.org))(文章最后会 ...

  6. nRF52832学习记录(八、WDT看门狗 )

    nRF52832 看门狗 使用 低频时钟源(LFCLK)提供时钟,是向下计数的定时器. 启动后,看门狗加载 CRV 寄存器中的指定值.然后开始计数,当计数到0后,会溢出产生 TIMEOUT 事件.看门 ...

  7. 看门狗芯片-SP706-调试记录

    一. 看门狗芯片 1.1 看门狗芯片与处理器引脚连接   本次主控单元使用的看门狗芯片为SP706芯片 .   引脚定义: 1.2 使能外部看门狗 (1) 看门狗芯片SP706芯片手册中的电路图: ( ...

  8. 第四天:关看门狗、设置栈、控制icache、重定位、链接脚本

    1.汇编写启动代码:关看门狗 什么是看门狗? 看门狗(watch dog timer看门狗定时器),比如:家门口有一只狗,这个狗定时会饿(譬如两小时一饿),狗饿了就会胡乱咬人,人进进出出要想保证安全必 ...

  9. ARM 看门狗机制 [包括MTK] 【1】

    watchdog一般是一个硬件模块(其实可以当做是一个定时器),其作用是,在嵌入式操作系统中,很多应用情况是系统长期运行且无人看守,导致程序跑飞,所以难免怕万一出现系统死机,那就悲剧了,这时,watc ...

最新文章

  1. 角度编码器 ST-3806-15-RS
  2. python能写软件吗-python代码能做成软件吗
  3. 【CTF大赛】第五届XMan选拔赛 ezCM Writeup
  4. php视频上传教程,php上传视频的代码_PHP教程
  5. 说说博客园的“关注”与“网摘”
  6. Flutter代码锦囊---切换时页面保持状态
  7. 南非醉茄提取物行业调研报告 - 市场现状分析与发展前景预测
  8. ThinkPHP 5.1+全开源带后台商城小程序源码程序+带详细安装使用文档
  9. 哨兵2号L1C数据下载及预处理
  10. 【2】嵌入式TCP/IP协议——————Art-Net处理流程
  11. 怎么把一台手机的便签转移到另一台手机上?
  12. 成都高新南区 高新西区 东部新区 多边形范围点位 AOI 高德
  13. Mentohust 编译安装方法 (2022)
  14. 作文第一次用计算机350,第一次作文350字
  15. python广告营销平台_python微信开发平台
  16. 微服务项目:尚融宝(40)(核心业务流程:申请借款额度(3))
  17. ARM920T内核工作模式
  18. 学会Python就能做游戏脚本开发?别天真了!
  19. 基于Unity3D的自动寻路车辆模拟
  20. 【数字IC基础】降动态功耗(降时钟翻转频率):门控时钟(clock gating)

热门文章

  1. 第10章 PCA降维技术
  2. 笔记本上修改蓝牙设备的名称
  3. java socket 单例_Java 单例模式的几种实现方式
  4. mysql消息队列推送到redis_Redis实现消息队列之发布订阅模式
  5. 科普:什么是网站安全证书,它对你的业务有什么作用?(上)
  6. 英雄联盟版本更新13.4
  7. RQN 273 马棚问题 dp
  8. 5款简单实用的WIN10软件推荐
  9. J Jack与Pony的战斗
  10. ajax beforesend 不执行,ajaxSetup(beforeSend不工作