STM32固件升级

升级方式

启动方式

在STM32F10xxx里有三种启动方式:

BOOT0BOOT1启动模式说明
0X用户闪存存储器用户闪存存储器,也就是flash启动
10系统存储器系统存储器自动,用于串口下载
11SRAM启动SRAM启动,用于再SRAM中调试代码

系统存储器是厂家固化好的一片存储区,地址为0x1FFFF000,具有串口升级的功能,并把程序引导至用户闪存存储区。

用户闪存存储区是保存用户代码及数据的存储区吗,地址为0x08000000,可以放置用户的bootloader,用于IAP。

注意不同的系列的STM32固话的系统存储区代码是不同的,STM32F1XXX系列只支持USART1。

ISP升级

升级时先将boot0置1,电脑使用ISP下载工具与MCU通过串口连接后升级。

IAP升级

可以实现远程OTA,在0x08000000处放置用户bootloader,在后面地址放置用户APP及升级包存储区,通过APP程序来升级。下面介绍IAP的升级方法。

Bootloader程序说明

功能

bootloader的主要功能是判断有无升级包需要升级,需要升级则搬移程序、校验升级包。然后跳转到APP程序

代码

#define CODE_ADDRESS_START       0x08001800
#define UPDATE_ADDRESS_START     0x08013800         //第78K
#define UPDATE_CRC_ADDRESS_START 0x0801F800         //第126K
#define DEFAULT_VALUE            0xFFFFFFFF
#define VERIFICATION             0x55555555
#define PACKAGE_BIG              48*1024
#define CLOSE_ALL_INT()  __set_PRIMASK(1)

typedef void (*Iapfun)(void);
static Iapfun jump2app;

FLASH_EraseInitTypeDef Flash;
uint32_t Flash_error;

int main(void)
{
  HAL_Init();
  SystemClock_Config();
	//读出flash中参数
  update_size = *(__IO uint32_t *)(UPDATE_CRC_ADDRESS_START);
  update_crc  = *(__IO uint32_t *)(UPDATE_CRC_ADDRESS_START+4);
  if(update_size < PACKAGE_BIG){
    update_data = *(__IO uint32_t *)(UPDATE_ADDRESS_START + update_size -4);
  }
  //有升级数据包,搬移程序
  if((update_size!= DEFAULT_VALUE)&&(update_size <= PACKAGE_BIG)&&(update_size%4 ==0)&&\
     (update_crc!= DEFAULT_VALUE)&&(update_data == VERIFICATION)){
    //搬移前
    __HAL_RCC_CRC_CLK_ENABLE();
    CRC->CR = CRC_CR_RESET;
    HAL_FLASH_Unlock();	 
    Flash.NbPages = PACKAGE_BIG/FLASH_PAGE_SIZE;
    Flash.PageAddress = CODE_ADDRESS_START;
    Flash.TypeErase = FLASH_TYPEERASE_PAGES;
    HAL_FLASHEx_Erase(&Flash,&Flash_error);
    //搬移
    for(i = 0; i < update_size/4; i++){
      update_data = *(__IO uint32_t *)(UPDATE_ADDRESS_START+4*i);
      HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD ,CODE_ADDRESS_START+4*i, update_data);
      U32_Exchange(&update_data);
      CRC->DR= update_data;
    }
    //搬移后
    HAL_FLASH_Lock();
      //升级成功
    if(update_crc == CRC->DR){
      HAL_FLASH_Unlock();	 
      Flash.NbPages = 1;
      Flash.PageAddress = UPDATE_CRC_ADDRESS_START;
      Flash.TypeErase = FLASH_TYPEERASE_PAGES;
      HAL_FLASHEx_Erase(&Flash,&Flash_error);
    }
      //升级失败
    else{
      NVIC_SystemReset();
    }
  }
  //跳转到APP程序
  jump2app=(Iapfun)*(volatile uint32_t *)(CODE_ADDRESS_START+4);	
  __set_MSP(*(volatile uint32_t *)CODE_ADDRESS_START);
  CLOSE_ALL_INT();
  jump2app();
}

