STM32 IAP固件升级 认知篇

1、环境

stm32f103zet6
MDK 5.28

2、芯片

2.1 Flash大小

我用的是stm32f103zet6属于高容量产品,flash大小512KB,每个Page2KB大小,一共256页(这个可以根据自己的芯片去ST官网查询文档),如下图所示:
在这里插入图片描述
我们这边对这个flash再做个划分(需要根据固件大小和bootloader程序大小划分,bootloader程序出厂就不会改变了,所以要预留考虑好分区是否放的下程序):
在这里插入图片描述

  • bootloader大小是前128KB,从0x08000000~0x0801FFFF
  • APP程序区是192KB,从0x08010000~0x0804FFFF
  • UpdateFirmware区是192KB,从0x08050000~0x0807FFFF

UpdateFirmware

这个区域我是把这个区域第一页用来存放是否升级,文件大小等信息等。
第二页开始也才开始存放真正意义上的固件。

内部flash详细分区

3、IAP升级流程

bootloader程序设计流程

在这里插入图片描述

APP程序设计流程

在这里插入图片描述

4、Bootloader程序设计

要实现IAP升级,需要先实现几个功能擦写内部flash、计算校验和、程序跳转和软件复位系统的功能。

擦除/写flash

flash解锁和上锁

ST对内部flash做了保护如果要擦写需要先解锁,使用结束后我们也会锁上。
这里使用的是HAL库提供的函数接口实现的:

  • flash解锁
HAL_StatusTypeDef HAL_FLASH_Unlock(void)    //解锁
  • flash上锁
HAL_StatusTypeDef HAL_FLASH_Lock(void)     //上锁
  • flash擦除
/**
  * @brief  Erase the specified FLASH memory sector
  * @param  Sector FLASH sector to erase
  *         The value of this parameter depend on device used within the same series      
  * @param  VoltageRange The device voltage range which defines the erase parallelism.  
  *          This parameter can be one of the following values:
  *            @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V, 
  *                                  the operation will be done by byte (8-bit) 
  *            @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V,
  *                                  the operation will be done by half word (16-bit)
  *            @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V,
  *                                  the operation will be done by word (32-bit)
  *            @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp, 
  *                                  the operation will be done by double word (64-bit)
  * 
  * @retval None
  */
void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
  • flash写入
/**
  * @brief  Program byte, halfword, word or double word at a specified address
  * @param  TypeProgram  Indicate the way to program at a specified address.
  *                           This parameter can be a value of @ref FLASH_Type_Program
  * @param  Address  specifies the address to be programmed.
  * @param  Data specifies the data to be programmed
  * 
  * @retval HAL_StatusTypeDef HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
  • 等待flash操作完成
/**
  * @brief  Wait for a FLASH operation to complete.
  * @param  Timeout maximum flash operationtimeout
  * @retval HAL Status
  */
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)

更新APP区代码如下

HAL_FLASH_Unlock();  

// 擦除应用程序区
for(uint8_t i=0;i<APP_SECTOR_TOTAL_NUM;i++)
{
	FLASH_WaitForLastOperation(0xffff);
	FLASH_Erase_Sector(APP_FIRST_SECTOR_NUM+i,FLASH_VOLTAGE_RANGE_2);//APP_FIRST_SECTOR_NUM定义成APP开始地址
}

for(uint32_t i=0;i<firmSize;i++)
{
	dat = *(__IO uint16_t*)(FIRMWARE_START_FLASH_ADDR + i*2);//FIRMWARE_START_FLASH_ADDR 定义固件区起始地址
	HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,APP_START_FLASH_ADDR + i*2,dat);//将新固件写入APP区
} 
 
// 擦除固件升级信息 
FLASH_WaitForLastOperation(0xffff);
FLASH_Erase_Sector(UPDATE_PLAN_SECTOR_NUM,FLASH_VOLTAGE_RANGE_2);//将升级计划擦除

// 擦除固件缓存区
for(uint8_t i=0;i<FIRMWARE_SECTOR_TOTAL_NUM;i++)
{
	FLASH_WaitForLastOperation(0xffff);
	FLASH_Erase_Sector(FIRMWARE_FIRST_SECTOR_NUM+i,FLASH_VOLTAGE_RANGE_2);
}
HAL_FLASH_Lock();//上锁  
FLASH_WaitForLastOperation(0xffff);//等待flash操作结束

校验

功能:确保固件在flash中是完全正确的
这个可以自己设计,和校验和CRC校验都可以。需要添加校验和到固件的末端或者头部。然后根据计算方法验证flash中的固件是否正确,与添加到固件中的校验和比对,若正确认为固件完整且正确。为了提高效率只有申请固件升级后才会对固件进行验证工作。

程序跳转

void Jump(uint32_t addr)
{ 
	__disable_irq() ; //关闭总中断
  /* Jump to user application */
  
	if (((*(volatile uint32_t*)addr) & 0x2FFE0000 ) == 0x20000000)
	{			
		JumpAddress = *((__IO uint32_t*) (addr + 4));
		Jump_To_Application = (pFunction) JumpAddress;
		/* Initialize user application's Stack Pointer */
		__set_MSP(*(__IO uint32_t*) addr);
		Jump_To_Application();
	}
}

从bootloader程序跳转到APP程序。

注:这里关闭了中断,所以跳转结束后,APP程序需要打中断否则会出现进不了中断的现象。

系统软复位

5、APP程序设计

flash起始位置的修改

在这里插入图片描述

中断向量表偏移

SCB->VTOR = FLASH_BASE | 0x20000; /* Vector Table Relocation in Internal FLASH */

注:
Q:为什么只有APP程序中需要设置中断向量偏移量?
A:bootloader一般写在FLASH的头部,开机直接启动,所以使用默认的向量偏移地址就可以。
App程序一般写在BootLoader的后面或者外部FLASH中,程序头部不在0x8000000,其中断向量表基地址也不在0x8000000。
Q:HAL库的

下载程序设计(也可以设计在Bootloader中)

Ymodem协议可以看另外一篇文章这里不过多介绍了。

flash的写入

在这里插入图片描述

与Bootloader中的flash擦写一致。
完成固件接收之后还需要将升级计划更新,以便于下次启动时更新新的的固件。

参考资料

STM32中SCB->VTOR的理解

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柒妖71

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值