STM32F103 Flash 读写实践(2KB 一页的坑)HAL库

我们实验室规定的协议,所有上传的数据要进行AES-128-CFB 加密, 密钥通过量产过程写入。密钥的持久化成了个问题。 单独给这16Byte 的数据加个EEPROM真的是不值当, 所以目光瞄向了512KByte 的Flash。 从网上查了资料发现STM32 的FLASH可以擦除重新编程。其实步骤很简单。可是一个坑让我难受了好多天……………………

①挖个坑!

这儿挖坑的时候注意,使用const修饰符修饰的全局变量会存到FLASH里面,然而STM32 的FLASH 在读之前要进行擦除操作, 而且擦除的时候要按页擦除。所以使用__align关键字使其对其到FLASH_PAGE_SIZE(后文会提到)。定义FLASH_PAGE_SIZE的宽度,防止擦除的时候把代码段擦除了。

__align(FLASH_PAGE_SIZE) const unsigned char aes_key[FLASH_PAGE_SIZE];

可以在MAP文件中搜到他的位置

QQ截图20180210200049.jpg

至于这个FLASH_PAGE_SIZE,后文会提到这是个大坑

②埋点土!

开个玩笑,并非埋土,而是要进行FLASH擦除操作。首先获得刚刚挖的坑的位置,可以使用 数组的地址即为刚刚变量的位置。

uint32_t addr = (uint32_t) aes_key;

uint32_t addr = (uint32_t) aes_key; 
uint32_t PageError = 0;
size_t olen;
FLASH_EraseInitTypeDef f;

f.TypeErase = FLASH_TYPEERASE_PAGES;
f.PageAddress = addr;
f.NbPages = 1;
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase(&f, &PageError);

for(int i = 0 ; i < 16; i += 2){
	uint32_t halfword =  (((uint32_t)tmp_aes_buff[i+1]) << 8 ) | tmp_aes_buff[i];
	HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr + i, halfword);
}
HAL_FLASH_Lock();

首先定义FLASH_EraseInitTypeDef ,然后指定地址和要擦除的页数,然后用HAL_FLASH_Program进行数据写入,要注意HAL_FLASH_Program 有三种写入模式,FLASH_TYPEPROGRAM_HALFWORD,即(16-bit), FLASH_TYPEPROGRAM_WORD 一个字 (32-bit),?FLASH_TYPEPROGRAM_DOUBLEWORD 双字 (64-bit), 并注意大端序。

然而,坑来了

网上所有的资料都显示F103 的FLASH 每个PAGE是1KB, 于是我先前写的?FLASH_PAGE_SIZE位置直接为1024, 导致每次写入之后程序都跑飞了。 于是我使用 J-Flash 把修改前后的FLASH 都出来,然后用UC COMPARE 比较,发现了这个大坑, 先是,我找到了 aes_key 的起始位置,发现写入正常, 如果按照1024字节那么他擦除的位置应该到8400,结果!!!!!

QQ图片20180210200440.png

从8400 开始我看到了我的BASE64 编码用的常量串............

纳尼,放开我的code

于是乎,我在代码段里面找到了这个宏

/** @defgroup FLASHEx_Page_Size Page Size
  * @{
  */ 
#if (defined(STM32F101x6) || defined(STM32F102x6) || defined(STM32F103x6) || defined(STM32F100xB) || defined(STM32F101xB) || defined(STM32F102xB) || defined(STM32F103xB))
#define FLASH_PAGE_SIZE          0x400U
#endif /* STM32F101x6 || STM32F102x6 || STM32F103x6 */
       /* STM32F100xB || STM32F101xB || STM32F102xB || STM32F103xB */

#if (defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F103xE) || defined(STM32F101xG) || defined(STM32F103xG) || defined(STM32F105xC) || defined(STM32F107xC))
#define FLASH_PAGE_SIZE          0x800U
#endif /* STM32F100xB || STM32F101xB || STM32F102xB || STM32F103xB */
       /* STM32F101xG || STM32F103xG */ 
       /* STM32F105xC || STM32F107xC */

你妹呀,说好的1K呢!!!!!
STM32F103RC 居然是2K !!!!!
把1024替换成宏以后, 问题解决!!
这个FLASH PAGE SIZE 是分型号的的, 在B系列是1K, 在C系列是2K,!!!

PS: 网上教程伤不起, 有的地方给的图片是1K,代码是2K, 有的地方给的图片是2K,代码是1K!!!

发表评论