stm32的學(xué)習(xí)—FLASH的操作和使用
Flash的操作:
stm32大容量的flash不僅用來存儲程序代碼,還可用來存儲一些數(shù)據(jù)和系統(tǒng)用戶的參數(shù)。程序的代碼一般保存在從flash開始區(qū)域,剩下的區(qū)域空間大小可以用來存儲用戶數(shù)據(jù)(大小取決于Flash的大小和代碼占用空間的大?。H绻鎯Φ臄?shù)據(jù)很少可以用最后一頁用于專門的存貯用戶數(shù)據(jù),這樣可以防止和程序代碼空間沖突。
1、STM32的Flash有讀寫次數(shù)和壽命的限制,所以不要放在循環(huán)中反復(fù)執(zhí)行讀寫操作。
2、FLASH的讀寫均需要時間,設(shè)置等待周期是為了確保正確的讀寫。因為cpu的速度遠(yuǎn)遠(yuǎn)大于FLASH的操作速度。用庫函數(shù)FLASH_SetLatency(FLASH_Latency_2)來設(shè)置。
3、開啟FLASH預(yù)讀緩沖功能,加速FLASH的讀取。所有程序中必須的
用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
4、打開內(nèi)部振蕩器RCC_HSICmd(ENABLE);
5、STM32對Flash的操作必須遵循一定的步驟,必須先擦除再寫入,擦除必須以PAGE(頁)位單位,寫(編程)必須以Word(兩字節(jié))為單位。
6、關(guān)于讀保護(hù)和寫保護(hù):
配置了讀保護(hù)之后,F(xiàn)lash中的代碼和數(shù)據(jù)無法通過JTAG和RAM中的程序讀出,起到了加密的作用。寫保護(hù)是以頁(或多頁)為單位的,配置之后無法被擦除或修改,加強(qiáng)了代碼的可靠性。讀保護(hù)和寫保護(hù)都是在自己的程序中配置的。你可以在第一次運(yùn)行程序是配置相關(guān)選擇字。
程序是從0x0800f800開始寫入2個半字的數(shù)據(jù),然后在MAIN函數(shù)中用串口返回:
voidflash_write()
{u16cnt=0;
u16data[2]={0x1234,0x5678};
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(0x0800f800);
for(cnt=0;cnt<2;cnt++)
FLASH_ProgramHalfWord((0x0800f800+cnt*2),data[cnt]);
FLASH_Lock();
}
MAIN函數(shù)關(guān)于Flash操作的代碼:
uint8_ti;
FLASH_SetLatency(FLASH_Latency_2);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
flash_write();
i=*(uint32_t*)(0x0800f802);//讀取改地址的數(shù)據(jù),賦值i
send_byte(i);//串口返回0x0800f802地址處的數(shù)據(jù)因為之前想寫一個字節(jié)老是出錯,所以翻翻手冊,果然看到不能寫1個字節(jié)數(shù)據(jù)。而且還發(fā)現(xiàn),flash寫地址為奇數(shù)時也會出錯。所以這份代碼里面
寫flash的地址只能是偶數(shù)。瀏覽過程中還發(fā)現(xiàn),手冊里面說寫flash和擦除flash的時候會影響cpu的運(yùn)行速度,沒仔細(xì)看(真心不想看)。
1.-DataFlash.c----------------------------------
2.
3.#include"DataFlash.h"
4uint16_tFlash_Write_Without_check(uint32_tiAddress,uint8_t*buf,uint16_tiNumByteToWrite){
9.uint16_ti;
10.volatileFLASH_StatusFLASHStatus=FLASH_COMPLETE;
11.i=0;
12.
13.//FLASH_UnlockBank1();
14.while((i 15.{ 16.FLASHStatus=FLASH_ProgramHalfWord(iAddress,*(uint16_t*)buf); 17.i=i+2; 18.iAddress=iAddress+2; 19.buf=buf+2; 20.} 21. 22.returniNumByteToWrite; 23.} 24.// 33.intFlash_Write(uint32_tiAddress,uint8_t*buf,uint32_tiNbrToWrite){ 34./ 35.uint32_tsecpos; 36.uint32_tiNumByteToWrite=iNbrToWrite; 37.uint16_tsecoff; 38.uint16_tsecremain; 39.uint16_ti=0; 40.uint8_ttmp[FLASH_PAGE_SIZE]; 41. 42.FLASH_UnlockBank1(); 43.secpos=iAddress&(~(FLASH_PAGE_SIZE-1));//扇區(qū)地址 44.secoff=iAddress&(FLASH_PAGE_SIZE-1);//在扇區(qū)內(nèi)的偏移 45.secremain=FLASH_PAGE_SIZE-secoff;//扇區(qū)剩余空間大小 46.volatileFLASH_StatusFLASHStatus=FLASH_COMPLETE; 47. 48.if(iNumByteToWrite<=secremain)secremain=iNumByteToWrite;//不大于4096個字節(jié) 49. 50.while(1){ 51.Flash_Read(secpos,tmp,FLASH_PAGE_SIZE);//讀出整個扇區(qū) 52.for(i=0;i//校驗數(shù)據(jù) 53.if(tmp[secoff+i]!=0XFF)break;//需要擦除 54.} 55.if(i//需要擦除 56.FLASHStatus=FLASH_ErasePage(secpos);//擦除這個扇區(qū) 57.if(FLASHStatus!=FLASH_COMPLETE) 58.return-1; 59.for(i=0;i//復(fù)制 60.tmp[i+secoff]=buf[i]; 61.} 62.Flash_Write_Without_check(secpos,tmp,FLASH_PAGE_SIZE);//寫入整個扇區(qū) 63.}else{ 64.Flash_Write_Without_check(iAddress,buf,secremain);//寫已經(jīng)擦除了的,直接寫入扇區(qū)剩余區(qū)間. 65.} 66. 67.if(iNumByteToWrite==secremain)//寫入結(jié)束了 68.break; 69.else{ 70.secpos+=FLASH_PAGE_SIZE; 71.secoff=0;//偏移位置為0 72.buf+=secremain;//指針偏移 73.iAddress+=secremain;//寫地址偏移 74.iNumByteToWrite-=secremain;//字節(jié)數(shù)遞減 75.if(iNumByteToWrite>FLASH_PAGE_SIZE)secremain=FLASH_PAGE_SIZE;//下一個扇區(qū)還是寫不完 76.elsesecremain=iNumByteToWrite;//下一個扇區(qū)可以寫完了 77.} 78. 79.} 80. 81.FLASH_LockBank1(); 82. return iNbrToWri