金牌会员
 
- 积分
- 1182
- 金钱
- 1182
- 注册时间
- 2020-5-13
- 在线时间
- 202 小时
|
1金钱
u8 Drv_FLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u32 secpos; //扇区地址
u16 secoff; //扇区内偏移地址(16位字计算)
u16 secremain; //扇区内剩余地址(16位字计算)
u16 i;
u32 offaddr; //去掉0X08000000后的地址
#ifdef USE_DYNAMIC_MEM
u16* Drv_FLASH_BUF=NULL;
Drv_FLASH_BUF=(u16*)mmalloc(FLASH_SECTOR_SIZE);
if(Drv_FLASH_BUF==NULL)
return FAIL;
#endif
if(WriteAddr<FLASH_BASE_ADDR||(WriteAddr>=FLASH_END_ADDR)||(pBuffer==NULL))
return FAIL;//非法地址
FLASH_Unlock(); //解锁
offaddr=WriteAddr-FLASH_BASE_ADDR; //实际偏移地址.
secpos=offaddr/FLASH_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6
secoff=(offaddr%FLASH_SECTOR_SIZE)/2; //在扇区内的偏移(2个字节为基本单位.)
secremain=FLASH_SECTOR_SIZE/2-secoff; //扇区剩余空间大小
if(NumToWrite<=secremain)
secremain=NumToWrite;//不大于该扇区范围
while(1)
{
Drv_FLASH_Read(secpos*FLASH_SECTOR_SIZE+FLASH_BASE_ADDR,Drv_FLASH_BUF,FLASH_SECTOR_SIZE/2);//读出整个扇区的内容
for(i=0;i<secremain;i++)//校验数据
{
if(Drv_FLASH_BUF[secoff+i]!=0XFFFF)
break;//需要擦除
}
if(i<secremain)//需要擦除
{
FLASH_ErasePage(secpos*FLASH_SECTOR_SIZE+FLASH_BASE_ADDR);//擦除这个扇区
for(i=0;i<secremain;i++)//复制
{
Drv_FLASH_BUF[i+secoff]=pBuffer;
}
Drv_FLASH_Write_NoCheck(secpos*FLASH_SECTOR_SIZE+FLASH_BASE_ADDR,Drv_FLASH_BUF,FLASH_SECTOR_SIZE/2);//写入整个扇区
}
else
Drv_FLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间.
if(NumToWrite==secremain)
break;//写入结束了
else//写入未结束
{
secpos++; //扇区地址增1
secoff=0; //偏移位置为0
pBuffer+=secremain; //指针偏移
WriteAddr+=secremain; //写地址偏移
NumToWrite-=secremain; //字节(16位)数递减
if(NumToWrite>(FLASH_SECTOR_SIZE/2))
secremain=FLASH_SECTOR_SIZE/2;//下一个扇区还是写不完
else
secremain=NumToWrite;//下一个扇区可以写完了
}
};
FLASH_Lock();
#ifdef USE_DYNAMIC_MEM
mfree(Drv_FLASH_BUF);
#endif
如果我的地址是 0x08008000 开始, 这个是怎么个运行原理?
|
|