#include "McuW25Q64JvssiqDrv.h" /* 关于flash操作的主体寄存器地址 */ #define DEVICE_ID_CMD 0x90 // 设备ID #define WRITE_ENBALE_CMD 0x06 // 写使能 #define WRITE_DISABLE_CMD 0x04 // 写失能 #define PAGE_PROGRAM_CMD 0x02 // 数据写入 #define DEVICE_ID_CMD 0x90 // 设备ID #define READ_DATA_CMD 0x03 // 读取数据 #define READ_STA1_CMD 0x05 // 读寄存器状态1 //#define READ_STA2_CMD 0x35 // 读寄存器状态2,该状态寄存器暂时不使用 #define SECTOR_ERASE_CMD 0x20 // 4KB擦除 //#define BLOCK_ERASE_32_CMD 0x52 // 32KB擦除 #define BLOCK_ERASE_64_CMD 0xD8 // 64KB擦除 #define CHIP_ERASE_CMD 0xC7 // 整片擦除 #define POWERDOWN_CMD 0xB9 // 低功耗 #define WAKEUP_CMD 0xAB // 唤醒 #define FLASH_CS_HIGH 1 #define FLASH_CS_LOW 0 static void W25Q64_WriteEnable(W25Q64JVSSIQ_OBJ * FlashObj); static unsigned short W25Q64_ReadId(W25Q64JVSSIQ_OBJ * FlashObj); //static void W25Q64_WriteDisable(W25Q64JVSSIQ_OBJ * FlashObj); static unsigned char W25Q64_ReadStaReg(W25Q64JVSSIQ_OBJ * FlashObj); static void W25Q64_WaitNoBusy(W25Q64JVSSIQ_OBJ * FlashObj); /* 初始化FLASH */ int W25Q64_Init(W25Q64JVSSIQ_OBJ * FlashObj) { if (0xef16 != W25Q64_ReadId(FlashObj)) { //华邦电子的代号0xef,W25Q64的ID代号0x16 return -1; } return 0; } /* 读取Flash上的部分数据 */ int W25Q64_ReadBytes(W25Q64JVSSIQ_OBJ * FlashObj, unsigned int Raddr, unsigned char *Rbuf, unsigned int RbufLen) { int i = 0; unsigned char AddrBuf[3] = {0}; if ((Rbuf == NULL) && ((W25Q64_FLASH_SIZE - Raddr) < RbufLen)) { return -1; } AddrBuf[0] = (Raddr & 0x00ff0000) >> 16; AddrBuf[1] = (Raddr & 0x0000ff00) >> 8; AddrBuf[2] = Raddr & 0x000000ff; W25Q64_WaitNoBusy(FlashObj); FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(READ_DATA_CMD); FlashObj->SpiWriteReadByte(AddrBuf[0]); FlashObj->SpiWriteReadByte(AddrBuf[1]); FlashObj->SpiWriteReadByte(AddrBuf[2]); for (i = 0; i < RbufLen; i++) { Rbuf[i] = FlashObj->SpiWriteReadByte(0xff); } FlashObj->SpiCs(FLASH_CS_HIGH); return 0; } int W25Q64_WriteBytes(W25Q64JVSSIQ_OBJ * FlashObj, unsigned int Waddr, unsigned char *Wbuf, unsigned int WbufLen) { int i; unsigned char AddrBuf[3] = {0}; if ((Wbuf == NULL) && ((W25Q64_FLASH_SIZE - Waddr) < WbufLen)) { return -1; } for (i = 0; i < WbufLen; i++) { if ((Waddr + i) % 4096 == 0) { W25Q64_EraseSector(FlashObj, (Waddr + i) / 4096); } if ((i == 0) || (((Waddr + i) % 256) == 0)) { AddrBuf[0] = ((Waddr + i) & 0x00ff0000) >> 16; AddrBuf[1] = ((Waddr + i) & 0x0000ff00) >> 8; AddrBuf[2] = (Waddr + i) & 0x000000ff; W25Q64_WriteEnable(FlashObj); W25Q64_WaitNoBusy(FlashObj); FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(PAGE_PROGRAM_CMD); FlashObj->SpiWriteReadByte(AddrBuf[0]); FlashObj->SpiWriteReadByte(AddrBuf[1]); FlashObj->SpiWriteReadByte(AddrBuf[2]); } FlashObj->SpiWriteReadByte(Wbuf[i]); if ((((Waddr + i) % 256) == 255) || (i == (WbufLen - 1))) { FlashObj->SpiCs(FLASH_CS_HIGH); W25Q64_WaitNoBusy(FlashObj); } } return 0; } /* 清除块数据 */ int W25Q64_EraseBlock(W25Q64JVSSIQ_OBJ * FlashObj, unsigned int BlockAddr) { unsigned char AddrBuf[3] = {0}; if (BlockAddr >= W25Q64_FLASH_BLOCK_NUM) { return -1; } BlockAddr *= 65536; AddrBuf[0] = (BlockAddr & 0x00ff0000) >> 16; AddrBuf[1] = (BlockAddr & 0x0000ff00) >> 8; AddrBuf[2] = BlockAddr & 0x000000ff; W25Q64_WriteEnable(FlashObj); W25Q64_WaitNoBusy(FlashObj); FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(BLOCK_ERASE_64_CMD); FlashObj->SpiWriteReadByte(AddrBuf[0]); FlashObj->SpiWriteReadByte(AddrBuf[1]); FlashObj->SpiWriteReadByte(AddrBuf[2]); FlashObj->SpiCs(FLASH_CS_HIGH); W25Q64_WaitNoBusy(FlashObj); return 0; } /* 清除扇区数据 */ int W25Q64_EraseSector(W25Q64JVSSIQ_OBJ * FlashObj, unsigned int SectorAddr) { unsigned char AddrBuf[3] = {0}; if (SectorAddr >= W25Q64_FLASH_SECTOR_NUM) { return -1; } SectorAddr *= 4096; AddrBuf[0] = (SectorAddr & 0x00ff0000) >> 16; AddrBuf[1] = (SectorAddr & 0x0000ff00) >> 8; AddrBuf[2] = SectorAddr & 0x000000ff; W25Q64_WriteEnable(FlashObj); W25Q64_WaitNoBusy(FlashObj); FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(SECTOR_ERASE_CMD); FlashObj->SpiWriteReadByte(AddrBuf[0]); FlashObj->SpiWriteReadByte(AddrBuf[1]); FlashObj->SpiWriteReadByte(AddrBuf[2]); FlashObj->SpiCs(FLASH_CS_HIGH); W25Q64_WaitNoBusy(FlashObj); return 0; } /* 清除FLASH数据 */ void W25Q64_EraseChip(W25Q64JVSSIQ_OBJ * FlashObj) { W25Q64_WriteEnable(FlashObj); W25Q64_WaitNoBusy(FlashObj); FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(CHIP_ERASE_CMD); FlashObj->SpiCs(FLASH_CS_HIGH); W25Q64_WaitNoBusy(FlashObj); } /* 进入低功耗 */ void W25Q64_PowerDown(W25Q64JVSSIQ_OBJ * FlashObj) { FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(POWERDOWN_CMD); FlashObj->SpiCs(FLASH_CS_HIGH); FlashObj->DelayUs(3); } /* 唤醒 */ void W25Q64_WakeUp(W25Q64JVSSIQ_OBJ * FlashObj) { FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(WAKEUP_CMD); FlashObj->SpiCs(FLASH_CS_HIGH); FlashObj->DelayUs(3); } /* FLASH读取Flash内部的ID */ static unsigned short W25Q64_ReadId(W25Q64JVSSIQ_OBJ * FlashObj) { unsigned short DeviceID; FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(DEVICE_ID_CMD); FlashObj->SpiWriteReadByte(0); FlashObj->SpiWriteReadByte(0); FlashObj->SpiWriteReadByte(0); DeviceID = FlashObj->SpiWriteReadByte(0xff); // 提供时序 DeviceID <<= 8; DeviceID |= FlashObj->SpiWriteReadByte(0xff); // 提供时序 FlashObj->SpiCs(FLASH_CS_HIGH); return DeviceID; } /* FLASH写使能 */ static void W25Q64_WriteEnable(W25Q64JVSSIQ_OBJ * FlashObj) { FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(WRITE_ENBALE_CMD); FlashObj->SpiCs(FLASH_CS_HIGH); } /* Flash写失能,由于手册中写明写完会自动进入写失能 */ //static void W25Q64_WriteDisable(W25Q64JVSSIQ_OBJ * FlashObj) //{ // FlashObj->SpiCs(FLASH_CS_LOW); // FlashObj->SpiWriteReadByte(WRITE_DISABLE_CMD); // FlashObj->SpiCs(FLASH_CS_HIGH); //} /* FLASH读取第一个状态寄存器 */ static unsigned char W25Q64_ReadStaReg(W25Q64JVSSIQ_OBJ * FlashObj) { unsigned char Sta; FlashObj->SpiCs(FLASH_CS_LOW); FlashObj->SpiWriteReadByte(READ_STA1_CMD); Sta = FlashObj->SpiWriteReadByte(0xFF); FlashObj->SpiCs(FLASH_CS_HIGH); return Sta; } /* 判忙 */ static void W25Q64_WaitNoBusy(W25Q64JVSSIQ_OBJ * FlashObj) { while (((W25Q64_ReadStaReg(FlashObj)) & 0x01) == 0x01) { FlashObj->DelayUs(3); } }