【STM32 IAP技术实现】适合小白“食用”(以STM32F103C8T6为例)

这篇具有很好参考价值的文章主要介绍了【STM32 IAP技术实现】适合小白“食用”(以STM32F103C8T6为例)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言:

  想必大家对单片机烧录一词都不陌生,就是将程序下载到我们的板子(MCU)里面。常见的烧录方法有用Keil下载,或者是编译出Hex文件通过烧录软件(上位机例如:muisp、flymcu)、烧录器软件(例如:J-LINK、ST-LINK)烧录,从程序的角度来看通过烧录,它被“更新”了。
  但是实际应用中单片机被封装在产品的内部,甚至有些涉及到加密(常见的是对汽车芯片的调试),这时没有烧录口,我们从一个设计者的角度来看,怎么才能对程序“更新”呢?

–>本文以以STM32F103C8T6为例,介绍使用串口通过Bootload方式实现程序的更新,即IAP技术

ps:小白想看懂IAP原理从第一章开始;使用IAP更新方法移步第三章;上位机使用专用IAP助手;


一、什么是IAP?

IAP-百度百科

   IAP是(In Application Programming)即应用编程,IAP是指用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。
   通俗的来说,IAP是将Flash划分为两部分,两部分区域各存放一个程序,一个叫Bootloader(引导加载程序),另一个叫user application(用户应用程序),下文简称APP。IAP技术的关键在于Bootloader程序,因为我们要依靠它来在单片机内部帮我们更新的APP程序。
   所以在我们自己不方便烧录时,通过在Flash中内置一个Bootloader程序帮我们更新APP程序,这也是我们经常听到的更新固件。
   在程序执行初始进入bootloader,在bootloader里面检测条件是否被触发(可通过按键是否被按下、串口是否接收到特定的数据、U盘是否插入等等),如果有则进行对user application进行擦除和重新写入操作,如果没有则直接跳转到user application执行应用;如果有则进行擦除用户代码(Old APP)并重新写入新的用户代码(New APP)

摘自:静静地思考_STM32+IAP方案的实现,IAP实现原理(详细解决说明)_一、什么是IAP,为什么要IAP


   

二、IAP实现原理(以STM32F103C8T6为例)

2.1 Bootloader运行流程

   
   既然说IAP技术关键在于Bootloader,那它又是如何帮我们更新APP的呢?

   当芯片上电后,首先是第一个项目代码(Bootloader)开始运行,它作如下操作: (摘自百科)  
      1)检查是否需要对第二部分代码进行更新   
      2)如果不需要更新则转到4) 
      3)执行更新操作   
      4)跳转到第二部分代码执行

   也就是说我们先将Bootloader程序烧录(正常烧录方式)到MCU中,Bootloader包含完整的程序(Main函数等等),不更新时他就在我们设定的Flash内存中等待更新指令,需要更新时才帮助我们更新。
   

2.2 Flash分区

   既然IAP技术要依靠Bootloader,且Bootloader和APP程序在Flash不同区,那么先搞清楚Flash怎么分区则是重中之重;
   
   STM32F103C8T6为中容量产品,所以Flash闪存容量为128K,查手册可知,地址为0x0800 0000-0x0801 FFFF;
   
   PS:这里关于STM32F103C8T6内置Flash是64K还是128K个人感觉手册写的比较含糊,储存器映像里是128K,我一直都是按照128K在是使用,但是配置又写分为64K与128K。
   这里有一篇博文我觉得可以参考参考
   所以容量确实有128K,但是只有64K经过测试。尽量还是设置为64K,以免出现一些奇奇怪怪的问题;stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   
   所以Bootloader程序例如下图放在Flash中 0x 0800 0000 - 0x 0800 1000地址占用4K大小空间(这样设置只是举个例子,大小位置都可以自己设置),当然设置Bootloader程序位置和APP程序不能重叠

         stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

    看到这里可能有小伙伴会有疑惑:这里不是ROM区吗,怎么起始地址是Flash起始地址??
   Flash可以说是兼容ROM和RAM功能,属于广义上的ROM。

