STM32F103实现IAP在线升级应用程序

发布者:q13358975046最新更新时间:2022-10-11 来源: csdn关键字:STM32F103  IAP  在线升级 手机看文章 扫描二维码
随时随地手机看文章

一、环境介绍

MCU:  STM32F103ZET6


编程IDE:  Keil5.25


工程附加源码包下载地址: 

CSDN

https://download.csdn.net/download/xiaolong1126626497/25652410

 

二、 IAP介绍 

IAP,全称是“In-Application Programming”,中文解释为“在程序中编程”。IAP是一种对通过微控制器的对外接口(如USART,IIC,CAN,USB,以太网接口甚至是无线射频通道)对正在运行程序的微控制器进行内部程序的更新的技术(注意这完全有别于ICP或者ISP技术)。


ICP(In-Circuit Programming)技术即通过在线仿真器对单片机进行程序烧写,而ISP技术则是通过单片机内置的bootloader程序引导的烧写技术。无论是ICP技术还是ISP技术,都需要有机械性的操作如连接下载线,设置跳线帽等。若产品的电路板已经层层密封在外壳中,要对其进行程序更新无疑困难重重,若产品安装于狭窄空间等难以触及的地方,更是一场灾难。但若进引入了IAP技术,则完全可以避免上述尴尬情况,而且若使用远距离或无线的数据传输方案,甚至可以实现远程编程和无线编程。这绝对是ICP或ISP技术无法做到的。某种微控制器支持IAP技术的首要前提是其必须是基于可重复编程闪存的微控制器。STM32微控制器带有可编程的内置闪存,同时STM32拥有在数量上和种类上都非常丰富的外设通信接口,因此在STM32上实现IAP技术是完全可行的。 


实现IAP技术的核心是一段预先烧写在单片机内部的IAP程序。这段程序主要负责与外部的上位机软件进行握手同步,然后将通过外设通信接口将来自于上位机软件的程序数据接收后写入单片机内部指定的闪存区域,然后再跳转执行新写入的程序,最终就达到了程序更新的目的。 


在STM32微控制器上实现IAP程序之前首先要回顾一下STM32的内部闪存组织架构和其启动过程。STM32的内部闪存地址起始于0x8000000,一般情况下,程序文件就从此地址开始写入。此外STM32是基于Cortex-M3内核的微控制器,其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动。而这张“中断向量表”的起始地址是0x8000004,当中断来临,STM32的内部硬件机制亦会自动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。最后还需要知道关键的一点,通过修改STM32工程的链接脚本可以修改程序文件写入闪存的起始地址。 


在STM32微控制器上实现IAP方案,除了常规的串口接收数据以及闪存数据写入等常规操作外,还需注意STM32的启动过程和中断响应方式。


下图显示了STM32常规的运行流程:



 

图解读如下: 

1、 STM32复位后,会从地址为0x8000004处取出复位中断向量的地址,并跳转执行复位中断服务程序。

2、 复位中断服务程序执行的最终结果是跳转至C程序的main函数,而main函数应该是一个死循环,是一个永不返回的函数。 

3、 在main函数执行的过程中,发生了一个中断请求,此时STM32的硬件机制会将PC指针强制指回中断向量表处。 

4、 根据中断源进入相应的中断服务程序。 

5、 中断服务程序执行完毕后,程序再度返回至main函数中执行。 


若在STM32中加入了IAP程序: 

1、 STM32复位后,从地址为0x8000004处取出复位中断向量的地址,并跳转执行复位中断服务程序,随后跳转至IAP程序的main函数。


2、 执行完IAP过程后(STM32内部多出了新写入的程序,地址始于0x8000004+N+M)跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main函数。新程序的main函数应该也具有永不返回的特性。同时应该注意在STM32的内部存储空间在不同的位置上出现了2个中断向量表。 


3、 在新程序main函数执行的过程中,一个中断请求来临,PC指针仍会回转至地址为0x8000004中断向量表处,而并不是新程序的中断向量表,注意到这是由STM32的硬件机制决定的。 


4、 根据中断源跳转至对应的中断服务,注意此时是跳转至了新程序的中断服务程序中。 


5、 中断服务执行完毕后,返回main函数。 


