#define W25Q64_PAGE_SIZE FLASH_PAGE_SIZE // 一个page 256 (Byte)
#define W25Q64_SECTOR_SIZE (W25Q64_PAGE_SIZE*16) // 16个page组成一个sector: PAGE * 16 = 4K (Byte) //擦除的最小操作单元
#define W25Q64_BLOCK_SIZE (W25Q64_SECTOR_SIZE*16) // 16个sector组成一个block: SECTOR * 16 = 64K (Byte)
#define W25Q64_CHIP_SIZE (W25Q64_BLOCK_SIZE*128) // 128个block组成整个flash空间: BLOCK * 128 = 8M
/**************************************************************
*功能:写数据到外部flash
*输入:u32Address要写的地址,
pBuf要写入的数据,
u32NbrToWrite要写的字节数
*输出:
*条件:要写入的数据不能为空
*返回:成功:写入的字节数
失败:0
注意: 按一页写SPI flash
***************************************************************/
static T_U32 _SPIFlash_Write(T_U32 u32Address, T_U8 *pBuf, T_U32 u32NbrToWrite)
{
T_U32 iNumByteToWrite = u32NbrToWrite, u32CountByte=0;
T_U32 u32SectorPos = 0;
T_U32 u32PagePos = 0;
T_U32 u32PageOff = 0;
T_U32 u32PageRemain = 0;
T_U32 u32PageAddr = 0;
T_U32 i = 0, j = 0;
T_S8 s8Buf[W25Q64_PAGE_SIZE] = {0};
ASSERT_EQUAL_RETVAL(pBuf, T_NULL, 0);
while(1)
{
/* 计算一些地址和关键值 */
// 一个page:256byte
// 一个 sector:4kByte 是擦除的最小单元
u32SectorPos = u32Address & (~(W25Q64_SECTOR_SIZE - 1)); //Sector地址
u32PagePos = u32Address & (~(W25Q64_PAGE_SIZE - 1)); //page地址 //page的地址 取256的整数倍
u32PageOff = u32Address & (W25Q64_PAGE_SIZE - 1); //在page内的偏移 取2048的余数
u32PageRemain = W25Q64_PAGE_SIZE - u32PageOff; //page剩余空间大小
if(iNumByteToWrite <= u32PageRemain)
{
u32PageRemain = iNumByteToWrite;
}
/* 读出对应扇区全部数据存到缓冲区*/
_SPIFlash_SectorErase((T_U32)FLASH_CACHE_START); //擦除1个扇区4k
for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
{
memset(s8Buf, 0, W25Q64_PAGE_SIZE);
_SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
_SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);
}
_SPIFlash_SectorErase(u32SectorPos); //擦除要写数据区4K
/* 从缓冲区读出数据修改对应位置后写入对应扇区 */
for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
{
u32PageAddr = u32SectorPos + i*W25Q64_PAGE_SIZE;
memset(s8Buf, 0, W25Q64_PAGE_SIZE);
_SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);
if(u32PageAddr == u32PagePos)
{
u32CountByte += u32PageRemain;
for(j=0; j<u32PageRemain; j++)
{ //复制
s8Buf[j+u32PageOff] = pBuf[j];
}
if(iNumByteToWrite != u32PageRemain)
{
u32PagePos += W25Q64_PAGE_SIZE;
u32PageOff = 0; //偏移位置为0
pBuf += u32PageRemain; //指针偏移
u32Address += u32PageRemain; //写地址偏移
iNumByteToWrite -= u32PageRemain; //字节数递减
if(iNumByteToWrite > W25Q64_PAGE_SIZE)
{
u32PageRemain = W25Q64_PAGE_SIZE; //下一个扇区还是写不完
}else
{
u32PageRemain = iNumByteToWrite; //下一个扇区可以写完了
}
}
}
_SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
}
//跨扇区写
while(u32CountByte != u32NbrToWrite)
{
u32SectorPos = u32SectorPos+ W25Q64_SECTOR_SIZE; //地址偏移到下一个扇区
/* 读出对应扇区全部数据存到缓冲区*/
_SPIFlash_SectorErase((T_U32)FLASH_CACHE_START); //擦除1个扇区4k
for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
{
memset(s8Buf, 0, W25Q64_PAGE_SIZE);
_SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
_SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);
}
//擦掉下一个扇区4k
_SPIFlash_SectorErase(u32SectorPos);
for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
{
memset(s8Buf, 0, W25Q64_PAGE_SIZE);
_SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);
u32PageAddr = u32SectorPos + i*W25Q64_PAGE_SIZE;
if(u32PageAddr == u32PagePos)
{
u32CountByte += u32PageRemain;
for(j=0; j<u32PageRemain; j++)
{ //复制
s8Buf[j+u32PageOff] = pBuf[j];
}
if(iNumByteToWrite != u32PageRemain)
{
u32PagePos += W25Q64_PAGE_SIZE;
u32PageOff = 0; //偏移位置为0
pBuf += u32PageRemain; //指针偏移
u32Address += u32PageRemain; //写地址偏移
iNumByteToWrite -= u32PageRemain; //字节数递减
if(iNumByteToWrite > W25Q64_PAGE_SIZE)
{
u32PageRemain = W25Q64_PAGE_SIZE; //下一个扇区还是写不完
}else
{
u32PageRemain = iNumByteToWrite; //下一个扇区可以写完了
}
}
}
_SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
}
}
if(u32CountByte == u32NbrToWrite) //
{
break;
}
}
return u32NbrToWrite;
}