2.3 那程序是如何在两个区之间运行的呢??

   
   因为一旦涉及到Flash分区,两个区程序中相应的中断向量,中断函数就需要偏移(各用各的中断)【挖个坑有读者感兴趣后面可以写一篇中断文章一起交流】,那么在Flash中不同区域中断向量表是如何联系以及执行;
   下图中,flash中存储了两块程序,同时存在了两个中断向量表。
上电后,程序执行顺序如下:stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   
   STM32复位后,还是从0X08000004地址(第一个中断向量,所以也说明复位中断的优先级最高) <1> 取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到IAP的main函数,如图标号①所示;
   在执行完IAP以后(即将新的APP代码写入STM32的FLASH,灰底部分。新程序的复位中断向量起始地址为0X08000004+N+M),跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main函数,如图标号②和③所示,同样main函数为一个死循环,并且注意到此时STM32的FLASH,在不同位置上,共有两个中断向量表
   在main函数 (APP程序) 执行过程中,如果CPU得到一个中断请求, PC指针(指示程序运行位置的指针)仍强制跳转到 地址0X08000004中断向量表处,而不是新程序的中断向量表 (APP程序) ,如图标号④所示;程序再根据我们设置的中断向量表偏移量,
跳转到对应中断源新的中断服务程序中,如图标号⑤所示;在执行完中断服务程序后,程序返回main函数继续运行,如图标号⑥所示。
   通过以上两个过程的分析,我们知道IAP程序必须满足两个要求:
   1) 新程序必须在IAP程序之后的某个偏移量为x的地址开始
   2) 必须将新程序的中断向量表相应的移动,移动的偏移量为x;返回起始地址,而是返回了最新的中断向量表地址。
   摘自正点原子-IAP测试实验
   

<1>:不知道大家有没有疑问就是关于这里为什么第一个中断向量地址是0x0800 0004 而不是0x0800 0001或者0x0800 0002等等?
—>这里推荐大家去看看这篇文章,通俗的来说就是,32位单片机CPU一次处理32位,这样寄存器等等一次收发32位性能最优。

2.4 IAP过程的跳转(IAP核心在于进程的转换)

   
   通过上图的相关分析,我们就能够知道,IAP的跳转过程无非是将PC指针跳转至用户APP中断向量表的开头,但在这个过程中,必须要先关闭所有中断,否则会让程序直接跑飞。
   具体代码如下(示例):

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

   该文件总共只有2个函数,其中,iap_write_appbin函数用于将存放在串口接收buf(寄存器) 里面的APP程序写入到FLASH。iap_load_app函数,则用于跳转到APP程序运行
   其参数appxaddr为APP程序的起始地址,程序先判断栈顶地址是否合法,在得到合法的栈顶地址后,通过MSR_MSP函数(该函数在sys.c文件)设置栈顶地址,
最后通过一个虚拟的函数(jump2app)跳转到APP程序执行代码,实现IAP-APP的跳转。

第一句:
   我们判断中断向量表的首字节,也就是系统栈堆顶部的值是否在0x20000000-0x20002000之间。因为APP的启动文件最开始就是初始化栈堆空间,如果这个里的栈顶值正确,那么就说明应用程序已经下载,并且已经初始化完成了。
第二句:
   由于在整个跳转过程中不允许中断发送,因此这里先屏蔽所有中断。
第三句:
   在common.c文件的第34行定义了pFunction Jump_To_Application;
(ApplicationAddress + 4)即为0x0800 3004也就是中断向量表中的复位句柄。
第四句:
   __disable_irq()在官方文件中是一个空函数,作用是关闭用到的中断,需要用户自己编写函数,用到什么中断就关闭什么。
第五句:
   查看pFunction的定义,我们可以在common.h文件中找到typedef void (pFunction)(void);
   该函数声明了一个函数指针,加上typedef之后,pFunciton也只是类型void ()(void)的一个别名。
所以Jump_To_Application = (pFunction) JumpAddress; 此时Jump_To_Application指向了复位函数所在的地址;
第六句:
   设置了主函数的栈指针
第七、八句:
   清除所有挂起的中断,同时取消屏蔽总中断
第九句:
   跳转至用户程序,也就是将PC指针跳转至了APP中断向量表中的复位句柄处。
   摘自正点原子-IAP测试实验
   

