#include "GD25Qxx.h"
#include "SPI0.h"
#include "LED.h"
uint32_t flash_id;
uint8_t Flash_Write_Buffer[Flash_Write_Buffer_Size];
uint8_t Flash_Read_Buffer[Flash_Read_Buffer_Size];
uint8_t spi_flash_send_byte(uint8_t byte);
uint8_t spi_flash_read_byte(void);
void spi_flash_write_enable(void);
void spi_flash_wait_for_write_end(void);
void GD25Qxx_Init(void);
//函数功能:SPI0发送byte,并将读到的数据返回
uint8_t spi_flash_send_byte(uint8_t byte)
{
uint8_t ret_Data;
ret_Data=SPI0_ReadWriteByte(byte);
return(ret_Data);
}
//函数功能:SPI0发送DUMMY_BYTE,为的是读取数据,并返回读到的值
uint8_t spi_flash_read_byte(void)
{
uint8_t ret_Data;
ret_Data=SPI0_ReadWriteByte(DUMMY_BYTE);
//SPI0发送byte,并将读到的数据返回
return(ret_Data);
}
//函数功能:发送"写使能命令"
void spi_flash_write_enable(void)
{
SPI0_CS_LOW();
spi_flash_send_byte(WriteEnable_CMD);//发送"写使能命令"
SPI0_CS_HIGH();
}
//函数功能:等待空闲
void spi_flash_wait_for_write_end(void)
{
uint8_t flash_status = 0;
SPI0_CS_LOW();
spi_flash_send_byte(ReadStatusRegister1_CMD);//发送"读状态寄存器命令"
do
{
flash_status = spi_flash_send_byte(DUMMY_BYTE);
//发送DUMMY_BYTE数据为的是读取状态寄存器的值
}while( (flash_status & WIP_FLAG) == SET );
//WIP位置1,表示芯片正处于编程/擦除/写状态
SPI0_CS_HIGH();
}
//函数功能:擦除扇区,其首地址为sector_addr
void spi_flash_sector_erase(uint32_t sector_addr)
{
union GD32_UINT32_DATA_TYPE addr;
addr.Uint32_Data=sector_addr;
spi_flash_write_enable();//发送"写使能命令"
擦出扇区开始///
SPI0_CS_LOW();
spi_flash_send_byte(SectorErase_CMD); //发送扇区擦除命令
spi_flash_send_byte( addr.b[2] ); //发送扇区地址的bit16~bit23
spi_flash_send_byte( addr.b[1] ); //发送扇区地址的bit8~bit15
spi_flash_send_byte( addr.b[0] ); //发送扇区地址的bit0~bit7
SPI0_CS_HIGH();
擦出扇区结束///
spi_flash_wait_for_write_end();//等待空闲
}
//函数功能:擦除整个芯片
void spi_flash_bulk_erase(void)
{
spi_flash_write_enable();//发送"写使能命令"
SPI0_CS_LOW();
spi_flash_send_byte(ChipErase_CMD);//发送"芯片擦除命令"
SPI0_CS_HIGH();
spi_flash_wait_for_write_end();//等待空闲
}
//函数功能:将pbuffer[]中的num_byte_to_write个字节型数据写入首地址为write_addr的Flash空间
void spi_flash_page_write(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write)
{
union GD32_UINT32_DATA_TYPE addr;
addr.Uint32_Data=write_addr;
spi_flash_write_enable();//发送"写使能命令"
SPI0_CS_LOW();
spi_flash_send_byte(PageProgram_CMD);//发送"页编程命令"
spi_flash_send_byte( addr.b[2] ); //发送页地址的bit16~bit23
spi_flash_send_byte( addr.b[1] ); //发送页地址的bit8~bit15
spi_flash_send_byte( addr.b[0] ); //发送页地址的bit0~bit7
while(num_byte_to_write--)
{
spi_flash_send_byte(*pbuffer);
pbuffer++;
}
SPI0_CS_HIGH();
spi_flash_wait_for_write_end();//等待空闲
}
//函数功能:将pbuffer[num_byte_to_write]写入Flash,其首地址为write_addr
void spi_flash_buffer_write(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write)
{
uint8_t num_of_page = 0, num_of_single = 0, addr = 0, count = 0, temp = 0;
addr = write_addr % SPI_FLASH_PAGE_SIZE;
count = SPI_FLASH_PAGE_SIZE - addr; //计算当前页剩余多少个字节空间
num_of_page = num_byte_to_write / SPI_FLASH_PAGE_SIZE;//计算需要写多少页
num_of_single = num_byte_to_write % SPI_FLASH_PAGE_SIZE;//计算不满一页的字节数量
if(0 == addr)//位于页边界
{
if(0 == num_of_page)//所写字节数量不满一页,num_byte_to_write < SPI_FLASH_PAGE_SIZE
spi_flash_page_write(pbuffer,write_addr,num_byte_to_write);
else//所写字节数量超过一页,num_byte_to_write > SPI_FLASH_PAGE_SIZE
{
while(num_of_page--)
{
spi_flash_page_write(pbuffer,write_addr,SPI_FLASH_PAGE_SIZE);
write_addr += SPI_FLASH_PAGE_SIZE;
pbuffer += SPI_FLASH_PAGE_SIZE;
}
spi_flash_page_write(pbuffer,write_addr,num_of_single);
}
}
else
{
if(0 == num_of_page)//所写字节数量不满一页
{
if(num_of_single > count)//超过当前页
{
temp = num_of_single - count;//计算跨页的字节数量
spi_flash_page_write(pbuffer,write_addr,count);
write_addr += count;//修改Flash地址
pbuffer += count; //修改指针
spi_flash_page_write(pbuffer,write_addr,temp);
}
else//没有超过当前页
spi_flash_page_write(pbuffer,write_addr,num_byte_to_write);
}
else//所写字节数量超过一页
{
num_byte_to_write -= count;//计算写当前页后的剩余字节总数
num_of_page = num_byte_to_write / SPI_FLASH_PAGE_SIZE; //剩余字节总数需要多少页
num_of_single = num_byte_to_write % SPI_FLASH_PAGE_SIZE;//剩余字节总数写完整页后的剩余字节数量
spi_flash_page_write(pbuffer,write_addr, count);//向当前页写入count字节,凑成1整页
write_addr += count;//修改Flash地址
pbuffer += count; //修改指针
while(num_of_page--)
{
spi_flash_page_write(pbuffer,write_addr,SPI_FLASH_PAGE_SIZE);
write_addr += SPI_FLASH_PAGE_SIZE;//修改Flash地址
pbuffer += SPI_FLASH_PAGE_SIZE; //修改指针
}
if(0 != num_of_single)//最后写剩余的字节
spi_flash_page_write(pbuffer,write_addr,num_of_single);
}
}
}
//函数功能:从Flash中读取num_byte_to_read个字节,保存到pbuffer[]中
void spi_flash_buffer_read(uint8_t* pbuffer, uint32_t read_addr, uint16_t num_byte_to_read)
{
union GD32_UINT32_DATA_TYPE addr;
addr.Uint32_Data=read_addr;
SPI0_CS_LOW();
spi_flash_send_byte(ReadData_CMD);//读数据命令
spi_flash_send_byte( addr.b[2] );//发送地址的bit16~bit23
spi_flash_send_byte( addr.b[1] );//发送地址的bit8~bit15
spi_flash_send_byte( addr.b[0] );//发送地址的bit0~bit7
while(num_byte_to_read--)
{
*pbuffer = spi_flash_send_byte(DUMMY_BYTE);
pbuffer++;
}
SPI0_CS_HIGH();
}
//函数功能:读Flash的ID
uint32_t spi_flash_read_id(void)
{
union GD32_UINT32_DATA_TYPE ret_Data;
ret_Data.Uint32_Data=0;
SPI0_CS_LOW();
spi_flash_send_byte(ReadIdentificationCMD); //发送"读Flash的ID命令"
ret_Data.b[2]=spi_flash_send_byte(DUMMY_BYTE); //读取数据的bit16~bit23
ret_Data.b[1]=spi_flash_send_byte(DUMMY_BYTE); //读取数据的bit8~bit15
ret_Data.b[0]=spi_flash_send_byte(DUMMY_BYTE); //读取数据的bit0~bit7
SPI0_CS_HIGH();
return (ret_Data.Uint32_Data);
}
//函数功能:若src[]和dst[]的前length个字节相同,则返回1
uint8_t memory_compare(uint8_t* src, uint8_t* dst, uint16_t length)
{
while(length --)
{
if(*src++ != *dst++) return 0;
}
return 1;
}
void GD25Qxx_Init(void)
{
uint16_t i;
flash_id=0;
SPI0_Init();
LED2_Off();
flash_id = spi_flash_read_id();//读Flash的ID
if(SFLASH_ID == flash_id)
{
for(i=0; i<SPI_FLASH_PAGE_SIZE;i++)
{
Flash_Write_Buffer[i]=i;
}
spi_flash_sector_erase(0x000000);//擦除扇区,其首地址为0x000000
spi_flash_buffer_write(Flash_Write_Buffer,0x000000,SPI_FLASH_PAGE_SIZE);
//将Flash_Write_Buffer[SPI_FLASH_PAGE_SIZE]写入Flash,其首地址为0x000000
spi_flash_buffer_read(Flash_Read_Buffer,0x000000,SPI_FLASH_PAGE_SIZE);
//从Flash首地址为0x000000开始,读取SPI_FLASH_PAGE_SIZE个字节,保存到Flash_Read_Buffer[]中
i=0;
i=memory_compare(Flash_Write_Buffer,Flash_Read_Buffer,SPI_FLASH_PAGE_SIZE);
//若Flash_Write_Buffer[]和Flash_Read_Buffer[]的前SPI_FLASH_PAGE_SIZE个字节相同,则返回1
if(i) LED2_On();//读写Flash正确,则LED2灯点亮
}
} |