(1)Flash的簡介
不同型號的 STM32,其 FLASH 容量也有所不同,最小的只有 16K 字節(jié),最大的則達到了1024K 字節(jié)。
STM32F103ZET6 的 FLASH 容量為 512K 字節(jié),屬于大容量產品。
STM32 的閃存模塊由:主存儲器、信息塊和閃存存儲器接口寄存器等 3 部分組成。
尤其是閃存存儲器接口寄存器有以下特性:閃存存儲器接口寄存器,該部分用于控制閃存讀寫等,是整個閃存模塊的控制機構。
對主存儲器和信息塊的寫入由內嵌的閃存編程/擦除控制器(FPEC)管理;編程與擦除的高電壓由內部產生。
在執(zhí)行閃存寫操作時,任何對閃存的讀操作都會鎖住總線,在寫操作完成后讀操作才能正確地進行;既在進行寫或擦除操作時,不能進行代碼或數據的讀取操作。
(2)stm32閃存編程過程如下圖
從上圖可以得到閃存的編程順序如下:
? 檢查 FLASH_CR 的 LOCK 是否解鎖,如果沒有則先解鎖
? 檢查 FLASH_SR 寄存器的 BSY 位,以確認沒有其他正在進行的編程操作
? 設置 FLASH_CR 寄存器的 PG 位為’1’
? 在指定的地址寫入要編程的半字
? 等待 BSY 位變?yōu)椤?’
? 讀出寫入的地址并驗證數據
前面提到,我們在 STM32 的 FLASH 編程的時候,要先判斷縮寫地址是否被擦除了,所以,
我們有必要再介紹一下 STM32 的閃存擦除,STM32 的閃存擦除分為兩種:頁擦除和整片擦除。
(3)stm32頁擦除如下圖
從上圖可以看出,STM32 的頁擦除順序為:
? 檢查 FLASH_CR 的 LOCK 是否解鎖,如果沒有則先解鎖
? 檢查 FLASH_SR 寄存器的 BSY 位,以確認沒有其他正在進行的閃存操作
? 設置 FLASH_CR 寄存器的 PER 位為’1’
? 用 FLASH_AR 寄存器選擇要擦除的頁
? 設置 FLASH_CR 寄存器的 STRT 位為’1’
? 等待 BSY 位變?yōu)椤?’
? 讀出被擦除的頁并做驗證
(4)下面就是操作Flash的一個重要的函數了:
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024
#else
#define STM_SECTOR_SIZE 2048
#endif
u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u32 secpos;
u16 secoff;
u16 secremain;
u16 i;
u32 offaddr;
if(WriteAddr
FLASH_Unlock();
offaddr=WriteAddr-STM32_FLASH_BASE;
secpos=offaddr/STM_SECTOR_SIZE;
secoff=(offaddr%STM_SECTOR_SIZE)/2;
secremain=STM_SECTOR_SIZE/2-secoff;
if(NumToWrite<=secremain)secremain=NumToWrite;
while(1)
{
STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
for(i=0;i
if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;
}
if(i
FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);
for(i=0;i
STMFLASH_BUF[i+secoff]=pBuffer[i];
}
STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
}else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);
if(NumToWrite==secremain)break;
else//D′è??′?áê?
{
secpos++;
secoff=0;
pBuffer+=secremain;
WriteAddr+=secremain;
NumToWrite-=secremain;
if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;
else secremain=NumToWrite;
}
};
FLASH_Lock();
}
#endif