stm32的學(xué)習(xí)—FLASH的操作和使用
Flash的操作:
stm32大容量的flash不僅用來(lái)存儲(chǔ)程序代碼,還可用來(lái)存儲(chǔ)一些數(shù)據(jù)和系統(tǒng)用戶的參數(shù)。程序的代碼一般保存在從flash開(kāi)始區(qū)域,剩下的區(qū)域空間大小可以用來(lái)存儲(chǔ)用戶數(shù)據(jù)(大小取決于Flash的大小和代碼占用空間的大?。H绻鎯?chǔ)的數(shù)據(jù)很少可以用最后一頁(yè)用于專門的存貯用戶數(shù)據(jù),這樣可以防止和程序代碼空間沖突。
1、STM32的Flash有讀寫(xiě)次數(shù)和壽命的限制,所以不要放在循環(huán)中反復(fù)執(zhí)行讀寫(xiě)操作。
2、FLASH的讀寫(xiě)均需要時(shí)間,設(shè)置等待周期是為了確保正確的讀寫(xiě)。因?yàn)閏pu的速度遠(yuǎn)遠(yuǎn)大于FLASH的操作速度。用庫(kù)函數(shù)FLASH_SetLatency(FLASH_Latency_2)來(lái)設(shè)置。
3、開(kāi)啟FLASH預(yù)讀緩沖功能,加速FLASH的讀取。所有程序中必須的
用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
4、打開(kāi)內(nèi)部振蕩器RCC_HSICmd(ENABLE);
5、STM32對(duì)Flash的操作必須遵循一定的步驟,必須先擦除再寫(xiě)入,擦除必須以PAGE(頁(yè))位單位,寫(xiě)(編程)必須以Word(兩字節(jié))為單位。
6、關(guān)于讀保護(hù)和寫(xiě)保護(hù):
配置了讀保護(hù)之后,F(xiàn)lash中的代碼和數(shù)據(jù)無(wú)法通過(guò)JTAG和RAM中的程序讀出,起到了加密的作用。寫(xiě)保護(hù)是以頁(yè)(或多頁(yè))為單位的,配置之后無(wú)法被擦除或修改,加強(qiáng)了代碼的可靠性。讀保護(hù)和寫(xiě)保護(hù)都是在自己的程序中配置的。你可以在第一次運(yùn)行程序是配置相關(guān)選擇字。
程序是從0x0800f800開(kāi)始寫(xiě)入2個(gè)半字的數(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ù)因?yàn)橹跋雽?xiě)一個(gè)字節(jié)老是出錯(cuò),所以翻翻手冊(cè),果然看到不能寫(xiě)1個(gè)字節(jié)數(shù)據(jù)。而且還發(fā)現(xiàn),flash寫(xiě)地址為奇數(shù)時(shí)也會(huì)出錯(cuò)。所以這份代碼里面
寫(xiě)flash的地址只能是偶數(shù)。瀏覽過(guò)程中還發(fā)現(xiàn),手冊(cè)里面說(shuō)寫(xiě)flash和擦除flash的時(shí)候會(huì)影響cpu的運(yùn)行速度,沒(méi)仔細(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個(gè)字節(jié) 49. 50.while(1){ 51.Flash_Read(secpos,tmp,FLASH_PAGE_SIZE);//讀出整個(gè)扇區(qū) 52.for(i=0;i//校驗(yàn)數(shù)據(jù) 53.if(tmp[secoff+i]!=0XFF)break;//需要擦除 54.} 55.if(i//需要擦除 56.FLASHStatus=FLASH_ErasePage(secpos);//擦除這個(gè)扇區(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);//寫(xiě)入整個(gè)扇區(qū) 63.}else{ 64.Flash_Write_Without_check(iAddress,buf,secremain);//寫(xiě)已經(jīng)擦除了的,直接寫(xiě)入扇區(qū)剩余區(qū)間. 65.} 66. 67.if(iNumByteToWrite==secremain)//寫(xiě)入結(jié)束了 68.break; 69.else{ 70.secpos+=FLASH_PAGE_SIZE; 71.secoff=0;//偏移位置為0 72.buf+=secremain;//指針偏移 73.iAddress+=secremain;//寫(xiě)地址偏移 74.iNumByteToWrite-=secremain;//字節(jié)數(shù)遞減 75.if(iNumByteToWrite>FLASH_PAGE_SIZE)secremain=FLASH_PAGE_SIZE;//下一個(gè)扇區(qū)還是寫(xiě)不完 76.elsesecremain=iNumByteToWrite;//下一個(gè)扇區(qū)可以寫(xiě)完了 77.} 78. 79.} 80. 81.FLASH_LockBank1(); 82. return iNbrToWri





