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

第八章 STM32之IAP编程

1、IAP简介

IAP(In Application Programming)即在应用编程,IAP是用户自己的程序在允许过程中对User Flash的部分区域进行烧写,目的是为了产品发布后,可以方便地通过预留地通信口对产品中地固件程序进行更新升级。

2、 程序执行流程

STM32正常的程序运行流程是通过JTAG/SWD或者串口将APP下载到以0x08000000开始的地址空间中,先存储中断向量表,然后存储对应的中断服务函数入口地址,最后是主程序main。程序执行过程中,如果发生中断请求会跳转到中断向量表去查询中断号,并进入对应的中断入口执行完成后回到中断发生打断的断点处。

加入了IAP后程序执行流程如图所示:

加入了IAP后,APP还是从0x08000000开始存储,依旧是中断向量表、中断入口函数、main函数,只不过在main函数中添加了一个IAP功能,这个函数主要是将通过串口、网口、USB等外设通信接口接收到的bin文件加载到程序存储的某个未使用的地址空间中。这个bin文件中也是完整的程序包括:中断向量表、中断入口函数、main函数等。加载完成后,可以使用IAP将程序的执行指针PC跳转到新添加的bin文件的地址头部,也就是整个程序只执行bin文件的功能。

3、IAP下载流程

STM32正常使用中,用户应用程序存储在以0x08000000开头的地址空间中,ST公司的程序引导文件bootloader存储在0x1FFFF000 - 0x1FFF F7FF中。使用串口下载代码就会通过bootloader才能将用户应用程序下载到以0x08000000开头的地址空间中,使用JTAG/SWD可以直接将代码下载到以0x08000000开头的地址空间中。下载流程如图所示

IAP下载流程就是在原本正常执行的程序中,添加了自己编写的bootloader(这个和STM官方地bootloader没有关系)通过外设接收bin文件(这个时候文件存在闪存中,SRAM的某个区域中[可自定义开始地址])然后保存到code程序存储区中。 这里可以选择直接bin中的程序,或者跳转到bin程序中,依旧执行以前老版本的程序。

4、APP程序起始地址设置方法

也就是说,一个code区域中,存放了STM32芯片本身自带的bootloader,和用户开发的APP1,以及即将存入进来的APP2。系统提供的bootloader的地址空间时固定的,APP1的起始地址可以默认为0x08000000,大小可以通过Keil来查看当前APP所占内存时多少。

4.1 Code区内存

Code区的地址是从0x00000000-0x1FFFFFFF的512M空间,主要实现存储用户自定义代码和ST官方提供的bootloader。

  • bootloader存放在 0x1FFF F000 - 0x1FFF F7FF的2K的地址空间中

  • 用户选择字节存放在0x1FFF F8000 - 0x1FFF F80F的16K地址空间中

  • 用户自定义代码存放在 0x0800 0000 - 0x0804 0000 的256K地址空间中

CPU:STM32F103RCT6,LQFP64,FLASH:256KB,SRAM:48KB;
flash起始地址为0x8000000,大小为0x4000(16进制)—>262144字节(10进制)—>256KB。地址空间为:0x08000000 - 0x0803FFFF
RAM起始地址为0x20000000,大小为0xC000(16进制)—>49125字节(10进制)—>48KB。地址空间为:0x20000000 - 0x2000BFFF

4.2 APP地址设置

针对于用户开发的程序,需要知道程序会占用多大的内存(ROM和RAM)使用Keil对程序进行编译生成内容code、RO-data等

在keil编译后,会生成如图所示

Code:    程序代码,存储在rom中
RO-data:只读数据,存储在rom中
RW-data:可读可写数据,即存在ram中,也存储在rom中
ZI-data:未初始化数据,上电后在ram中划分一个区域统一存储
程序占用ROM = code + RO-data + RW-data
RAM = RW-data + ZI-data

在下载代码时,需要设置代码下载的起始地址,0x08000000是ROM的起始地址,0x02000000是RAM的起始地址,RAM是数据存储器,存储的是零时数据,每次执行不同程序,RAM都是从0x02000000开始。

这里设置了起始地址,会将程序29.7KB大小依次存入到以0x08000000(实际上是0x08000000+0x04 偏移地址)开头的地址空间中。全局变量,动态分配内存、局部变量等存在RAM中从0x02000000开始的地址空间,最大存到0x02000000 + 0xC0000

APP2

APP2的内存使用为ROM=30420+6804+256=37580->0x92CC->36.67K

RAM = 356+2012=2368->0x940->2.31K

最终,在code区呈现的状态为:

APP1存储在以0x08000000到0x080076C8的地址空间中,STM32F103RCT6有256K的用户程序地址空间,所以这里设备APP2的起始地址空间为0x08010000能够实现将APP1和APP2同时存入flash中。

只考虑APP1和APP2的ROM地址不发生冲突,为什么不考虑RAM是否发生冲突???
对于代码来说,所有的数据都是存放在ROM中,然后在初始化过程中,会清空以前RAM中的内容,将全局变量、内存分配等存放在RAM中。所有RAM中的内容是不会发生冲突的。
APP1正在运行,跳转到执行APP2时,会清空RAM中内容重新填入,也就是说同一时刻只有一个APP能使用RAM。

5、串口接收bin文件

5.1 如何生成bin文件

要想生成bin文件,需要在keil中进行一些配置,如图所示(先生成hex文件,然后将hex文件变为bin文件)

这个地方添加的地址为:
E:\KeilMDK\ARM\ARMCC\bin\fromelf.exe --bin -o ..\OBJ|LED.axf
E:\KeilMDK\ARM\ARMCC\bin\fromelf.exe --bin -o ../../Output/atk_f429.bin ../../Output/atk_f429.axf

前面为Keil中 fromelf.exe的路径,后面为这个工程生成的.axf路径,这里添加的是相对路径。点击编译,会在OBJ目录下生成一个.bin文件。

5.2 串口接收bin文件

配置好后,编辑编译在文件生成路径下会生成一个bin文件

使用串口工具,打开这个bin文件,然后点击上传。

这里第一个APP能够接收这个bin文件是因为在程序中编写了bootloader,实现串口接收数据,并将数据存入到Flash中。

6、IAP代码实现

6.1 写入程序

传入写入flash的起始地址,数据数组和数据大小

参考第七章 STM32内部FLASH读写,每次对flash是半字,也就是uint16类型。每次以1024个uint16写入到flash中。
如果APP为3.4K,也就是执行一次for 会写入2k uint8的数据,剩余的1.4k从if(i)中写入到flash中

6.2 跳转到应用程序起始地址

在iap_load_app()函数中,接收到的数据,首先存储在SRAM中,然后再写入到flash中,

这里使用appxaddr检测栈顶地址是否合法(这里有个疑惑,为啥appxaddr == 0x0801000 与上一个值会是0x20000000):这是因为STM32程序的前两个字(8字节)必须是栈顶地址和复位向量表。
也是就算是如果设置0x08010000为程序的起始地址,这个地址存储的栈顶地址,栈顶地址一定是指向SRAM(0x200000000~2001FFFF之间 具体要根据不同芯片,有不同的SRAM大小)。所以,0x08010000 的地址指向 0x20000000+size的区域。

为什么appxaddr+4是因为复位向量表的地址是这个,程序也是从复位开始执行的

http://www.dtcms.com/a/273757.html

相关文章:

  • mysql数据库导入导出命令
  • ARM架构CPU的市场和生态
  • 欢乐熊大话蓝牙知识26:想让设备秒连?Connection Interval 配得对吗?
  • 零碳园区:安科瑞EMS如何破解新能源消纳难与高耗能产业转型困局
  • 锁的艺术:从Mutex到ReentrantLock,掌握并发编程的脉搏
  • 大模型使用
  • Qt 实现新手引导
  • Windows解决 ping 127.0.0.1 一般故障问题
  • unity 有打击感的图片,怎么做动画,可以表现出良好的打击效果
  • STM32串口通信(寄存器与hal库实现)
  • 2025年7月11日学习笔记一周归纳——模式识别与机器学习
  • 高校智慧教室物联网系统设计与实现
  • 《磁力下载工具实测:资源搜索+高速下载一站式解决方案》
  • 串行数据检测器,检测到011,Y输出1,否则为0.
  • JavaScript加强篇——第五章 DOM节点(加强)与BOM
  • 网安系列【18】之SpringBoot漏洞
  • React Three Fiber 实现 3D 模型点击高亮交互的核心技巧
  • 小架构step系列11:单元测试引入
  • Rocky Linux上使用NVM安装Node.js 18
  • 老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)
  • 大数据时代UI前端的用户体验设计新思维:以数据为驱动的情感化设计
  • golang -gorm 增删改查操作,事务操作
  • 分布式推客系统全栈开发指南:SpringCloud+Neo4j+Redis实战解析
  • Neo4j启动
  • 从一到无穷大 #47:浅谈对象存储加速
  • 基于vscode的go环境安装简介
  • 企业级LLM知识库:构建智能知识管理平台,赋能业务增长
  • 降本增效!上云真香!
  • 如何批量旋转视频90度?
  • 基于Selenium和FFmpeg的全平台短视频自动化发布系统