1.stm32f10xxx閃存編程參考手冊寫的很詳細。
2.主閃存編程:
對主閃存編程每次可以寫入16位。當FLASH_CR寄存器的PG位爲’1’時,在一個閃存地址寫入一個半字將啓動一次編程;寫入任何非半字的數據,FPEC都會產生總線錯誤。在編程過程中(BSY位爲’1’),任何讀寫閃存的操作都會使CPU暫停,直到此次閃存編程結束。
3.
4. 寫入flash函數
代碼正點原子例程。
用一個數組u16(半字)存放數據,然後在解鎖的情況下,一個一個的複製到被寫入的flash地址中去。
這裏沒有跨越頁區。
//從指定地址開始寫入指定長度的數據
//WriteAddr:起始地址(此地址必須爲2的倍數!!)
//pBuffer:數據指針
//NumToWrite:半字(16位)數(就是要寫入的16位數據的個數.)
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024 //字節
#else
#define STM_SECTOR_SIZE 2048
#endif
u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字節
void STMFLASH_Write(u32 WriteAddr,u16 * pBuffer,u16 NumToWrite)
{
u32 secpos; //扇區地址
u16 secoff; //扇區內偏移地址(16位字計算)
u16 secremain; //扇區內剩餘地址(16位字計算)
u16 i;
u32 offaddr; //去掉0X08000000後的地址
if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
FLASH_Unlock(); //解鎖
offaddr=WriteAddr-STM32_FLASH_BASE; //實際偏移地址.
secpos= offaddr / STM_SECTOR_SIZE; //扇區地址 0~127 for STM32F103RBT6
secoff=(offaddr % STM_SECTOR_SIZE)/2; //在扇區內的偏移(2個字節爲基本單位.)
secremain=STM_SECTOR_SIZE/2-secoff; //扇區剩餘空間大小
if(NumToWrite<=secremain)secremain=NumToWrite;//不大於該扇區範圍
//爲後面的循環寫入提供方便,第92行的判斷
while(1)
{
STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//讀出整個扇區的內容
for(i=0;i<secremain;i++)//校驗數據
{
if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除
}
if(i<secremain)//需要擦除
{
FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除這個扇區
for(i=0;i<secremain;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//寫入未結束
{
secpos++; //扇區地址增1
secoff=0; //偏移位置爲0
pBuffer+=secremain; //指針偏移
WriteAddr+=secremain; //寫地址偏移
NumToWrite-=secremain; //字節(16位)數遞減
if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一個扇區還是寫不完
else secremain=NumToWrite;//下一個扇區可以寫完了
}
};
FLASH_Lock();//上鎖
}
#endif
5# 速度匹配問題