/***************************************************************************** ** Copyright (C) WCH 2001-2025 ** ** Web: http://wch.cn ** ****************************************************************************** Abstract: 基于SPI接口的FLASH操作函数,提供SPI FLASH 型号识别、块读、块写、块擦除等函数。 Environment: user mode only,VC6.0 and later Notes: Copyright (c) 2025 Nanjing Qinheng Microelectronics Co., Ltd. Revision History: 4/3/2022: TECH30 --*/ #include "Main.h" UINT8V Flash_Type; /* FLASH芯片类型: 0: W25XXX系列; 1: SST25XXX系列; 2: MT25QXX系列 */ UINT32V Flash_ID; extern UINT32V Flash_Sector_Count;/* FLASH芯片扇区数 */ extern UINT16V Flash_Sector_Size; /* FLASH芯片扇区大小 */ extern ULONG DevIndex; /******************************************************************************* * Function Name : FLASH_ReadID * Description : 读取FLASH芯片ID * Input : None * Output : None * Return : 返回4个字节,最高字节为0x00, * 次高字节为Manufacturer ID(0xEF), * 次低字节为Memory Type ID * 最低字节为Capacity ID * W25X40BL返回: 0xEF、0x30、0x13 * W25X10BL返回: 0xEF、0x30、0x11 *******************************************************************************/ UINT32 FLASH_ReadID( void ) { UINT32 dat=0; UCHAR oInBuffer[16] = {0}; ULONG iInLength; oInBuffer[0] = CMD_FLASH_JEDEC_ID; memset(oInBuffer+1,0xFF,3); iInLength = 3; if ( CH347SPI_WriteRead( DevIndex, 0x80, iInLength+1, oInBuffer ) == FALSE ) return( 0xFFFFFFFF ); else { oInBuffer[0] = 0; memcpy(&dat,oInBuffer,4); } //Exit: return( EndSwitch(dat) ); } /******************************************************************************* * Function Name : FLASH_ReadStatusReg * Description : FLASH芯片读取状态寄存器 * Input : None * Output : None * Return : 返回寄存器值 *******************************************************************************/ UINT8 FLASH_ReadStatusReg( void ) { UINT8 status; //PIN_FLASH_CS_LOW( ); ULONG iLen=0; UCHAR DBuf[512]={0}; DBuf[0] = CMD_FLASH_RDSR; iLen = 1; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+1, DBuf) ) return 0xFF; else status = DBuf[1]; //PIN_FLASH_CS_HIGH( ); return( status ); } /******************************************************************************* * Function Name : FLASH_WriteStatusReg * Description : FLASH芯片写状态寄存器 * Input : statusdata---所要写入的状态寄存器值 * Output : None * Return : None * 注意:写状态寄存器前,必须先发送Enable-Write-Status-Register (EWSR),命令码0X50或Write-Enable,命令码0X06 *******************************************************************************/ void FLASH_WriteStatusReg( UINT8 dat ) { ULONG iLen=0; UCHAR DBuf[128]={0}; DBuf[0] = CMD_FLASH_EWSR; iLen = 1; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen, DBuf) ) { DbgPrint(" FLASH_WriteStatusReg failure1."); return; } //PIN_FLASH_CS_LOW( ); //SPI_FLASH_SendByte( CMD_FLASH_WRSR ); //SPI_FLASH_SendByte( dat ); //PIN_FLASH_CS_HIGH( ); DBuf[0] = CMD_FLASH_WRSR;/* 发送写状态寄存器命令 */ DBuf[1] = dat;/* 发送状态寄存器数值 */ iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+2, DBuf) ) { DbgPrint(" FLASH_WriteStatusReg failure2."); return; } } /******************************************************************************* * Function Name : MT25QXX_ReadExAddrReg * Description : MT25QXXX芯片读取扩展地址寄存器 * Input : None * Output : None * Return : 返回寄存器值 *******************************************************************************/ UINT8 MT25QXXX_ReadExAddrReg( void ) { UINT8 status; ULONG iLen=0; UCHAR DBuf[128]={0}; DBuf[0] = CMD_RD_EX_ADDR_REG; iLen = 1; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+1, DBuf) ) return 0xFF; else status = DBuf[1]; return( status ); } /******************************************************************************* * Function Name : MT25QXXX_WriteExAddrReg * Description : MT25QXXX芯片写扩展地址寄存器 * Input : dat---所要写入的寄存器值 * Output : None * Return : None *******************************************************************************/ BOOL MT25QXXX_WriteExAddrReg( UINT8 dat ) { ULONG iLen=0; UCHAR DBuf[128]={0}; DBuf[0] = CMD_FLASH_WREN; iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+1, DBuf) ) return FALSE; DBuf[0] = CMD_WR_EX_ADDR_REG; DBuf[1] = dat; iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+2, DBuf) ) return FALSE; else return TRUE; } /******************************************************************************* * Function Name : MT25QXXX_ChangeExAddrReg * Description : MT25QXXX芯片改变扩展地址寄存器 * Input : dat---所要写入的寄存器值 * Output : None * Return : None *******************************************************************************/ void MT25QXXX_ChangeExAddrReg( UINT8 dat ) { UINT8 ex_addr; ex_addr = MT25QXXX_ReadExAddrReg( ); if( ex_addr != dat ) { MT25QXXX_WriteExAddrReg( dat ); } } /******************************************************************************* * Function Name : FLASH_IC_Check * Description : FLASH芯片检测 * Input : None * Output : None * Return : None *******************************************************************************/ BOOL FLASH_IC_Check( void ) { UINT32 count; UINT8 temp8; CHAR FlashID[128]=""; BOOL RetVal = FALSE; Flash_ID = 0; /* 读取FLASH芯片ID号 */ Flash_ID = FLASH_ReadID( ); /* 获取FLASH的ID号 */ /* 获取FLASH的ID号 */ DbgPrint(" Flash_ID: %X\n",Flash_ID); /* 根据芯片型号,判断容量大小 */ Flash_Type = 0x00; Flash_Sector_Count = 0x00; /* FLASH芯片扇区数 */ Flash_Sector_Size = 0x00; /* FLASH芯片扇区大小 */ #if 1 switch( Flash_ID ) { /**************************************************************************/ /* W25XXX系列芯片 */ case W25X10_FLASH_ID: /* 0xEF3011-----1M bit */ strcpy(FlashID,"W25X10_FLASH_ID"); count = 1; break; case W25X20_FLASH_ID: /* 0xEF3012-----2M bit */ strcpy(FlashID,"W25X20_FLASH_ID"); count = 2; break; case W25X40_FLASH_ID: /* 0xEF3013-----4M bit */ strcpy(FlashID,"W25X40_FLASH_ID"); count = 4; break; case W25X80_FLASH_ID: /* 0xEF4014-----8M bit */ strcpy(FlashID,"W25X80_FLASH_ID"); count = 8; break; case W25Q16_FLASH_ID1: /* 0xEF3015-----16M bit */ case W25Q16_FLASH_ID2: /* 0xEF4015-----16M bit */ strcpy(FlashID,"W25Q16_FLASH_ID1/2"); count = 16; break; case W25Q32_FLASH_ID1: /* 0xEF4016-----32M bit */ case W25Q32_FLASH_ID2: /* 0xEF6016-----32M bit */ strcpy(FlashID,"W25Q32_FLASH_ID1/2"); count = 32; break; case W25Q64_FLASH_ID1: /* 0xEF4017-----64M bit */ case W25Q64_FLASH_ID2: /* 0xEF6017-----64M bit */ strcpy(FlashID,"W25Q64_FLASH_ID1/2"); count = 64; break; case W25Q128_FLASH_ID1: /* 0xEF4018-----128M bit */ case W25Q128_FLASH_ID2: /* 0xEF6018-----128M bit */ strcpy(FlashID,"W25Q128_FLASH_ID1/2"); count = 128; break; case W25Q256_FLASH_ID1: /* 0xEF4019-----256M bit */ case W25Q256_FLASH_ID2: /* 0xEF6019-----256M bit */ strcpy(FlashID,"W25Q256_FLASH_ID1/2"); count = 256; break; /**************************************************************************/ /* SST25XXX系列芯片 */ case SST25VF040_FLASH_ID: /* 0xBF258D-----4M bit */ count = 4; Flash_Type = DEF_TYPE_SST25XXX; strcpy(FlashID,"SST25VF040_FLASH_ID"); break; case SST25VF080_FLASH_ID: /* 0xBF258E-----8M bit */ count = 8; Flash_Type = DEF_TYPE_SST25XXX; /* FLASH芯片类型: 0: W25系列; 1: SST系列 */ strcpy(FlashID,"SST25VF080_FLASH_ID"); break; case SST25VF016_FLASH_ID: /* 0xBF254A-----16M bit */ count = 16; Flash_Type = DEF_TYPE_SST25XXX; /* FLASH芯片类型: 0: W25系列; 1: SST系列 */ strcpy(FlashID,"SST25VF016_FLASH_ID"); break; case SST25VF032_FLASH_ID: /* 0xBF254A-----32M bit */ count = 32; Flash_Type = DEF_TYPE_SST25XXX; /* FLASH芯片类型: 0: W25系列; 1: SST系列 */ strcpy(FlashID,"SST25VF032_FLASH_ID"); break; case SST25VF064_FLASH_ID: /* 0xBF254B-----64M bit */ count = 64; Flash_Type = DEF_TYPE_SST25XXX; /* FLASH芯片类型: 0: W25系列; 1: SST系列 */ strcpy(FlashID,"SST25VF064_FLASH_ID"); break; /**************************************************************************/ /* M25PXXX系列 */ case M25P40_FLASH_ID: /* 4M bit */ count = 4; Flash_Type = DEF_TYPE_M25PXXX; strcpy(FlashID,"M25P40_FLASH_ID"); break; case M25P80_FLASH_ID: /* 8M bit */ count = 8; Flash_Type = DEF_TYPE_M25PXXX; strcpy(FlashID,"M25P80_FLASH_ID"); break; case M25P16_FLASH_ID: /* 16M bit */ count = 16; Flash_Type = DEF_TYPE_M25PXXX; strcpy(FlashID,"M25P16_FLASH_ID"); break; case M25P32_FLASH_ID: /* 32M bit */ count = 32; Flash_Type = DEF_TYPE_M25PXXX; strcpy(FlashID,"M25P32_FLASH_ID"); break; case M25P64_FLASH_ID: /* 64M bit */ count = 64; Flash_Type = DEF_TYPE_M25PXXX; strcpy(FlashID,"M25P64_FLASH_ID"); break; /**************************************************************************/ /* MX25LXXX系列 */ case MX25L40_FLASH_ID: /* 4M bit */ count = 4; Flash_Type = DEF_TYPE_MX25LXXX; strcpy(FlashID,"MX25L40_FLASH_ID"); break; case MX25L80_FLASH_ID: /* 8M bit */ count = 8; Flash_Type = DEF_TYPE_MX25LXXX; strcpy(FlashID,"MX25L80_FLASH_ID"); break; case MX25L16_FLASH_ID: /* 16M bit */ count = 16; Flash_Type = DEF_TYPE_MX25LXXX; strcpy(FlashID,"MX25L16_FLASH_ID"); break; case MX25L32_FLASH_ID: /* 32M bit */ count = 32; Flash_Type = DEF_TYPE_MX25LXXX; strcpy(FlashID,"MX25L32_FLASH_ID"); break; case MX25L64_FLASH_ID: /* 64M bit */ count = 64; Flash_Type = DEF_TYPE_MX25LXXX; strcpy(FlashID,"MX25L64_FLASH_ID"); break; /**************************************************************************/ /* MT25QXX系列芯片 */ case MT25Q_FLASH_64Mb: /* 0x20BA17-----64M bit */ count = 64; Flash_Type = DEF_TYPE_MT25QXXX; strcpy(FlashID,"MT25Q_FLASH_64Mb"); break; case MT25Q_FLASH_128Mb: /* 0x20BA18-----128M bit */ count = 128; Flash_Type = DEF_TYPE_MT25QXXX; strcpy(FlashID,"MT25Q_FLASH_128Mb"); break; case MT25Q_FLASH_256Mb: /* 0x20BA19-----256M bit */ count = 256; Flash_Type = DEF_TYPE_MT25QXXX; strcpy(FlashID,"MT25Q_FLASH_256Mb"); break; case MT25Q_FLASH_512Mb: /* 0x20BA20-----512M bit */ count = 512; Flash_Type = DEF_TYPE_MT25QXXX; strcpy(FlashID,"MT25Q_FLASH_512Mb"); break; case MT25Q_FLASH_1024Mb: /* 0x20BA21-----1G bit */ count = 1024; Flash_Type = DEF_TYPE_MT25QXXX; strcpy(FlashID,"MT25Q_FLASH_1024Mb"); break; case MT25Q_FLASH_2048Mb: /* 0x20BA22-----2G bit */ count = 2048; Flash_Type = DEF_TYPE_MT25QXXX; strcpy(FlashID,"MT25Q_FLASH_2048Mb"); break; default: strcpy(FlashID,"Unknonw flash type"); if( ( Flash_ID != 0xFFFFFFFF ) || ( Flash_ID != 0x00000000 ) ) { count = 16; } else { count = 0x00; } break; } count = ( (UINT32)count * 1024 ) * ( (UINT32)1024 / 8 ); #endif #if 0 if( ( Flash_ID != 0xFFFFFFFF ) || ( Flash_ID != 0x00000000 ) ) { count = 8; } else { count = 0x00; } count = ( (UINT32)count * 1024 ) * ( (UINT32)1024 / 8 ); #endif /* 根据不同类型芯片进行特殊处理 */ if( Flash_Type == DEF_TYPE_SST25XXX ) { temp8 = FLASH_ReadStatusReg( ); FLASH_WriteStatusReg( 0x00 ); /* 清状态寄存器中的位:BP0、BP1、BP2,允许FLASH进行擦除、写操作 */ temp8 = FLASH_ReadStatusReg( ); } /* 保存FLASH芯片扇区数目,扇区大小等信息 */ if( count ) { Flash_Sector_Count = count / SPI_FLASH_SectorSize;//DEF_UDISK_SECTOR_SIZE; /* FLASH芯片扇区数 */ Flash_Sector_Size = SPI_FLASH_SectorSize;//DEF_UDISK_SECTOR_SIZE; /* FLASH芯片扇区大小 */ } DbgPrint(" FlashID:%s(%X),Cap:%dMbit,%dB*%d", FlashID,Flash_ID, Flash_Sector_Count*Flash_Sector_Size/1024/1024*8,Flash_Sector_Size,Flash_Sector_Count); RetVal = TRUE; return RetVal; } /******************************************************************************* * Function Name : FLASH_WriteEnable * Description : FLASH芯片允许写操作 * Input : None * Output : None * Return : None *******************************************************************************/ BOOL FLASH_WriteEnable( void ) { //PIN_FLASH_CS_LOW( ); //SPI_FLASH_SendByte( CMD_FLASH_WREN ); /* 发送允许写操作命令 */ //PIN_FLASH_CS_HIGH( ); ULONG iLen=0; UCHAR DBuf[128]={0}; DBuf[0] = CMD_FLASH_WREN; iLen = 0; return CH347SPI_WriteRead( DevIndex, 0x80, iLen+1, DBuf); } /******************************************************************************* * Function Name : FLASH_WriteDisable * Description : FLASH芯片禁止写操作 * Input : None * Output : None * Return : None *******************************************************************************/ BOOL FLASH_WriteDisable( void ) { //PIN_FLASH_CS_LOW( ); //SPI_FLASH_SendByte( CMD_FLASH_WRDI ); /* 发送禁止写操作命令 */ //PIN_FLASH_CS_HIGH( ); ULONG iLen=0; UCHAR DBuf[128]={0}; DBuf[0] = CMD_FLASH_WRDI; iLen = 0; return CH347SPI_WriteRead( DevIndex, 0x80, iLen+1, DBuf); } /******************************************************************************* * Function Name : W25XXX_WR_Page * Description : 写入一块数据 * 注:当前程序不支持跨页写数据 * Input : address----准备写的首地址 * len--------准备写的数据长度 * *pbuf------准备写入的缓冲区地址 * Output : None * Return : None *******************************************************************************/ BOOL W25XXX_WR_Page( UINT8 *pbuf, UINT32 address, UINT32 len ) { UINT8 temp; /* 写之前必须先打开写使能,且必须写在擦除过的地址处 */ FLASH_WriteEnable( ); /* 打开写使能 */ /* 判断如果是MT25QXXX芯片则需要判断地址最高字节,当前操作的是哪个大块 */ if( Flash_Type == DEF_TYPE_MT25QXXX ) { MT25QXXX_ChangeExAddrReg( (UINT8)( address >> 24 ) ); } /* 开始写入数据 */ if( len > SPI_FLASH_PerWritePageSize ) /* 限定长度 */ { len = SPI_FLASH_PerWritePageSize; } /* Deselect the FLASH: Chip Select high */ ULONG iLen=0,Timeout=0; UCHAR DBuf[8192]={0}; if(len>sizeof(DBuf)) { DbgPrint(" W25XXX_WR_Page操作长度不能操作%d",len); return FALSE; } DBuf[0] = CMD_FLASH_BYTE_PROG; DBuf[1] = (UINT8)( address >> 16 ); DBuf[2] = (UINT8)( address >> 8 ); DBuf[3] = (UINT8)address; memcpy(&DBuf[4],pbuf,len); iLen = 4; if( !CH347SPI_Write(DevIndex,0x80,iLen+len,SPI_FLASH_PerWritePageSize+4,DBuf)) { DbgPrint(" W25XXX_WR_Page[%X]>>CH347SPI_WriteRead failure.",address); return FALSE; } Timeout = 0; /* Wait the end of Flash writing */ do { temp = FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(5); Timeout += 5; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" W25XXX_WR_Page>FLASH_ReadStatusReg timeout"); return FALSE; } }while( temp & 0x01 ); /* 等待当前操作执行完成 */ return TRUE; } /******************************************************************************* * Function Name : SST25XXX_WriteBlock * Description : 块方式写(快速方式) * 注意: 对于不同的芯片,本函数可能不适用.比如SST25VF512B,操作方式不一样 * Input : address---准备写的首地址 * length----准备写的数据长度 * *pbuf-----准备写入的缓冲区地址 * Output : None * Return : None 速度测试:写512字节需要大概3MS 写4K大概需要24.5MS *******************************************************************************/ BOOL SST25XXX_WriteBlock( UINT32 address, UINT32 length, UINT8 *pbuf ) { UINT8 temp; UINT32 i; ULONG iLen=0,Timeout; UCHAR DBuf[4096]={0}; /* 写之前必须先打开写使能,且必须写在擦除过的地址处 */ FLASH_WriteEnable( ); /* 打开写使能 */ /* 采用Auto Address Increment (AAI) Program方式,进行写操作 */ DBuf[0] = CMD_FLASH_AAI_WORD_PROG; DBuf[1] = (UINT8)( address >> 16 ); DBuf[2] = (UINT8)( address >> 8 ); DBuf[3] = (UINT8) address; memcpy(&DBuf[4],pbuf,2); iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+4+2, DBuf) ) { DbgPrint(" SST25XXX_WriteBlock>>CH347SPI_WriteRead-1 failure."); return FALSE; } Timeout = 0; do { temp=FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(0); Timeout += 1; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" SST25XXX_WriteBlock>FLASH_ReadStatusReg1 timeout"); return FALSE; } }while( temp & 0X01 ); /* 等待当前操作执行完成 */ for( i = 2; i < length; i = i + 2 ) /* 发送后续数据 */ { DBuf[0] = CMD_FLASH_AAI_WORD_PROG; /* 发送写数据命令 */ memcpy(&DBuf[1],&pbuf[i],2); iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+3, DBuf) ) { DbgPrint(" SST25XXX_WriteBlock>>CH347SPI_WriteRead-2 failure."); return FALSE; } /* 等待操作结束 */ Timeout = 0; do { temp = FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(0); Timeout += 1; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" SST25XXX_WriteBlock>FLASH_ReadStatusReg2 timeout"); return FALSE; } }while( temp & 0X01 ); /* 等待当前操作执行完成 */ } /* 写完毕之后,关闭写使能退出AAI模式 */ FLASH_WriteDisable( ); /* 关闭写使能 */ Timeout = 0; do { temp = FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(0); Timeout += 1; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" SST25XXX_WriteBlock>FLASH_ReadStatusReg3 timeout"); return FALSE; } }while( temp & 0X01 ); /* 等待当前操作执行完成 */ return TRUE; } /******************************************************************************* * Function Name : W25XXX_WR_Block * Description : 写入一块数据 * Input : address----准备写的首地址 * len--------准备写的数据长度 * *pbuf------准备写入的缓冲区地址 * Output : None * Return : None *******************************************************************************/ UINT32 W25XXX_WR_Block( UINT8 *pbuf, UINT32 address, UINT32 len ) { UINT32 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0; Addr = address % SPI_FLASH_PageSize; count = SPI_FLASH_PageSize - Addr; NumOfPage = len / SPI_FLASH_PageSize; NumOfSingle = len % SPI_FLASH_PageSize; if( Addr == 0 ) /* WriteAddr is SPI_FLASH_PageSize aligned */ { if( NumOfPage == 0 ) /* NumByteToWrite < SPI_FLASH_PageSize */ { W25XXX_WR_Page( pbuf, address, len ); } else /* NumByteToWrite > SPI_FLASH_PageSize */ { while( NumOfPage-- ) { W25XXX_WR_Page( pbuf, address, SPI_FLASH_PageSize ); address += SPI_FLASH_PageSize; pbuf += SPI_FLASH_PageSize; } if(NumOfSingle) W25XXX_WR_Page( pbuf, address, NumOfSingle ); } } else /* WriteAddr is not SPI_FLASH_PageSize aligned */ { if( NumOfPage == 0 ) /* NumByteToWrite < SPI_FLASH_PageSize */ { if( NumOfSingle > count ) /* (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */ { temp = NumOfSingle - count; W25XXX_WR_Page( pbuf, address, count ); address += count; pbuf += count; W25XXX_WR_Page( pbuf, address, temp ); } else { W25XXX_WR_Page( pbuf, address, len ); } } else/* NumByteToWrite > SPI_FLASH_PageSize */ { len -= count; NumOfPage = len / SPI_FLASH_PageSize; NumOfSingle = len % SPI_FLASH_PageSize; W25XXX_WR_Page( pbuf, address, count ); address += count; pbuf += count; while( NumOfPage-- ) { W25XXX_WR_Page( pbuf, address, SPI_FLASH_PageSize ); address += SPI_FLASH_PageSize; pbuf += SPI_FLASH_PageSize; } if( NumOfSingle != 0 ) { W25XXX_WR_Page( pbuf, address, NumOfSingle ); } } } return len; } /******************************************************************************* * Function Name : FLASH_RD_Block * Description : FLASH块数据读取 * Input : None * Output : None * Return : None *******************************************************************************/ UINT32 FLASH_RD_Block( UINT32 address,UINT8 *pbuf,UINT32 len ) { /* W25系列FLASH、SST系列FLASH */ ULONG iLen=0; UCHAR DBuf[8192]={0}; DBuf[0] = CMD_FLASH_READ; DBuf[1] = (UINT8)( address >> 16 ); DBuf[2] = (UINT8)( address >> 8 ); DBuf[3] = (UINT8)( address ); iLen = len; if( !CH347SPI_Read(DevIndex,0x80,4,&iLen,DBuf) ) { //DbgPrint(" FLASH_RD_Block %d bytes failure."); return 0; } else { memcpy(pbuf,DBuf,len); return len; } } BOOL FLASH_Erase_Sector( UINT32 address ) /* FLASH扇区擦除 */ { UINT8 temp; ULONG iLen=0,Timeout =0; UCHAR DBuf[8192]={0}; /* 擦除之前,必须进行写使能操作 */ FLASH_WriteEnable( ); /* 打开写使能 */ /* 判断如果是MT25QXXX芯片则需要判断地址最高字节,当前操作的是哪个大块 */ if( Flash_Type == DEF_TYPE_MT25QXXX ) { MT25QXXX_ChangeExAddrReg( (UINT8)( address >> 24 ) ); } /* 进行FLASH擦除 */ //PIN_FLASH_CS_LOW( ); if( Flash_Type == DEF_TYPE_M25PXXX ) { //SPI_FLASH_SendByte( CMD_M25PXX_SECTOR_ERASE ); DBuf[0] = CMD_M25PXX_SECTOR_ERASE; } else { DBuf[0] = CMD_FLASH_SECTOR_ERASE; } DBuf[1] = (UINT8)( address >> 16 ); /* 发送三个字节需要读取数据的地址 */ DBuf[2] = (UINT8)( address >> 8 ); /* 数据地址次字节 */ DBuf[3] = (UINT8)address; /* 数据地址最低字节 */ iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+4, DBuf) ) { DbgPrint(" FLASH_Erase_Sector>>CH347SPI_WriteRead failure."); return FALSE; } /* 等待操作结束 */ do { temp = FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(30); Timeout += 30; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" FLASH_Erase_Sector>FLASH_ReadStatusReg timeout"); return FALSE; } }while( temp & 0x01 ); return TRUE; } BOOL FLASH_Erase_Block( UINT32 address ) /* FLASH扇区擦除 */ { UINT8 temp; ULONG iLen=0,Timeout =0; UCHAR DBuf[8192]={0}; /* 擦除之前,必须进行写使能操作 */ FLASH_WriteEnable( ); /* 打开写使能 */ /* 判断如果是MT25QXXX芯片则需要判断地址最高字节,当前操作的是哪个大块 */ if( Flash_Type == DEF_TYPE_MT25QXXX ) { MT25QXXX_ChangeExAddrReg( (UINT8)( address >> 24 ) ); } /* 进行FLASH擦除 */ //PIN_FLASH_CS_LOW( ); if( Flash_Type == DEF_TYPE_M25PXXX ) { //SPI_FLASH_SendByte( CMD_M25PXX_SECTOR_ERASE ); DBuf[0] = CMD_M25PXX_SECTOR_ERASE; } else { //SPI_FLASH_SendByte( CMD_FLASH_SECTOR_ERASE ); DBuf[0] = CMD_FLASH_BLOCK_ERASE1;/* 发送4-KByte Sector-Erase命令 */ } DBuf[1] = (UINT8)( address >> 16 );/* 发送三个字节需要读取数据的地址 */ DBuf[2] = (UINT8)( address >> 8 );/* 数据地址次字节 */ DBuf[3] = (UINT8)address;/* 数据地址最低字节 */ iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+4, DBuf) ) { DbgPrint(" FLASH_Erase_Block>>CH347SPI_WriteRead failure."); return FALSE; } /* 等待操作结束 */ do { temp = FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(10); Timeout += 10; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" FLASH_Erase_Block>FLASH_ReadStatusReg timeout"); return FALSE; } }while( temp & 0x01 ); return TRUE; } BOOL FLASH_Erase_Full() /* FLASH全片擦除 */ { UINT8 temp; ULONG iLen=0,Timeout =0; UCHAR DBuf[8192]={0}; /* 擦除之前,必须进行写使能操作 */ FLASH_WriteEnable( ); /* 打开写使能 */ //SPI_FLASH_SendByte( CMD_FLASH_SECTOR_ERASE ); /* 发送4-KByte Sector-Erase命令 */ DBuf[0] = CMD_FLASH_CHIP_ERASE1; iLen = 0; if( !CH347SPI_WriteRead( DevIndex, 0x80, iLen+1, DBuf) ) { DbgPrint(" FLASH_Erase_Block>>CH347SPI_WriteRead failure."); return FALSE; } /* 等待操作结束 */ do { temp = FLASH_ReadStatusReg( ); if( (temp & 0x01)<1) break; Sleep(10); Timeout += 10; if(Timeout > FLASH_OP_TIMEOUT*20) { DbgPrint(" FLASH_Erase_Block>FLASH_ReadStatusReg timeout"); return FALSE; } }while( temp & 0x01 ); return TRUE; } UINT32 FLASH_WR_Block( UINT32 address, UINT8 *pbuf, UINT32 len ) /* FLASH块数据写入 */ { /* W25系列FLASH、SST系列FLASH */ if( Flash_Type == DEF_TYPE_W25XXX ) { return W25XXX_WR_Block( pbuf, address, len ); } else if( Flash_Type == DEF_TYPE_SST25XXX ) { return SST25XXX_WriteBlock( address, len, pbuf ); } else { return W25XXX_WR_Block( pbuf, address, len ); } return 0; }