STM32系列—Flash操作更新

内容分享1周前发布
0 6 0

STM32F103程序存储为Flash,支持在线读写以及擦除。Flash写的特性为:先要按照页擦除,擦除之后每个字节的数值为0xFF,然后才能对Flash进行写操作。读的特性倒是没有特殊的要求,可以直接读。

STM32的HAL库里面有Flash的写操作以及擦除操作的,这就为我们Firmware Update提供了便利。

STM32(HAL库)BootLoader实现(BootLoader跳转到Application)

STM32(HAL库)BootLoader实现2(Application跳转到BootLoader)

上面两篇文章详细叙述了如何为了Firmware升级建立BootLoader(如果没有思路的,可以看看我的这两篇文章)。BootLoader和Application的相互可以通过上述方式实现,那么具体的Firmware的操作(即Flash的擦除与写操作)是怎么弄的呢?

第一是Flash的擦除,见下面代码:

#define APP_FLASH_ADDR_START_INDEX  (0x8008000)
#define APP_FLASH_ADDR_END_INDEX    (0x8080000)
#define FLASH_PAGE_SIZE_USER        (0x800)

USBD_StatusTypeDef USB_Erese_Flash()  //USB 接口调用的擦除Flash,返回值为USB状态
{
	FLASH_EraseInitTypeDef pEraseInit; // HAL 库定义的擦除句柄
	uint32_t PageError = 0;
	pEraseInit.NbPages = (APP_FLASH_ADDR_END_INDEX-APP_FLASH_ADDR_START_INDEX)/FLASH_PAGE_SIZE_USER;//定义要擦除的页数,每页为2K Bytes
	pEraseInit.PageAddress = APP_FLASH_ADDR_START_INDEX; //定义开始地址
	pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;//定义擦除类型为页擦除
	if(HAL_FLASHEx_Erase(&pEraseInit, &PageError)!=HAL_OK) //直接调用Flash 擦除库函数
	{
		return USBD_FAIL;
	}
	return USBD_OK;
}

写操作的代码如下:(依旧有库函数作为基本的调用)

//*src Flash数据的来源数组,addr 要更新的地址,Length 数据长度(byte长度)
USBD_StatusTypeDef USB_Write_Flash(uint8_t *src,uint32_t addr,uint32_t length)
{
	uint32_t index;
	for(index=0;index<length;index=index+4)
	{
    //4个Byte一起更新,由于STM32为32位单片机,32位的操作是默认的。
		if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+index, *(uint32_t*)(src+index))==HAL_OK)
		{
      //可以增加读取然后比较的函数,这样就可以确定Flash上的数据时对的。
      //我的应用场景中会在最后对Flash进行CRC校验,因此这一步会省掉,后面文章会详细叙述
		}
		else
		{
			return USBD_FAIL;
		}
	}
	return USBD_OK;
}

这样只需要调用上面的两个函数就可以对Flash进行基本的更新操作了。

另外需要提醒一下,STM32的Flash擦除和写操作的时候需要对其进行解锁,如下面代码:

USBD_StatusTypeDef USB_Init_Flash()
{
	HAL_FLASH_Unlock();//Flash操作的解锁
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP|FLASH_FLAG_WRPERR|FLASH_FLAG_PGERR);//清除相关标志位
	return (USBD_OK);
}

最后再说明一点,Flash的解锁,写和擦除操作上面代码都已经有叙述,那么读操作呢?

如下:

#define Flash_Addr  0x8008000
uint32_t device_flash_data=  *(__IO uint32_t *)(Flash_Addr);//直接对该地址数据进行读取

这就是所有对Flash的操作,加上我上文提到的实现BootLoader以及之前文章中分享的USB HID接口实现,实则,目前已经可以实现STM32 Flash的自定义升级了。我后面的文章就将其总结完善,敬请期待。

© 版权声明

相关文章

6 条评论

您必须登录才能参与评论!
立即登录
  • 头像
    顿悟而立且行且珍惜 读者

    收藏了,感谢分享

    无记录
  • 头像
    带给你饼和酒 读者

    谢谢

    无记录
  • 头像
    观世音菩萨基金会 读者

    收藏了,感谢分享!期待更多嵌入式开发相关知识!特别比较感兴趣的是不知道有没有这样的案例:让application与上位机握手通讯上,然后加载RAM Bootloader到RAM,最后再将控制权交给(跳转到运行)RAM BL,进行application区域的擦除、重新写入

    无记录
  • 头像
    电子1豆 投稿者

    不确定能不能实现,我先来研究下,相当于在某种条件下让FW在RAM中开始运行。你能说下为啥要这样操作吗?为了执行快?还是说有其他优势?

    无记录
  • 头像
    白银海沙飞 读者

    这个是我们公司的一台国外设备对冰箱控制板作编程用的,我们这俗称刷程序!目的就是为了给控制板更新程序!控制板在供应商会预先烧写一部分固件,我们叫ROM BL,实际上包含ROM bootloader +application,然后通过这个,到工厂后由老外的设备跟控制板完成握手通讯!剩下的就更我之前描述一样了!

    无记录
  • 头像
    北初创业会 读者

    实现肯定是没问题了,对于mcu平台没啥意义倒是真的,从ROM或外部存储中将代码拷贝到RAM,然后跳转到RAM执行,执行完之后跳回ROM,拷贝下一段代码到RAM,依此循环,这就是干了操作系统的活。mcu平台一般没有这么干的,ROM不够就换个ROM更大的型号,如果ROM最大的mcu资源都不够,那就用arm A系列,用Linux等操作系统了。如果是为了释放ROM bootloader的空间供业务代码使用,就更没必要了,最小版的bootloader就占个1kB的ROM,至于RAM,用完就释放了。

    无记录