20230731_XiaoFuZi_emb/ZheDaXiaoFuZi/Src/Usr/Driver/Ldrv/W25Q64JVSSIQ/McuW25Q64JvssiqDrv.c
Rjh913828050 a8560d741e 类型:重构
内容:重新整理项目文件分类
人员:任家豪
2023-10-08 16:10:23 +08:00

219 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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)
{
W25Q64_WakeUp(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);
}
}