STM32F407HAL uses FLASH to write and power-down save

FLASH workflow

Data write process: Flash unlock-erase sector-write data to the specified space-lock write protection;
read data process: read the specified length of data from the specified address.

Source file flash.c writing

The STMFLASH_GetFlashSector function is used to determine which sector the starting address is written in, and return to the sector, and then erase the sector.

uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
    
    
	return *(__IO uint32_t*)faddr; 
}


uint8_t STMFLASH_GetFlashSector(uint32_t addr)
{
    
    
	if(addr<ADDR_FLASH_SECTOR_1)return FLASH_SECTOR_0;
	else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_SECTOR_1;
	else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_SECTOR_2;
	else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_SECTOR_3;
	else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_SECTOR_4;
	else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_SECTOR_5;
	else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_SECTOR_6;
	else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_SECTOR_7;
	else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_SECTOR_8;
	else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_SECTOR_9;
	else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_SECTOR_10;   
	return FLASH_SECTOR_11;	
}

The write function needs to use the HAL library. Before unlocking, define the structure first and determine whether the write address is legal. Then unlock, erase the corresponding sector and write. Erase is to erase one sector at a time, and write is to write one by one, and finally lock.
The start address of the read function must be the same as the address written before, and then stored in the defined array.
The inputs of the above two functions are the starting address, the array to be read and written, and the number of numbers in the array.

void STMFLASH_Write(uint32_t Addr,uint32_t *pBuffer,uint32_t Num)	
{
    
     
	FLASH_EraseInitTypeDef FlashEraseInit;
	HAL_StatusTypeDef FlashStatus=HAL_OK;
	uint32_t SectorError=0;
	uint32_t addrx=0;
	uint32_t endaddr=0;	
	if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;	//非法地址
    
	HAL_FLASH_Unlock();             //解锁	
	addrx=WriteAddr;				//写入的起始地址
	endaddr=WriteAddr+Num*4;	//写入的结束地址
    
	if(addrx<0X080C1000)
	{
    
    
		while(addrx<endaddr)		
		{
    
    
			 if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)			{
    
       
				FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS;       //擦除类型,扇区擦除 
				FlashEraseInit.Sector=STMFLASH_GetFlashSector(addrx);   //要擦除的扇区
				FlashEraseInit.NbSectors=1;                             //一次只擦除一个扇区
				FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3;      //电压范围,VCC=2.7~3.6V之间!!
				if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK) 
				{
    
    
					break;//发生错误了	
				}
				}else addrx+=4;
				FLASH_WaitForLastOperation(FLASH_WAITETIME);                //等待上次操作完成
		}
	}
	FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME);            //等待上次操作完成
	if(FlashStatus==HAL_OK)
	{
    
    
		 while(WriteAddr<endaddr)//写数据
		 {
    
    
			if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,WriteAddr,*pBuffer)!=HAL_OK)//写入数据
			{
    
     
				break;	//写入异常
			}
			WriteAddr+=4;
			pBuffer++;
		}  
	}
	HAL_FLASH_Lock();           //上锁
} 

void STMFLASH_Read(uint32_t Addr,uint32_t *pBuffer,uint32_t size)   	
{
    
    
	uint32_t i;
	for(i=0;i<size;i++)
	{
    
    
		pBuffer[i]=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
		ReadAddr+=4;//偏移4个字节.	
	}
}

Header file flash.h

The 11 sectors here correspond to the sectors of the main register of the STM32F407.

#define STM32_FLASH_BASE 0x08000000 	//STM32 FLASH的起始地址
#define FLASH_WAITETIME  50000          //FLASH等待超时时间

//FLASH 扇区的起始地址
#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) 	//扇区0起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) 	//扇区1起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) 	//扇区2起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) 	//扇区3起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) 	//扇区4起始地址, 64 Kbytes  
#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) 	//扇区5起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) 	//扇区6起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) 	//扇区7起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08080000) 	//扇区8起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_9     ((uint32_t)0x080A0000) 	//扇区9起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_10    ((uint32_t)0x080C0000) 	//扇区10起始地址,128 Kbytes  
#define ADDR_FLASH_SECTOR_11    ((uint32_t)0x080E0000) 	//扇区11起始地址,128 Kbytes 

uint32_t STMFLASH_ReadWord(uint32_t faddr);		  	//读出字  
void STMFLASH_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite);		//从指定地址开始写入指定长度的数据
void STMFLASH_Read(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t NumToRead);   		//从指定地址开始读出指定长度的数据

Insert picture description here

The main function should be added

When the power is off, write the 6 numbers you want to save to this address. Note that this address must be within the range of the 11 addresses defined above. If it exceeds, the erased sector will be detected incorrectly and cannot Write normally. Furthermore, the address needs to be a free address, which cannot affect the normal operation of the program. (The 6 numbers to be stored are 8-bit and are forced to be converted to 32-bit writing)

       if(掉电)
       {
    
    
         uint8_t TEXT[6];
         TEXT[0] = Set_A;;
		 TEXT[1] = Set_B;
		 TEXT[2] = Set_C;
 		 TEXT[3] = Set_E;
		 TEXT[4] = Set_F;
		 TEXT[5] = Set_G;	
     STMFLASH_Write(0x800C0000,(uint32_t*)TEXT,6);
     }

Note that the read address should be the same as the write address. Another thing is that the six numbers we read are all 32-bits, and the numbers we need are 8-bits, so add uint8_t to force them to 32-bits. , So that it can work normally and realize power-down save.

		if(上电)
		{
    
    
		 uint8_t INXT[6];
		 STMFLASH_Read(0x800C0000,(uint32_t*)INXT,6);
		 uint8_t Set_A = INXT[0];
		 uint8_t Set_B = INXT[1];
		 uint8_t Set_C = INXT[2];
 		 uint8_t Set_E = INXT[3];
		 uint8_t Set_F = INXT[4];
		 uint8_t Set_G = INXT[5];
		 } 

Novice summary

This is my first time to write a blog. I wrote this mainly because when I used the HAL library to write down and save, I could not find a more comprehensive method on the Internet. I pieced together and finally realized this function. Maybe There are also a lot of rough writing, I hope you will criticize and correct me, and I hope this article can help me use the HAL library to write the uncomfortable problems of power-down storage, O(∩_∩)O~.

Guess you like

Origin blog.csdn.net/chenzhen1223/article/details/108754049