二、hex文件与bin文件区别

Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量。Intel HEX文件经常被用于将程序或数据传输存储到ROM、EPROM,大多数编程器和模拟器使用Intel HEX文件。


很多编译器的支持生成HEX格式的烧录文件,尤其是Keil c。但是编程器能够下载的往往是BIN格式,因此HEX转BIN是每个编程器都必须支持的功能。HEX格式文件以行为单位,每行由“:”(0x3a)开始,以回车键结束(0x0d,0x0a)。行内的数据都是由两个字符表示一个16进制字节,比如”01”就表示数0x01;”0a”,就表示0x0a。对于16位的地址,则高位在前低位在后,比如地址0x010a,在HEX格式文件中就表示为字符串”010a”。


hex和bin文件格式

Hex文件,这里指的是Intel标准的十六进制文件,也就是机器代码的十六进制形式,并且是用一定文件格式的ASCII码来表示。具体格式介绍如下: Intel hex 文件常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。  hex和bin文件格式Hex文件,这里指的是Intel标准的十六进制文件,也就是机器代码的十六进制形式,并且是用一定文件格式的ASCII码来表示。具体格式介绍如下: Intel hex 文件常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。 


三、使用Keil软件完成hex文件转bin文件


 

选项框里的代码:


C:app_setupfor_KEILARMARMCCbinfromelf.exe --bin -o ./OBJECT/STM32_MD.bin ./OBJECT/STM32_MD.axf


解析如下:


C:app_setupfor_KEILARMARMCCbinfromelf.exe:是keil软件安装目录下的一个工具,用于生成bin


--bin -o ./OBJECT/STM32_MD.bin :指定生成bin文件的目录和名称


./OBJECT/STM32_MD.axf  :指定输入的文件. 生成hex文件需要axf文件


新工程的编译指令:


C:Keil_v5ARMARMCCbinfromelf.exe  --bin -o ./obj/STM32HD.bin ./obj/STM32HD.axf

 

将该文件下载到STM32内置FLASH,复位开发板,即可启动程序。


四、 使用win hex软件将bin文件搞成数组

 

生成数组之后,可以直接将数组编译到程序里,然后使用STM32内置FLASH编程代码,将该程序烧写到内置FLASH里,再复位开发板即可运行新的程序。


五、 Keil编译程序大小计算

 

Program Size: Code=x RO-data=x RW-data=x ZI-data=x 的含义


Code(代码): 程序所占用的FLASH大小,存储在FLASH.

     2. RO-data(只读的数据): Read-only-data,程序定义的常量,如const型,存储在FLASH中。


     3. RW-data(有初始值要求的、可读可写的数据):


     4. Read-write-data,已经被初始化的变量,存储在FLASH中。初始化时RW-data从flash拷贝到SRAM。


     5.  ZI-data:Zero-Init-data,未被初始化的可读写变量,存储在SRAM中。ZI-data不会被算做代码里因为不会被初始化。


ROM(Flash) size = Code + RO-data + RW-data;


RAM size = RW-data + ZI-data


简单的说就是在烧写的时候是FLASH中的被占用的空间为:Code+RO Data+RW Data


程序运行的时候,芯片内部RAM使用的空间为: RW Data + ZI Data


六、工程编译信息与堆栈信息查看

对于没有OS的程序,堆栈大小是在 startup.s 里设置的:  Stack_Size      EQU     0x00000800 


对于使用用 uCos 的系统,OS自带任务的堆栈,在 os_cfg.h 里定义:


/* ——————— TASK STACK SIZE ———————- */ 

#define OS_TASK_TMR_STK_SIZE    128    /* Timer      task stack size (# of OS_STK wide entries)        */

#define OS_TASK_STAT_STK_SIZE   128    /* Statistics task stack size (# of OS_STK wide entries)        */ 

#define OS_TASK_IDLE_STK_SIZE   128    /* Idle       task stack size (# of OS_STK wide entries)        */  

用户程序的任务堆栈,在 app_cfg.h 里定义:


#define  APP_TASK_MANAGER_STK_SIZE           512 

#define  APP_TASK_GSM_STK_SIZE                        512 

#define  APP_TASK_OBD_STK_SIZE                         512 

#define  OS_PROBE_TASK_STK_SIZE                       128  

 总结:


1, 合理设置堆栈很重要 


2, 多种方法结合,相互核对、校验 


