STM32 internal FLASH is used as the user data area Byte operation function design (HAL)

STM32 internal FLASH is used as the user data area Byte operation function design (HAL)

Description

The FLASH space inside STM32 is mainly used as code storage space. In IAP mode, it is divided into two areas, boot and app. The boot area can be written by JTAG/SWD and ISP. The app area receives data through the selected interface and writes it to FLASH. In this mode, the first address of the app Generally, it is the page-aligned address of FLASH, no matter it is erased or written, there is no need to consider the previous data information protection.

When the user uses a block (usually at the back) of the FLASH space as the third area as a data area, when erasing and writing, the original data and the part that will not be rewritten this time need to be protected.

STM32 internal FLASH only supports 32-bit word address writing, and does not support byte and half-word address writing; while the read operation is not restricted, and byte, half-word and word address data can be read. When the FLASH space is used as a data area, operating flexibility requires the ability to write and read bytes as a unit, so the STM32 internal FLASHByte operation function is designed based on the following rules.

rule

  1. If the first page and last page data written are not a whole page, the data in the original page needs to be read out, and then combined with the data to be written, it is written as a whole page data after sorting.
  2. The middle page is the entire page of data, which can be overwritten after being erased directly.
  3. The final realization of writing and reading from 1 byte to any byte (within a page or across multiple pages) does not affect data at other addresses.

STM32 internal FLASH WORD read and write functions

Taking STM32L0 as an example, first understand the read and write functions of WORD. Before FLASH is written, unlock and page erasure are required: The
HAL library STM32L0xx_hal_flash.h has the definition of Flash space and page space:

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

The read function for word operations can be written as follows:

//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;
}

The write function for word operations can be written as follows:

//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 internal FLASH BYTE read function

The byte read function can be written as follows, which is relatively easy:

//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 internal FLASH BYTE write function

The design of the byte write function is divided into three types of page situations, which are only written in 1 page, only written in 2 pages, and written in more than 2 pages. The specific function design is as follows:

//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<FLASH_PAGE_SIZE; icount++)
    	{
     		fpage[icount]=*((uint8_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount));
    	}

    	for (icount = 0; icount< pstart; icount++)
    	{
    		fpage[(addr%FLASH_PAGE_SIZE) + icount]= *(data+icount);
    	}

        FLASH_EraseInitTypeDef fe;
    	fe.TypeErase = FLASH_TYPEERASE_PAGES;
    	fe.PageAddress = addr;
  	    fe.NbPages = 1;
  	    HAL_FLASHEx_Erase(&fe, &PageError);  //Erase page

  	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
  	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
  	    __HAL_LOCK(&pFlash);  // Process Locked

    	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
    	{
    		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; // Clean the error context
    		*(uint32_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount*4) = *(uint32_t *)(fpage+icount*4);
      	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
      	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
    	}
        __HAL_UNLOCK(&pFlash);   /* Process Unlocked */
        HAL_FLASH_Lock();
    }
    else if (pn==2)
    {
         	for (icount = 0; icount<FLASH_PAGE_SIZE; icount++)
        	{
        		fpage[icount]=*((uint8_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount));

        	}
        	for (icount = 0; icount< pstart; icount++)
        	{
        		fpage[(addr%FLASH_PAGE_SIZE) + icount]= *(data+icount);
        	}

        	for (icount = 0; icount<FLASH_PAGE_SIZE; icount++)
        	{
        		lpage[icount]=*((uint8_t *)((addr/FLASH_PAGE_SIZE+1)*FLASH_PAGE_SIZE+icount));

        	}
        	for (icount = 0; icount< pstop; icount++)
        	{
        		lpage[icount]= *(data+(FLASH_PAGE_SIZE-(addr%FLASH_PAGE_SIZE))+icount);
        	}

            FLASH_EraseInitTypeDef fe;
        	fe.TypeErase = FLASH_TYPEERASE_PAGES;
        	fe.PageAddress = addr;
      	    fe.NbPages = 2;
      	    HAL_FLASHEx_Erase(&fe, &PageError);  //Erase page

      	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE*2);// Wait for last operation to be completed
      	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
      	    __HAL_LOCK(&pFlash);  // Process Locked


        	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
        	{
        		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; // Clean the error context
        		*(uint32_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount*4) = *(uint32_t *)(fpage+icount*4);
          	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
          	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
        	}

        	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
        	{
        		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
        		*(uint32_t *)((addr/FLASH_PAGE_SIZE+1)*FLASH_PAGE_SIZE+icount*4) = *(uint32_t *)(lpage+icount*4);
          	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
          	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
        	}

            __HAL_UNLOCK(&pFlash);   /* Process Unlocked */
            HAL_FLASH_Lock();
     }
     else
     {
       if (pstart != FLASH_PAGE_SIZE)
       {
       	  for (icount = 0; icount<FLASH_PAGE_SIZE; icount++)
       	  {
       		fpage[icount]=*((uint8_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount));
       	  }
       	  for (icount = 0; icount< pstart; icount++)
       	  {
       		fpage[(addr%FLASH_PAGE_SIZE) + icount]= *(data+icount);
       	  }
       }

       if (pstop != FLASH_PAGE_SIZE)
       {
       	  for (icount = 0; icount<FLASH_PAGE_SIZE; icount++)
       	  {
       		lpage[icount]=*((uint8_t *)((addr/FLASH_PAGE_SIZE+pn-1)*FLASH_PAGE_SIZE+icount));
       	  }
       	  for (icount = 0; icount< pstop; icount++)
       	  {
       		lpage[icount]= *(data+(Size-pstop)+icount);
       	  }

       }

        FLASH_EraseInitTypeDef fe;
    	fe.TypeErase = FLASH_TYPEERASE_PAGES;
   	    fe.PageAddress = addr;
 	    fe.NbPages = pn;
 	    HAL_FLASHEx_Erase(&fe, &PageError);  //Erase page

 	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE*pn);// Wait for last operation to be completed
 	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
 	    __HAL_LOCK(&pFlash);  // Process Locked

  	    if (pstart!=FLASH_PAGE_SIZE)
 	    {
 	    	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
 	    	{
 	    		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;  	    // Clean the error context
 	    		*(uint32_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount*4) = *(uint32_t *)(fpage+icount*4);
 	      	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
 	      	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
 	    	}
 	    }
  	    else
 	    {
 	    	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
 	    	{
 	    		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; 	    // Clean the error context
 	    		d32 = (*(data+icount*4)) + ((*(data+icount*4+1))<<8) + ((*(data+icount*4+2))<<16) + ((*(data+icount*4+3))<<24);
 	    		*(uint32_t *)((addr/FLASH_PAGE_SIZE)*FLASH_PAGE_SIZE+icount*4) = *(uint32_t *)(data+icount*4);
 	      	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
 	      	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
 	    	}
 	    }

        for (icount = 0; icount < (pn-2)*(FLASH_PAGE_SIZE/4); icount++)
        {
	    		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
	    		d32 = (*(data+pstart+icount*4)) + ((*(data+pstart+icount*4+1))<<8) + ((*(data+pstart+icount*4+2))<<16) + ((*(data+pstart+icount*4+3))<<24);
	    		*(uint32_t *)((addr+pstart)+icount*4) = d32;

	      	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
	      	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
        }

        if (pstop != FLASH_PAGE_SIZE)
        {
        	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
        	{
        		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
        		*(uint32_t *)((addr/FLASH_PAGE_SIZE+pn-1)*FLASH_PAGE_SIZE+icount*4) = *(uint32_t *)(lpage+icount*4);
          	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
          	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
        	}
        }
        else
        {
        	for (icount = 0; icount< (FLASH_PAGE_SIZE/4); icount++)
        	{
        		pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
        		d32 = (*(data+(Size-pstop)+icount*4)) + ((*(data+(Size-pstop)+icount*4+1))<<8) + ((*(data+(Size-pstop)+icount*4+2))<<16) + ((*(data+(Size-pstop)+icount*4+3))<<24);
        		*(uint32_t *)((addr/FLASH_PAGE_SIZE+pn-1)*FLASH_PAGE_SIZE+icount*4) = d32;
          	    HAL_STATUS = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);// Wait for last operation to be completed
          	    if (HAL_STATUS!=HAL_OK) return HAL_STATUS;
        	}

        }

        __HAL_UNLOCK(&pFlash);   /* Process Unlocked */
        HAL_FLASH_Lock();

     }

    return HAL_STATUS;
}

After verification, the first address is an odd or even address, write half page of byte data, one page of half byte data, two pages of half byte data, read back bytes are correct, and the unoperated address, byte data is not Erase destruction.

-End-

Guess you like

Origin blog.csdn.net/hwytree/article/details/103907992