IAP_2_IAP执行流程、实现思路

本文详细介绍了IAP(在线编程)程序更新的过程,包括程序执行流程、bin文件的应用及存储发送方式,并提供了一种基于STM32的IAP实现方案。

1、IAP的程序执行流程

被更新的单片机要有两个程序,一个是“Bootloader”,一个是“APP”。

首先执行“Bootloader”,用来决定是否更新APP,接收串口数据,然后跳转到真正想运行的“APP”,具体运行流程图如下。

  1. 从栈顶地址开始,从“中断向量表1”找到复位中断,处理复位中断函数;
  2. 执行IAP的main函数;
  3. 跳转到“中断向量表2”,找到复位中断,处理复位中断函数;
  4. 执行APP的main函数;

在这里插入图片描述

2、关于bin文件

2.1、为什么要用bin文件

一般情况下,我们生成的是hex文件,hex文件是以ASCII文本形式保存编译后的二进制文件信息,使用各种烧录软件实际上就是把这些工具把hex文件转换成二进制的bin文件,烧录到单片机当中。

在IAP更新程序的时候,我们就相当于这些烧录软件,直接使用bin文件,跳过了hex转成bin文件的这一步。

hex文件包含了地址和校验的信息,利用hex文件加上烧录工具,会更加安全。

2.2、bin文件的存储和发送方式

可以用电脑的串口发送软件(有某些协议的上位机),也可以用单片机的串口发送。

如果用电脑来存储bin文件,无疑是非常简单的,不过发送bin文件的话,更新程序的时候就要带电脑,还要在电脑上进行操作,不太方便。

如果使用单片机的话,需要事先把bin文件存在Flash当中,或者SD卡当中,发送就通过串口。

3、IAP方案简介

用一个STM32F103做为存储和发送bin文件的地方,用的是正点原子的Mini板,有屏幕,方便显示信息,也有例程可以修改来用,就叫做“STM32_TX”。

另一个STM32F103就是需要被升级的了,不妨称为“STM32_RX”。

3.1、把bin文件存到STM32当中

把STM32外加的Flash或SD卡模拟成U盘,利用文件系统,当插入USB的时候,就相当于插入U盘,这时候把bin文件直接复制粘贴到U盘中就可以了。

需要用到的知识:读写外部Flash、读写SD卡、文件系统、USB等。

3.2、把bin文件发送出去

利用STM32串口,要考虑到分包、校验、重发机制。

分包的原因:一个简单的程序也往往是几十K字节的,一次性发送,接收端的SRAM没有那么大的缓存,所以需要将bin文件分成一个个数据包,比如1K大小。

校验:打算就先用CRC8校验。

重发:超时重发,出错重发,重发次数最大为10.

3.3、接收端的处理

每次发送1K字节,接收方接收1K字节,校验有误申请重发,校验无误之后写入自己的内部Flash。

当整个bin文件全部接收并写入完成之后,跳转到APP执行。

#ifndef _EEPROM_H_ #define _EEPROM_H_ #define SECTOR_SIZE 512 sfr ISP_DATA=0xe2; sfr ISP_ADDRH=0xe3; sfr ISP_ADDRL=0xe4; sfr ISP_CMD=0xe5; sfr ISP_TRIG=0xe6; sfr ISP_CONTR=0xe7; void Read_FixTime(unsigned int addr1,unsigned char Fixtime[][10]); void Save_FixedTime(unsigned int addr2,unsigned char Savetime[][10]); #endif#include <reg52.h> #include "EEPROM.h" #include "Delay.h" void IAP_Dsiable(void); static void IAP_Trigger(void); void IAP_EraseSector(unsigned int sector_addr); void IAP_data_w(unsigned char dat,unsigned int addr); void IAP_Dsiable(void) { ISP_CMD = 0x00; ISP_TRIG = 0x00; ISP_CONTR = 0x00; } static void IAP_Trigger(void) { ISP_TRIG = 0x46; ISP_TRIG = 0xB9; } void IAP_EraseSector(unsigned int sector_addr) { // 扇区地址应该是扇区的起始地址,必须是512字节对齐 unsigned int sector_start = sector_addr & 0xFE00; EA=0; ISP_CONTR = 0x81; // 使能IAP ISP_CMD = 0x03; // 擦除命令 ISP_ADDRL = sector_addr; ISP_ADDRH = sector_addr >> 8; IAP_Trigger(); // 触发擦除 IAP_Dsiable(); EA=1; } void IAP_data_w(unsigned char dat,unsigned int addr) { ISP_CONTR=0x81; ISP_CMD=0x02; ISP_ADDRL=addr; ISP_ADDRH=addr>>8; ISP_DATA=dat; IAP_Trigger(); IAP_Dsiable(); } //读取EEPORM时间 void Read_FixTime(unsigned int addr1,unsigned char Fixtime[][10]) { unsigned int i,j; EA=0; for(i=0;i < 12;i++) { for(j=0;j <10 ;j++) { ISP_CONTR = 0x81; ISP_CMD = 0x01; ISP_ADDRL = addr1; ISP_ADDRH = addr1 >> 8; IAP_Trigger(); Fixtime[i][j] = ISP_DATA; IAP_Dsiable(); if(Fixtime[i][j] == '\0') { j++; break; } addr1++; } if(j<10) { Fixtime[i][j]='\0';} } EA=1; } //存储EEPORM时间 void Save_FixedTime(unsigned int addr2,unsigned char Savetime[][10]) { unsigned int i,j; IAP_EraseSector(addr2); EA=0; for(i=0;i < 12 ;i++) { for(j=0;j < 10 && Savetime[i][j]!= '\0';j++) { IAP_data_w(Savetime[i][j],addr2); addr2 ++; } if (j < 10) { ISP_CONTR = 0x81; ISP_CMD = 0x02; ISP_ADDRL = addr2 ; ISP_ADDRH = addr2 >> 8; ISP_DATA = '\0'; IAP_Trigger(); IAP_Dsiable(); addr2++; } } EA=1; }在不改变原变量情况下优化该代码
07-10
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值