3, 尽量避免大数组,如果一定要用,尽量定义为 全局变量,使其不占用堆栈空间, 如果函数有重入可能性,则要注意保护。


七、实现STM32在线升级程序

 7.1 升级的思路与步骤

1. 首先得完成STM32内置FLASH编程操作


2. 将(升级的程序)新的程序编译生成bin文件(编译之前需要在Keil软件里设置FLASH的起始位置)


3. 创建一个专门用于升级的boot程序(IAP Bootloader)


4. 使用网络、串口、SD卡等方式接收到bin文件,再将bin文件烧写到STM32内置FLASH里


5. 设置主堆栈指针


6. 将用户代码区第二个字(第4个字节)为程序开始地址(强制转为函数指针)


7. 执行函数,进行程序跳转


7.2 待升级的程序FLASH起始设置

Bootloader的程序大小先固定为: 20KB,最好是越小越好,可以预留更加多的空间给APP程序使用。


20KB----->20480Byte-----> 0x5000


STM32内置FLASH闪存的起始地址是: 0x08000000 ,大小是512KB。


现在将内置FLASH闪存前20KB的空间留给Bootloader程序使用,后面剩下的空间就给APP程序使用。


APP程序的起始位置就可以设置为:  0x08000000+ 0x5000=0x08005000


剩余的大小就是:  512KB-20KB=492KB------>503808Byte-------->0x7B000


设置FLASH的起始位置(APP主程序):

中断向量表偏移量设置

设置编译bin文件

 


7.3 Bootloader的程序设置

//设置写入的地址,必须偶数,因为数据读写都是按照2个字节进行

#define FLASH_APP_ADDR 0x08005000  //应用程序存放到FLASH中的起始地址

 

int main()

{   

  printf("UART1 OK.....n");

printf("进入IAP Bootloader程序!n");

  while(1)

  {

  key=KEY_Scanf();

      if(key==1) //KEY1按下,写入STM32 FLASH

      {

        printf("正在更新IAP程序...............n");

        iap_write_appbin(FLASH_APP_ADDR,(u8*)app_bin_data,sizeof(app_bin_data));//烧写新的程序到内置FLASH

printf("程序更新成功....n");

        iap_load_app(FLASH_APP_ADDR);//执行FLASH APP代码

      }

  }

}

 

/*

函数功能:跳转到应用程序段

appxaddr:用户代码起始地址.

*/

typedef  void (*iap_function)(void); //定义一个函数类型的参数.   

void IAP_LoadApp(u32 app_addr)

{

  //给函数指针赋值合法地址

  jump2app=(iap_function)*(vu32*)(app_addr+4);//用户代码区第二个字为程序开始地址(复位地址)

  __set_MSP(*(vu32*)app_addr);  //设置主堆栈指针

  jump2app();      //跳转到APP.

}

关键字:STM32F103  IAP  在线升级 引用地址:STM32F103实现IAP在线升级应用程序

上一篇:基于STM32设计的实时心率检测仪
下一篇:基于STM32移植UCGUI图形界面框架(3.9.0源码版本)

推荐阅读最新更新时间:2024-11-13 12:11

