STM32 内部FLASH用作用户数据区Byte操作函数设计 (HAL)

STM32 内部FLASH用作用户数据区Byte操作函数设计 (HAL)

说明

STM32内部的FLASH空间,主要用作代码存储空间。在IAP模式,分为boot和app两个区,boot区可以由JTAG/SWD和ISP方式写入,app区通过选定的接口接收数据后写入FLASH, 在这种模式下, app的首地址一般是FLASH的页对齐地址,无论是擦除还是写入,都没有之前的数据信息保护需要考虑。

当用户把一块(通常靠后)的FLASH空间,用作第三个区,作为数据区使用,则在擦除和写入时,需要对原有数据,本次不改写的部分,进行保护。

STM32内部FLASH只支持32位字地址写入,不支持字节和半字地址写入;而读操作不受限制,可以读取字节,半字和字地址数据。在把FLASH空间用作数据区时,操作灵活性上要求能够进行字节为单位的写入和读取,故基于下述规则设计了STM32内部FLASHByte操作函数。

规则

  1. 如果写入的首页和尾页数据,不是一整页,则需要把原有页内数据读出,再和要写入的数据组合后,作为整理后的一整页数据写入。
  2. 中间的页面,是整页数据,可以直接擦除后覆盖写入。
  3. 最终实现从1个byte到任意byte(在一个页内或跨多个页)的写入读取,不影响其它地址的数据。

STM32内部FLASH WORD读写函数

以STM32L0为例,先了解下WORD的读写函数, FLASH写入前需要进行解锁和页擦除:
HAL库STM32L0xx_hal_flash.h里有Flash空间和页面空间的定义:

#define FLASH_SIZE                (uint32_t)((*((uint32_t *)FLASHSIZE_BASE)&0xFFFF) * 1024U)
#define FLASH_PAGE_SIZE           ((uint32_t)128U)  /*!< FLASH Page Size in bytes */

字操作的读函数可如下编写:

//Word read
HAL_StatusTypeDef FLASH_READ_WORD(uint32_t addr, uint32_t *data, uint32_t Size)
{
  uint32_t d32;

  for(uint32_t i = 0;i< Size ;i++)
	{
			d32 = *(__IO uint32_t*)(addr + i * 4);
			*(data+i * 4) = d32;

	}
  return HAL_OK;
}

字操作的写函数可如下编写:

//Word write
HAL_StatusTypeDef FLASH_WRITE_WORD(uint32_t addr, uint32_t *data, uint32_t Size)
{
	uint8_t HAL_STATUS = 0;
    uint32_t PageError = 0;

    HAL_FLASH_Unlock();  //unlock

    FLASH_EraseInitTypeDef fe;
    fe.TypeErase = FLASH_TYPEERASE_PAGES;
    fe.PageAddress = addr;
    fe.NbPages = 1;

    HAL_FLASHEx_Erase(&fe, &PageError);  //Erase page

	  uint32_t d32 = 0;
	  for(uint32_t i = 0;i< Size ;i++)
	 {
		 d32 = (*(data+i*4));
		 HAL_STATUS += HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD , addr + i * 4, d32);
	 }

     HAL_FLASH_Lock();

     if (HAL_STATUS==0) return HAL_OK;
     else return HAL_ERROR;
}

STM32内部FLASH BYTE读函数

字节读函数可编写如下,相对比较容易:

//Byte read
HAL_StatusTypeDef FLASH_READ_BYTE(uint32_t addr, uint8_t *data, uint32_t Size)
{
  uint8_t d8;

  for(uint32_t i = 0;i< Size ;i++)
	{
			d8 = *(__IO uint8_t*)(addr + i);
			*(data+i) = d8;

	}
  return HAL_OK;
}

STM32内部FLASH BYTE写函数

字节写函数的设计分为3种页面情况,只在1页写,只在2页写和超过2页写。具体的函数设计如下:

//Byte write:written by Pegasus Yu 2019/01/09
HAL_StatusTypeDef FLASH_WRITE_BYTE(uint32_t addr, uint8_t *data, uint32_t Size)
{
	HAL_StatusTypeDef HAL_STATUS = HAL_ERROR;
    uint32_t PageError = 0;

    extern FLASH_ProcessTypeDef pFlash;
    uint32_t pstart = 0; //address number in first page
    uint32_t pn = 0;     //total page number
    uint32_t pstop = 0;  //address number in last page
    uint8_t fpage[FLASH_PAGE_SIZE] = {0};
    uint8_t lpage[FLASH_PAGE_SIZE] = {0};
    uint32_t icount;
    uint32_t d32;

    assert_param(IS_FLASH_PROGRAM_ADDRESS(addr));// Check the parameters

    if (Size>(FLASH_PAGE_SIZE-(addr%FLASH_PAGE_SIZE)))
    {
    pstart =(FLASH_PAGE_SIZE-(addr%FLASH_PAGE_SIZE));
    pn = (Size-((pstart==FLASH_PAGE_SIZE)?FLASH_PAGE_SIZE:pstart))/FLASH_PAGE_SIZE + ((((Size-((pstart==FLASH_PAGE_SIZE)?FLASH_PAGE_SIZE:pstart))%FLASH_PAGE_SIZE)==0)?0:1) + 1;  //total page number
    pstop = Size-pstart-(pn-2)*FLASH_PAGE_SIZE; //address number in last page
    }
    else
    {
    pn = 1;
    pstart = Size;
    pstop = Size;
    }

    HAL_FLASH_Unlock();  //unlock

    if (pn==1)
    {
    	for (icount = 0; icount

经过验证,首地址为奇数或偶数地址,写半页字节数据,一页半字节数据,两页半字节数据,读回字节都正确,且未操作的地址,字节数据未被擦除破坏。

-End-

你可能感兴趣的:(STM32)