• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

单片机OTA升级流程和bootload软件框架

武飞扬头像
_LiuChunJiang刘春江
帮助1

为什么要进行OTA升级

OTA 英文全称是Over-the-Air Technology,即空间下载技术,是通过移动通信(GSM或CDMA)的空中接口对SIM卡数据及应用进行远程管理的技术。在我们常用的电子设备中,通过会进行软件优化或者固件升级,这个时候我们的产品可能已经在全国各地,不可能亲自去进行固件升级,所以就需要利用OTA技术进行升级。

OTA升级的流程

这里的升级流程框架我是按照我之前的一个项目写的,该项目中所用单片机的FLASH大小为128K,其中包含我的FLASH分配,和APP和BOOTLOAD对于升级流程实现
学新通

bootload软件框架

这里主要是bootload代码的实现框架和一些具体的细节问题,可以和下面的后面的代码部分相结合阅读。
学新通

bootload软件源码(针对接收HEX文件)

这里我就只放一下IAP的头文件和源文件
#ifndef _IAP_H_
#define _IAP_H_
#include "stm32f10x.h"

#define FlashBaseAddress              0x08000000
#define ApplicationAddress    			0x8003000
#define ApplicationSize							0xD000						// 52KB
#define ApplicationBackup						(ApplicationAddress   ApplicationSize)
typedef  void (*pFunction)(void);

#define UPGRADE_FLAG_START	    				((uint16_t)0x1010)
#define UPGRADE_FLAG_RECV_COMPLETE				((uint16_t)0x2020)
#define UPGRADE_FLAG_END						((uint16_t)0x3030)	// 注意如果没有读到0x600的值也视为已经完成

extern volatile uint8_t updateFinished;
extern uint32_t maxProgramAdd;

void jumpToApplication(void);//跳转到APP程序

uint8_t IsUpgradeStarted(void);//开始Bootload升级标记
uint8_t IsUpgradeRecEnd(void);//接收Bootload升级标记
uint8_t IsUpgradeComplete(void);Bootload升级完成标记

uint8_t EraseFlash(uint32_t baseAddress);//擦除FLASH
uint8_t WriteUpgradeFlag(uint16_t flagValue);//写半字
uint8_t WriteMaxProgramAddress(uint32_t address);//写OTA接收程序最大地址
uint8_t readMaxProgramAddress(uint32_t* addressValue);//读OTA接收程序最大地址
static uint8_t MassCopy(void);//根据程序大小,从Application备份区拷贝到Application区
uint8_t copyApplication(void);//擦除Application区,从备份区拷贝新程序到Application区

uint8_t HEX_File_Parsing(uint8_t * data,uint8_t len);//Hex文件解析

#endif
#include "iap.h"
#include "Flash.h"
#include "EEPROM.h"
#include "stdio.h"
pFunction Jump_To_Application;
uint32_t JumpAddress;
uint32_t maxProgramAdd=0;
volatile uint8_t updateFinished = 0;
void jumpToApplication(void)//跳转到APP程序
{
//	__set_PRIMASK(1);
//	__DSB();
//    __ISB();
//    SysTick->CTRL = 0;
	if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)       
	{
			JumpAddress = *(__IO uint32_t*) (ApplicationAddress   4);                 
			Jump_To_Application = (pFunction) JumpAddress;                             
			__set_MSP(*(__IO uint32_t*) ApplicationAddress);                           
			Jump_To_Application();                                                                 
	}
}

uint8_t IsUpgradeStarted(void)
{
	uint16_t FlashData;
	uint8_t FreshStatus=readSysU16(0x600,&FlashData);
	
	if(FreshStatus==0 && FlashData == UPGRADE_FLAG_START)
	{
		return 0;
	}
	return 1;	
}

uint8_t IsUpgradeRecEnd(void)
{
	uint16_t FlashData;
	uint8_t FreshStatus=readSysU16(0x600,&FlashData);
	FreshStatus |= readMaxProgramAddress(&maxProgramAdd);
	if(FreshStatus==0 && FlashData == UPGRADE_FLAG_RECV_COMPLETE)
	{
		return 0;
	}
	return 1;
}
uint8_t IsUpgradeComplete(void)
{
	uint16_t FlashData;
	uint8_t FreshStatus=readSysU16(0x600,&FlashData);
	
	if(FreshStatus==0 && FlashData == UPGRADE_FLAG_END)
	{
		printf("\r\n升级成功了!");
		return 0;
	}
	return 1;	
}

/**
  * @brief  擦除ApplicationSize大小的Flash
  * @param  None
  * @retval None
  */
uint8_t EraseFlash(uint32_t baseAddress) 
{
	uint8_t flashStatus = 0;
	for (uint32_t i = 0; i < ApplicationSize; i =PAGE_SIZE)
	{
		flashStatus = FLASH_ErasePage(baseAddress   i);
		if (flashStatus != FLASH_COMPLETE) 
			return flashStatus;
	}
	return 0;
}

/**
  * @brief  Writes/upadtes variable data in EEPROM.
  * @param  flagValue: new value
  * @retval Success or error status:
  *           - 0: Success
  *           - PAGE_FULL: if valid page is full
  *           - NO_VALID_PAGE: if no valid page was found
  *           - Flash error code: on write Flash error
  */
uint8_t WriteUpgradeFlag(uint16_t flagValue) 
{
	uint8_t error = writeSysU16(0x0600, flagValue);
	return error == FLASH_COMPLETE ? 0 : error;
}
/**
  * @brief  Writes/upadtes variable data in EEPROM.
  * @param  flagValue: new value
  * @retval Success or error status:
  *           - 0: Success
  *           - PAGE_FULL: if valid page is full
  *           - NO_VALID_PAGE: if no valid page was found
  *           - Flash error code: on write Flash error
  */
uint8_t WriteMaxProgramAddress(uint32_t address) 
{
	uint8_t error = writeSysU16(0x0601, (u16)(address >> 16));
	if (error == FLASH_COMPLETE) error = writeSysU16(0x0602, ((u16)(address & 0xFF)));
	return error == FLASH_COMPLETE ? 0 : error;
}
/**
  * @brief  Returns the last stored max programAddress
  * @param  addressValue: Global variable contains the read variable value
  * @retval Success or error status:
  *           - 0: if variable was found
  *           - 1: if the variable was not found
  *           - NO_VALID_PAGE: if no valid page was found.
  */
uint8_t readMaxProgramAddress(uint32_t* addressValue) 
{
	u16 hb,lb;
	u8 flashStatus = readSysU16(0x0601, &hb) || readSysU16(0x0602, &lb);
	*addressValue = (((u32)hb) << 16) | lb;
	if (flashStatus == 0 && *addressValue > ApplicationAddress && *addressValue < ApplicationAddress   ApplicationSize) {
		return 0;
	}
	return 1;
}
/**
	* @brief  根据程序大小,从Application备份区拷贝到Application区
  * @param  None
  * @retval None
  */
static uint8_t MassCopy(void) 
{
	uint8_t flashStatus = 0;
	for (uint32_t i = 0; i <= (maxProgramAdd - ApplicationAddress); i = 2)
	{
		flashStatus = FLASH_ProgramHalfWord(ApplicationAddress   i, readFlashU16(ApplicationBackup   i));
		if (flashStatus != FLASH_COMPLETE) return flashStatus;
	}
	return 0;
}
/**
	* @brief  擦除Application区,从备份区拷贝新程序到Application区
  * @param  None
  * @retval None
  */
uint8_t copyApplication(void) 
{
	uint8_t Error = 0; 
	
	printf("\r\n 开始擦除APP!");
	Error = EraseFlash(ApplicationAddress);
	if(Error)
		return (Error); 
	
	Error = MassCopy();
	if(Error)
		return (Error);
	
	Error = WriteUpgradeFlag(UPGRADE_FLAG_END);  // 擦除bootloader标志
	updateFinished = 1;
	return Error;
}

//Hex文件解析
uint8_t HEX_File_Parsing(uint8_t * data,uint8_t len)
{
	/*数据格式::|LL|aaaa|TT|data|CC|
	** :冒号 HEX文件每一行首字节都是由冒号开头
	** LL:数据域长度
	** AAAA:地址域
	** TT:类型域 00数据记录 
				  01文件结束记录 
				  02扩展段地址记录
				  03开始段地址记录
				  04扩展线性地址记录 
				  05开始线性地址记录
	** data:数据域
	** CC:校验
	*/
	uint8_t i;
	uint8_t crctotal=0;
	uint8_t flashStatus=0;
	uint16_t Flashdata=0;
	
	if(data[0]!=0x3A)//开头是不冒号
	{
		printf("\r\n error1");
		return 1;
	}
		
	
	for(uint8_t i=1;i<len-1;i  )//hex文件校验和
	{
		crctotal =data[i];
	}
	if(crctotal!=(uint8_t)(0x100-data[len-1]))//crc校验不通过
	{
		printf("\r\n error2");
		return 1;
	}
		
	if(data[4]==0x04)//04扩展线性地址记录
	{
		uint32_t Freshaddress=(data[5]<<8) data[6];
		if(Freshaddress!=0x0800)
			return 1;
	}
	else if (data[4]==0x00)//00数据记录
	{
		uint32_t Freshaddress=FlashBaseAddress   ((data[2]<<8) data[3]);//这里应该是APP的地址
		
		maxProgramAdd=Freshaddress data[1];//最大地址等于 目前最新地址 该行数据长度
		
		if(maxProgramAdd>=ApplicationBackup && maxProgramAdd<= ApplicationAddress)//如果地址越界
		{
			printf("\r\n error3");
			return 1;
		}
					
		for(i=0;i<data[1];i =2)
		{
			uint32_t WriteAdree=Freshaddress i;
	
			Flashdata=data[6 i]<<8;//半字高8位
			Flashdata =data[5 i];//半字低8位
//			printf("\r\n要写的数据是%x",Flashdata);
//			printf("  要写的地址是%x",WriteAdree);
//			printf("\r\n要写的地址是%x",ApplicationBackup   (WriteAdree - ApplicationAddress));
			flashStatus = FLASH_ProgramHalfWord(ApplicationBackup   (WriteAdree - ApplicationAddress),Flashdata);
		
			if (flashStatus != FLASH_COMPLETE)
			{
				printf("\r\n error4 %d",flashStatus);
				return flashStatus;
			}			
		}
	}

	return 0;
}

如果看完有帮助的可以点赞收藏一下,还有不懂的可以直接联系我哦~

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgabjei
系列文章
更多 icon
同类精品
更多 icon
继续加载