2.5 IAP过程的总结

   
   根据上文的相关分析,其实IAP过程除 设置好分区 之外,最重要的是跳转进程,其中要关闭所有中断,通过函数指针的形式将PC指针跳转至APP的复位句柄处,那么就能跳转进程到我们的APP程序。
   对于APP程序来说,一方面其存储地址不能和Bootloader程序重复,另一方面在程序开始时必须重定位中断向量表位置。


—>下文将介绍Bootloader程序如何接收我们想更新的APP程序


三、上位机软件(以IAP专用串口助手为例)

3.1上位机又是什么???

   1.1-做了这么久,才知道什么是上位机
   这里所说的上位机软件也就是实现IAP中,给Bootloader发送更新指令的一种方式(类似的可以根据串口方式、无线方式等发送),因为考虑到实际应用中IAP的需要: 所以采用上位机的方式发送更新指令。更新指令中包含帧头和CRC校验以及更新程序大小、分包等等。(可以使用Qt编写上位机程序自定义帧头)
   本例中上位机协议如下图:
   
    stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
    stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

   stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

3.2 上位机发送程序基本流程

    stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

四、教程(以STM32F10C8T6为例)

   在实际操作之前应该明白原理,熟读本例源码,再上手操作这一点很重要!!!

4.1 Bootloader的写入

第一步:keil设置MCU内存大小

   由于本例使用的是STM32F103C8T6,中容量芯片,需要修改对应Flash宏。

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

   点击魔术棒,切换到C/C++选项卡,将Preprocessor Symbols下的Define栏中改成STM32F10X_MD。
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
这里大家根据自己MCU用户手册修改

   

第二步:设置Bootloader程序的位置和大小

   设置Keil在烧写Bootloader时的Flash大小,这里限制为0x1FFF,8kB,所以APP层的代码应该在0x0800 2000的位置。

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   
   实际上Bootloader程序用不到8K的储存空间,一般2K都足够了,本例实际使用不到6K。

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   如何从keil工程知道使用了多少RAM和ROM空间
   如上,我们便完成了对Bootloader的设置,通过烧录口正常将程序烧录到MCU中,接下来就是通过Bootloader帮助我们烧录APP程序;

4.2 APP程序的烧写

第一步:keil设置APP的烧录位置

   设置Keil在烧写APP时的起始位置,一定不能与Bootloader程序地址重合。故写入位置应该从0x0800 2000开始。
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

第二步:APP程序中设置地址偏移量

    本程序相对向量基地址偏移8K字节 ,对应Bootloader程序设置的8K空间
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

第三步:生成bin文件,再使用IAP上位机向MCU发送更新指令

   大家平时烧录对Hex文件应该都不陌生,可是这里为什么要选择使用BIN文件呢?
   在KEIL中生成bin文件的方法
   BIN文件为纯二进制码流,不用解析直接放在指定的Flash位置。
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   
   成功生成BIN文件Output如下:
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机   

4.3 通过上位机实现IAP

第一步:打开串口

   
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   

第二步:选择需要更新的BIN文件

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
   

第三步:下载APP程序

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机

   上图未烧录Bootloader程序上位机发送更新请求

stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
stm32f103c8t6 iap,stm32,嵌入式硬件,单片机
烧录Bootloader程序后,成功更新APP程序

更新成功后LED(PC13)闪烁

STM32F103C8T6实现IAP更新APP程序

   
   APP程序部分中断偏移有待改进,同时也正在实现用外挂Eeprom储存的方式完善IAP,欢迎有兴趣的小伙伴一起交流学习。

2023/12/2
外挂Eeprom方式已经实现;详情请看这篇文章
现在实现BIN文件拆包后乱序方式储存到Eeprom中;

网盘链接_有效期至2024-11
提取码:LUCK文章来源地址https://www.toymoban.com/news/detail-773099.html

