219 lines
7.0 KiB
C
219 lines
7.0 KiB
C
|
|
#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)) { //华邦电子的代号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);
|
|||
|
|
}
|
|||
|
|
}
|