20230731_XiaoFuZi_emb/ZheDaXiaoFuZiBoot/Src/Usr/Driver/Ldrv/W25Q64JVSSIQ/McuW25Q64JvssiqDrv.c

218 lines
6.9 KiB
C
Raw Normal View History

#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)) { //华邦电子的代号0xefW25Q64的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);
}
}