到了这里,关于【STM32 IAP技术实现】适合小白“食用”(以STM32F103C8T6为例)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • STM32F103实现USB虚拟串口

            今天分享一下STM32F103如何实现虚拟串口,目标是让新手也能上手,如果谁没看懂或者照着做功能没有实现可以私信我,只要我看到一定回复。        本次使用的是STM32F103C8T6核心板,按以下步骤新建一个STM32CubeMX工程。        步骤一 :先输入MCU型号搜索芯片,软件

    2024年02月09日
    浏览(45)
  • STM32F103实现数字振镜XY2-100协议

    一、 XY2—100协议如下         该协议时钟(SENDCK)为2MHz ,SYNC为同步信号,CHANNELX/Y 是数据信号,它有20位组成,其中C2、C1、C0是振镜运动方向值,参考值为001,D15—D0是数据位,它是16位的二进制数,用来控制振镜转过的角度大小(取值为0~65535,即将振镜轴的转动角度范围

    2024年02月16日
    浏览(148)
  • STM32F4 IAP 跳转 APP问题

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

    2024年02月11日
    浏览(47)
  • 【STM32】STM32F103C8T6串口通信,实现3个串口收发数据

    串口通信(Serial Communications)实现单片机与电脑或者其它外设进行通信,通信时只需两根线(TX,RX)就可以实现数据传输。STM32f103有三个串口,分别为串口1(RX PA10, TX PA 9),串口2(RX PA3,TX PA2),串口3(RX PB11,TX PB10)。 以下代码是配置三个串口: usart.c usart.h main.c 注意,

    2024年02月12日
    浏览(48)
  • STM32-IAP基本原理及应用 | ICP、IAP程序下载流程 | 程序执行流程 | 配置IAP到STM32F4xxx

    ①在线编程(ICP,In-Circuit Programming) :通过JTAG/SWD协议或者系统加载程序(Bootloader, 串口 )下载用户应用程序到微控制器中。 ②在程序中编程(IAP,In Application Programming) :通过任何一种通信接口(如IO端口,USB,CAN,UART,I2C,SPI等)下载程序或者应用数据到存储器中( 需要在此前通过在线编

    2024年02月07日
    浏览(43)
  • STM32F407串口IAP远程升级程序

    相关代码和工程文件链接:https://pan.baidu.com/s/1wN4THWJwqzjjIe7e2TENBA?pwd=o86o 提取码:o86o         STM32代码烧录主要有三种:ICP、ISP、IAP。         ICP(In Circuit Programing),在电路编程,通过JTAG或者SWD接口进行程序的烧录,就是平时利用ST-Link或者J-Link烧录程序;       

    2024年02月10日
    浏览(107)
  • STM32F103R8T6 SPWM实现正弦波输出

    PWM合成正弦波,原理什么的不详细说了,概括一下就是 PWM有效面积的积分 = 正弦波的有效面积。PWM的频率越快,细分的越多,锯齿也就越不明显。 做法是:首先利用正弦波取点软件,取点1000个,生成一个正弦波的数组。 PWM波的频率(F_PWM)与正弦波频率(F_SIN)之间的对应关系与

    2024年02月03日
    浏览(55)
  • 正点原子STM32F103精英版+HAL库实现4×4矩阵按键检测

    首先声明,本人小白一枚,所做的工作都是借鉴网上的大佬+自己摸索,但是都是亲测实际有效的。 因为所需要的功能开发板自带按键不够用,所以购买了4×4矩阵按键,当时购买的时候以为一个按键对应一个IO口,后来发现不是这样的,会浪费太多的IO口,4×4矩阵键盘用8个

    2024年02月06日
    浏览(55)
  • 摇杆按键+SG90 实现舵机云台(STM32F103C8T6)

    STM32F103C8T6最小系统板*1 SG90舵机(180°)*2 摇杆按键*1 舵机支架*1 面包板*1(非必须) 杜邦线若干 类似这种的支架,不过需要自己裁切嵌入的部分 代码很简单,主要使用ADC双通道读取两个电位器的值(实际上就是电压),通过获取到的值的范围来确定上下左右,从而来改变两

    2024年02月14日
    浏览(50)
  • STM32F103C8T6最小系统板实现蜂鸣器报警

    SWD方式下载程序,4线,VCC,GND。 SWDIO:Serial Wire Data Input Output,串行数据输入输出引脚,作为仿真信号的双向数据信号线,建议上拉。 SWCLK:Serial Wire Clock,串行线时钟引脚,作为仿真信号的时钟信号线,建议下拉; 蜂鸣器的IO口接在了最小系统板的PB12引脚上。 蜂鸣器的操作

    2024年02月01日
    浏览(56)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包