STM32F103RC 一上电重复重启
现象:烧了有看门狗的程序,就正常;反之,一直在重启。 原因:之前用STM32 ST-LINK Utility 烧写程序时,Options Bytes设置错误。正确的是默认选上WDG_SW、nRST_STOP、nRST_STDBY。不勾选WDG_SW,代表选择硬件看门狗,因程序中没有喂狗,故一直重启
[单片机]
STM32F103做从机SPI通信SPI3中断异常
在做AM335D板子与STM32F103使用SPI通信时,需要用到STM32的从机模式,所以特别对于ST的从机模式进行了研究,由于硬件上使用的是STM32F103的SPI3,所以过程中遇到了一点麻烦,这里记录一下过程,以备查阅: 使用SPI3通信时,从机时钟产生不了中断,经过查阅资料,是因为spi3的nss口与JTAG有共用引脚,所以配置错误会导致SPI3无法使用。需要注意以下两点就可以了: 1.开启GPIO时钟的同时,开启AFIO时钟,如下: RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE ); 2.关闭JTAG功能,
[单片机]
STM32F103ZET定时器TIM1输出六路带死区互补PWM波形
使用默认引脚输出6路PWM,#define FullRemap_TIM1则重映射 PIN脚; 遗留问题:调用TIM_CCxNCmd(TIM1, TIM_Channel_X, TIM_CCx_Enable);导致互补PWM无输出。 TIM_CCxCmd(TIM1, TIM_Channel_X, TIM_CCx);确可以正常开关PWM输出; 遇到问题:PA8、10、PB13、14、15均有输出,PA9无输出; 问题解决:虽然没初始化UART1模块,但打开RCC_APB2Periph_USART1时钟导致; void Timer1_Init(void) { TIM_OCInitTypeDef TIM_OCIni
[单片机]
STM32存储器 — <3> STM32实现IAP
在对STM32存储器结构及相关知识了解后,我们就可以进行IAP的设计了。 在上一篇笔记中,进行了一个简单的IAP程序结构,以及和User App程序的相互联系的系统设计。 本篇对IAP实现的细节进行了较为详细的论述,包括源码结构的设计;我们从上位机(PC C#)和下位机(MCU C)共同描述IAP功能的实现过程。 1 STM32的IAP实现平台 IAP功能的实现需要两个方面(上位机和STM32上的IAP程序)的密切合作。因此,我们除了需要知道STM32芯片上的IAP程序结构,我们还需要了解上位机的程序结构,这样才能使上位机和STM32很好的相互工作。 下位机(指的是STM32构成的单片机系统): 本下位机系统使用C语言进行
[单片机]
stm32f103c8t6引脚图及功能
STM32F103C8T6是一款基于ARM Cortex-M 内核STM32系列的32位的微控制器,程序存储器容量是64KB,需要电压2V~3.6V,工作温度为-40°C ~ 85°C。 引脚图与功能 STM32F103C8T6引脚图 STM32F103C8T6功能表
[单片机]
<font color='red'>stm32f103</font>c8t6引脚图及功能
ATMEL系列MCU在线升级bootloader固件源码及操作过程
前几天出差,无意间问了大家是否需要bootloader实现在线升级,需要的还是比较多,在这里我就把我实现过程与大家分享,并我的bootloader固件给大家参考。我在mage和xmage上都实现过,不过我使用的RS485,所以固件里面也是RS485的,大家使用RS232的话,把RS485的控制去掉就可以了,RS232实现起来比RS485简单,因为RS232是全双工的。 我开发使用的环境是Atmel Studio 6.2,这个看大家习惯,环境主要就是实现可执行文件。bootloader固件都是C语言 实现,相信大家都能看明白,这里就直接上传bootloader固件源码。bootloader固件是需要仿真器等设备下载到设备中的。
[单片机]
ATMEL系列MCU<font color='red'>在线升级</font>bootloader固件源码及操作过程
STM32F103VCT6+W5500 UDP通信成功
STM32F103VCT6+W5500 UDP通信成功,实现电脑与W5500模块的双机UDP通信。 这里需要注意的是:UDP设置了目标端口后,要用这个设置的目标端口连接才行。否则通信不上。 如UDP设置了IP:192.168.1.128 8000端口,目标IP192.168.1.105(这里是我的电脑的IP)端口为:8000, 则网络助手连接时,协议类型:UDP,本机IP为:192.168.1.105,本地端口为:8000,然后打开。 如果打开成功后,还需要设置一下:目标主机IP:这里为W5500模块的,192.168.1.128 8000端口。 默认有可能为本机的,这样通信也是可行的,不过与实验无关。。 通信效果如下:
[单片机]
STM32f103之外部中断
一、背景 有个需求,IO口检测上升沿,然后做相应的动作。在此记录STM32F103的外部中断结构及配置方法, 以备下次快速上手使用。 有许多不太明白,又是老司机(:-D)帮忙,真的是站在别人的肩膀上会让你看的更远,走的更快, 感谢老司机。 二、正文 STM32f103有68个可屏蔽中断。(但是,真正能用的其实远没有这么多,原因下面会详述。) 有16个可编程的优先等级,优先等级的概念可详见我的另外一篇博客《STM32 之 NVIC(中断向量、 优先级)简述》,链接: http://www.cnblogs.com/ChYQ/p/5859974.html ,接着看中断向量表,    如下图:
[单片机]
<font color='red'>STM32f103</font>之外部中断
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved