218 lines
6.9 KiB
C
218 lines
6.9 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)
|
||
{
|
||
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);
|
||
}
|
||
}
|