__set_MSP(*(volatile uint32_t *)CODE_ADDRESS_START):STM32规定程序起始必须为栈顶指针。

jump2app=(Iapfun)*(volatile uint32_t *)(CODE_ADDRESS_START+4):用户程序为地址地址+4 且为中断向量表。

APP程序说明

功能

APP程序需要完成1.bin文件的接收、存储、校验。2通知bootloader升级包已准备好(写入flash特定位置特定参数)

代码

/**
  * @功能: 
  * @变量: 
  */
uint8_t Write_Update_Package(uint8_t number,uint16_t len, uint32_t *data)
{
  uint16_t i;
  if((number ==0)||(len>1024)){
    return ERROR;
  }
  number--;
  //第一包 开启CRC
  if(number == 0){
    __HAL_RCC_CRC_CLK_ENABLE();
    CRC->CR = CRC_CR_RESET;
  }
  //保存数据 计算CRC
  HAL_FLASH_Unlock();
  for(i=0;i<len/4;i++){
    //最后一个数据是CRC数据
    if((number + 1 == OTA_para.total_package)&&(i == len/4-1)){
      U32_Exchange(data+i);
      if(data[i] == CRC->DR){
      //校验成功	
        uint32_t total_length = OTA_para.total_package*1024 + len - 1028;
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD ,UPDATE_CRC_ADDRESS_START ,total_length);
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD ,UPDATE_CRC_ADDRESS_START+4 ,data[i]);
        HAL_FLASH_Lock();
        return SUCCESS;
      }
    }
    //其余正常数据,写FLASH 计算CRC
    else{
      HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, UPDATE_ADDRESS_START + number*1024 + i*4, data[i]);
      U32_Exchange(data+i);
      CRC->DR= data[i];
    }
  }
  HAL_FLASH_Lock();
  return ERROR;
}

设置

  • keil的Options中的Target选项卡,中IROM1的Start改为APP的地址。
  • 如采用硬件库,则在system_stm32f1xx.c中 97行打开宏定义 #define USER_VECT_TAB_ADDRESS,并修改偏移#define VECT_TAB_OFFSET 0x00001800U。

BIN文件制作

生成

keil的Options中的User选项卡,在After Build/Rebuild中打钩,并填入 下面

fromelf --bin -o “$L@L.bin” “#L”

结构

数据结构为:数据(4*NBYTE)+验证码(4BYTE)+校验码(4BYTE)。

验证码用于判断BIN文件的有效性,防止升级成不相干的bin。

校验码用于判断BIN文件的完整性,防止BIN文件的损坏。

通过Hex Editor 可以对bin文件编辑。通过这里可以计算CRC-32/MPEG-2。

CRC32校验

​ STM32自带CRC硬件,可通过自身硬件快速进行CRC32校验。

校验格式:

CRC-32/MPEG-2:x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
宽度:32
多项式:04C11DB7
初始值:FFFFFFFF
结果亦或值:00000000
输入反转:false
输出反转:false

需要注意的是,一些常用的校验工具校验文件时,采用的是高端存储方式,STM32采用的是低端存储方式,在STM32采用硬件校验时,需要将每个32位数据的4个字节的顺序变换:

void U32_Exchange(uint32_t *data)
{
  uint32_t result=0;
	result |= (*data & 0xFF000000UL) >> 24;
	result |= (*data & 0x00FF0000UL) >> 8;
	result |= (*data & 0x0000FF00UL) << 8;
	result |= (*data & 0x000000FFUL) << 24;
  *data = result;
}

CRC32硬件使用

使用前打开时钟并RESET

__HAL_RCC_CRC_CLK_ENABLE();
CRC->CR = CRC_CR_RESET;

使用时直接写入

  U32_Exchange(data+i);
  CRC->DR= data[i];

校验后直接读取

  data[i] = CRC->DR;

STM32的CRC计算时会占用MCU的核心,所以程序无需等待,随写随读。

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值