915 lines
17 KiB
C
915 lines
17 KiB
C
|
||
#include "norflash.h"
|
||
|
||
#include "trigger.h"
|
||
#include "shell.h"
|
||
#include "delay.h"
|
||
|
||
//--------------------------------------------------------------------------------------------
|
||
|
||
// 常量定义
|
||
//----------------------------------------------
|
||
|
||
// serial Norflash 配置命令 (标准/双路/四路SPI指令),基本指令,
|
||
|
||
// // 实现
|
||
#define SNF_WT_ENABLE 0x06 // * // 写使能
|
||
#define SNF_VSR_WR_ENABLE 0x50 // // 易失存储器SR写使能
|
||
#define SNF_WT_DISABLE 0x04 // * // 写保护
|
||
|
||
#define SNF_RD_STREG1 0x05 // * // 读状态寄存器1(S7--S0)
|
||
#define SNF_RD_STREG2 0x35 // * // 读状态寄存器2(S15--S8)
|
||
#define SNF_WT_STREG12 0x01 // * // 写状态寄存器1和2(S7--S0 S15--S8)
|
||
|
||
#define SNF_READ_DATA 0x03 // * // 读数据 (3字节地址+至少1字节数据)
|
||
#define SNF_FAST_READ 0x0B // * // 读数据[快速读指令] (3字节地址+1字节虚字+至少1字节数据)
|
||
|
||
#define SNF_PAGE_PROGRAM 0x02 // * // 页写数据[最多可以写128个字(256个字节)数据,且不可以跨页] (3个字节的地址+2字节数据个数)
|
||
#define SNF_4K_ERASE 0x20 // * // 扇区擦除(4KB) (3字节地址)
|
||
#define SNF_32K_ERASE 0x52 // * // 块擦除(32KB) (3字节地址)
|
||
#define SNF_64K_ERASE 0xD8 // * // 块擦除(64KB) (3字节地址)
|
||
|
||
|
||
#define SNF_CHIP_ERASE 0xC7 // * // 片擦除 或 0x60
|
||
|
||
|
||
#define SNF_EP_SUSPEND 0x75 // // 擦除或写入挂起
|
||
#define SNF_EP_RESUME 0x7A // // 擦除或写入恢复(从挂起中)
|
||
#define SNF_POWER_DOWN 0xB9 // // 掉电
|
||
|
||
#define SNF_WKUP_DEVICE_ID 0xAB // // 上电和读取设备ID (3字节虚字+1字节设备ID)
|
||
#define SNF_MANU_DEVICE_ID 0x90 // * // 读取制造商ID和设备ID (2字节虚字+00H+1字节制造ID+1字节设备ID)
|
||
#define SNF_JEDEC_ID 0x9F // * // 芯片 JEDEC ID (固态技术协会)(1字节制造ID+2字节设备ID(存储器类型+存储器容量))
|
||
#define SNF_UNIQUE_ID 0x4B // * // 独特ID (4字节虚字+8字节UID)
|
||
#define SNF_RD_SFDP 0x5A // // 读SFDP寄存器(3字节地址+1字节虚字+至少1字节数据)
|
||
|
||
#define SNF_ERASE_SECURITY 0x44 // // 擦除 保密 寄存器(3字节地址) 三组保密寄存器地址 0x0010xx 0x0020xx 0x0030xx
|
||
#define SNF_PROGRAM_SECURITY 0x42 // // 编程 保密 寄存器(3字节地址+至少1字节数据)
|
||
#define SNF_READ_SECURITY 0x48 // // 读取 保密 寄存器(3字节地址+至少1字节数据)
|
||
|
||
#define SNF_RESET_DEVICE 0x66 // // 允许复位
|
||
#define SNF_ENABLE_RESET 0x99 // // 复位芯片
|
||
|
||
/*
|
||
#define SNF_BLOCK_LOCK 0x7E // // 全部锁定
|
||
#define SNF_BLOCK_UNLOCK 0x98 // // 全部解锁
|
||
#define SNF_ENTER_QPI 0x38 // // 进入QPI模式
|
||
|
||
#define SNF_INDV_BLOCK_LOCK 0x36 // // 单独锁定
|
||
#define SNF_INDV_BLOCK_UNLOCK 0x39 // // 单独解锁
|
||
#define SNF_READ_BLOCK_LOCK 0x3D // // 读取锁定
|
||
*/
|
||
|
||
//---------------------------------------------------
|
||
|
||
#define DUMMY_BYTE 0xFF
|
||
|
||
//--------------------------------------------------------------------------------------------
|
||
|
||
int SNFWaitNotBusyMs(u32 timeout);
|
||
int SNFWaitNotBusy10Us(u32 timeout);
|
||
|
||
u8 SNFReadStatusReg1(void);
|
||
u8 SNFReadStatusReg2(void);
|
||
void SNFWriteStatusReg1And2(u8 reg1, u8 reg2);
|
||
|
||
void ShowSNFInfo(void);
|
||
void SNFlashTest(char * para1, char * para2); // NorFlash 测试
|
||
|
||
//--------------------------------------------------------------------------------------------
|
||
|
||
typedef struct
|
||
{
|
||
int inited;
|
||
// SPI 读写函数
|
||
void (*spicson)(void);
|
||
void (*spicsoff)(void);
|
||
u8 (*spird)(void);
|
||
void (*spiwr)(u8 wb);
|
||
|
||
}SNFCtrl;
|
||
|
||
SNFCtrl g_snfCtrl;
|
||
|
||
//--------------------------------------------------------------------------------------------
|
||
|
||
// NorFlash 初始化
|
||
int SNFlashInit(void (*spicson)(void), void (*spicsoff)(void), u8 (*spird)(void), void (*spiwr)(u8 wb))
|
||
{
|
||
memset(&g_snfCtrl, 0, sizeof(SNFCtrl));
|
||
|
||
g_snfCtrl.spicson = spicson;
|
||
g_snfCtrl.spicsoff = spicsoff;
|
||
g_snfCtrl.spird = spird;
|
||
g_snfCtrl.spiwr = spiwr;
|
||
|
||
if (g_snfCtrl.spicson == NULL ||
|
||
g_snfCtrl.spicsoff == NULL ||
|
||
g_snfCtrl.spird == NULL ||
|
||
g_snfCtrl.spiwr == NULL ||
|
||
0 )
|
||
{
|
||
printf("SNFlashInit para error\r\n");
|
||
return -1;
|
||
}
|
||
|
||
g_snfCtrl.inited = 1;
|
||
|
||
SNFWirteEnable();
|
||
|
||
SNFWriteStatusReg1And2(0, 0);
|
||
|
||
SNFWaitNotBusyMs(100);
|
||
|
||
SNFWirteDisable();
|
||
|
||
#if (0)
|
||
ShowSNFInfo();
|
||
AddShellCmd("NORFLASH", "test nor flash", SNFlashTest);
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
// 写使能开
|
||
// 设置状态寄存器中得WEL 位 为1
|
||
// 必须在执行 擦除,编程写状态寄存器等指令之前将WEL位置1
|
||
void SNFWirteEnable(void)
|
||
{
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_WT_ENABLE);
|
||
|
||
g_snfCtrl.spicsoff();
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
// 写使能关(可关闭非易失寄存器的写使能)
|
||
// 设置状态寄存器中得WEL 位 为0
|
||
// 必须在执行 擦除,编程写状态寄存器等指令之前将WEL位置1
|
||
void SNFWirteDisable(void)
|
||
{
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_WT_DISABLE);
|
||
|
||
g_snfCtrl.spicsoff();
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
// 读状态寄存器1
|
||
// 可在任意时候读取(数据可以连续读取)
|
||
// SRP0 SEC TB PB2 PB1 PB0 WEL BUSY
|
||
|
||
u8 SNFReadStatusReg1(void)
|
||
{
|
||
u8 dat;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_RD_STREG1);
|
||
|
||
dat = g_snfCtrl.spird(); //
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return dat;
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
// 读状态寄存器2
|
||
// 可在任意时候读取(数据可以连续读取)
|
||
// SUS CMP LB3 LB2 LB1 (R) QE SRP1
|
||
u8 SNFReadStatusReg2(void)
|
||
{
|
||
u8 dat;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_RD_STREG2);
|
||
|
||
dat = g_snfCtrl.spird(); //
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return dat;
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
// 写状态寄存器1和2
|
||
void SNFWriteStatusReg1And2(u8 reg1, u8 reg2)
|
||
{
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_WT_STREG12);
|
||
|
||
g_snfCtrl.spiwr(reg1);
|
||
|
||
g_snfCtrl.spiwr(reg2);
|
||
|
||
g_snfCtrl.spicsoff();
|
||
}
|
||
|
||
//---------------------------------
|
||
// 函数功能: 判断Nor是否处于空闲状态
|
||
// 返回值: 0, 空闲
|
||
// 1, 忙
|
||
|
||
int SNFIsdStatusBusy(void)
|
||
{
|
||
u8 sta1;
|
||
sta1 = SNFReadStatusReg1();
|
||
sta1 &= 0x01; // WIP flag
|
||
|
||
return sta1;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 读数据(50M以下的速度)
|
||
// 在整个存储区域内可以连续读取
|
||
int SNFlashRdData(u32 addr, u8 * pBuf, int len)
|
||
{
|
||
int i;
|
||
if (pBuf == NULL ||
|
||
len <= 0 ||
|
||
g_snfCtrl.inited == 0 ||
|
||
0 )
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_READ_DATA);
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
*pBuf++ = g_snfCtrl.spird();
|
||
}
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return 0;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 快速读取(可达到104M)
|
||
// 在整个存储区域内可以连续读取
|
||
int SNFFastReadData(u32 addr, u8 * pBuf, int len)
|
||
{
|
||
int i;
|
||
if (pBuf == NULL ||
|
||
len <= 0 ||
|
||
g_snfCtrl.inited == 0 ||
|
||
0 )
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_FAST_READ);
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(DUMMY_BYTE);
|
||
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
*pBuf++ = g_snfCtrl.spird();
|
||
}
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return 0;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 判断数据区是否为空
|
||
int IsSNFlashEmpty(u32 addr, int len)
|
||
{
|
||
u32 i;
|
||
int rslt = 0;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_READ_DATA);
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
if (g_snfCtrl.spird() != 0xff)
|
||
{
|
||
rslt = 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 页内写数据[最多可以写256个字节数据]
|
||
// 如果数据超出一页,地址会循环回到一页的起始继续写入
|
||
int SNFPageProgram(u32 addr, u8 * pBuf, int len)
|
||
{
|
||
int i;
|
||
if (pBuf == NULL ||
|
||
len <= 0 ||
|
||
g_snfCtrl.inited == 0 ||
|
||
0 )
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
SNFWirteEnable();
|
||
SNFWaitNotBusy10Us(100);
|
||
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_PAGE_PROGRAM);
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
g_snfCtrl.spiwr(*pBuf++);
|
||
}
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return SNFWaitNotBusy10Us(300);
|
||
}
|
||
|
||
//---------------------------------
|
||
// 扇区擦除(4KB)
|
||
int SNFlash4kErase(u32 addr, int wait)
|
||
{
|
||
int rslt = 1;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return rslt;
|
||
}
|
||
|
||
SNFWirteEnable();
|
||
SNFWaitNotBusy10Us(100);
|
||
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_4K_ERASE);
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
if (wait != 0)
|
||
{
|
||
rslt = SNFWaitNotBusyMs(300);
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 扇区擦除(32KB)
|
||
int SNFlash32kErase(u32 addr, int wait)
|
||
{
|
||
int rslt = 1;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return rslt;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_32K_ERASE);
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
if (wait != 0)
|
||
{
|
||
rslt = SNFWaitNotBusyMs(800);
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 扇区擦除(64KB)
|
||
int SNFlash64kErase(u32 addr, int wait)
|
||
{
|
||
int rslt = 1;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return rslt;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_64K_ERASE);
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(HIWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(HIBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spiwr(LOBYTE(LOWORD(addr)));
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
if (wait != 0)
|
||
{
|
||
rslt = SNFWaitNotBusyMs(1000);
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 正片擦除
|
||
int SNFlashChipErase(u32 addr, int wait)
|
||
{
|
||
int rslt = 1;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return rslt;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
|
||
g_snfCtrl.spiwr(SNF_CHIP_ERASE);
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
if (wait != 0)
|
||
{
|
||
rslt = SNFWaitNotBusyMs(6000);
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 读取 制造商 id 和 设备 ID
|
||
// manufacturer id + device id
|
||
|
||
u32 SNFGetManufacDeviceID(void)
|
||
{
|
||
u32 mdid;
|
||
u8 mid,did;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
g_snfCtrl.spiwr(SNF_MANU_DEVICE_ID);
|
||
g_snfCtrl.spiwr(0);
|
||
g_snfCtrl.spiwr(0);
|
||
g_snfCtrl.spiwr(0);
|
||
|
||
mid = g_snfCtrl.spird();
|
||
did = g_snfCtrl.spird();
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
mdid = MAKEDWORDF(did, mid, 0, 0);
|
||
|
||
// printf("Nor flash manufacturer id and device id = 0x%x\r\n", mdid);
|
||
|
||
return mdid;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 读取 JEDEC ID
|
||
// manufacturer id + memory type + capacity
|
||
|
||
u32 SNFGetJedecID(void)
|
||
{
|
||
u32 jid;
|
||
u8 id1,id2,id3;
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
g_snfCtrl.spiwr(SNF_JEDEC_ID);
|
||
id3 = g_snfCtrl.spird();
|
||
id2 = g_snfCtrl.spird();
|
||
id1 = g_snfCtrl.spird();
|
||
g_snfCtrl.spicsoff();
|
||
|
||
jid = MAKEDWORDF(id1, id2, id3, 0);
|
||
|
||
// printf("Nor flash jedec id = 0x%x\r\n", jid);
|
||
|
||
return jid;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 读取 Unique ID
|
||
// 8字节的唯一序列号
|
||
|
||
u64 SNFGetUniqueID(void)
|
||
{
|
||
int i;
|
||
u8 id;
|
||
u64 uid;
|
||
u8 * pId = (u8 *)(&uid);
|
||
|
||
if (g_snfCtrl.inited == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
g_snfCtrl.spicson();
|
||
g_snfCtrl.spiwr(SNF_UNIQUE_ID);
|
||
g_snfCtrl.spiwr(DUMMY_BYTE);
|
||
g_snfCtrl.spiwr(DUMMY_BYTE);
|
||
g_snfCtrl.spiwr(DUMMY_BYTE);
|
||
g_snfCtrl.spiwr(DUMMY_BYTE);
|
||
|
||
printf("Nor flash Unique id = ");
|
||
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
id = g_snfCtrl.spird();
|
||
*pId++ = id;
|
||
printf("0x%x, ", id);
|
||
}
|
||
printf("\r\n");
|
||
|
||
g_snfCtrl.spicsoff();
|
||
|
||
return uid;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 连续写数据
|
||
int SNFlashWrData(u32 addr, u8 *data, int len)
|
||
{
|
||
int rslt;
|
||
u32 pglen;
|
||
|
||
pglen = addr % SNF_BYTES_PER_PAGE;
|
||
if (pglen == 0)
|
||
{
|
||
pglen = SNF_BYTES_PER_PAGE;
|
||
}
|
||
|
||
do
|
||
{
|
||
rslt = SNFPageProgram(addr, data, pglen);
|
||
if (rslt != 0)
|
||
{
|
||
break;
|
||
}
|
||
addr += pglen;
|
||
data += pglen;
|
||
len -= pglen;
|
||
if (len >= SNF_BYTES_PER_PAGE)
|
||
{
|
||
pglen = SNF_BYTES_PER_PAGE;
|
||
}
|
||
else if (len > 0)
|
||
{
|
||
pglen = len;
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}while(1);
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------
|
||
/* 整个扇区
|
||
* ---------------------- eaddr:扇区首地址(起始地址) -----
|
||
* | | |
|
||
* | | |
|
||
* | 页1 | |
|
||
* ---------------------- |
|
||
* | | |
|
||
* | | elen:扇区首地址到写入完成的字节数
|
||
* | 页2 | |
|
||
* ---------------------- ---- addr:写入起始地址 |
|
||
* | | | |
|
||
* | | len:写入长度 |
|
||
* | 页3 | | |
|
||
* ---------------------- ----- ----
|
||
* | |
|
||
* | |
|
||
* | 页4 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页5 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页6 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页7 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页8 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页9 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页10 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页11 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页12 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页13 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页14 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页15 |
|
||
* ----------------------
|
||
* | |
|
||
* | |
|
||
* | 页16 |
|
||
* ----------------------
|
||
*/
|
||
// 写数据(自动擦除)
|
||
int SNFlashWrDataWithErase(u32 addr, u8 *data, int len)
|
||
{
|
||
int i, erflag, rslt; // erflag:擦除标志 = 1,擦除
|
||
u8 rdata[SNF_BYTES_PER_SEC]; // 存储整个扇区的数据
|
||
u32 eaddr; // 扇区首地址
|
||
u32 elen, wlen; // elen:扇区首地址到写入完成的字节数 wlen:写入长度
|
||
|
||
eaddr = (addr/SNF_BYTES_PER_SEC) * SNF_BYTES_PER_SEC; // 取整扇区首地址
|
||
rslt = 0;
|
||
|
||
printf("nwe, fad=0x%x, sad=0x%x len=%d, \r\n", addr, eaddr, len);
|
||
|
||
while(addr < SNF_TOTAL_BYTES && len > 0)
|
||
{
|
||
erflag = 0;
|
||
SNFlashRdData(eaddr, rdata, SNF_BYTES_PER_SEC); // 读取一个扇区
|
||
|
||
elen = SNF_BYTES_PER_SEC;
|
||
if ((addr-eaddr)+len < elen)
|
||
{
|
||
elen = len+(addr-eaddr); // 扇区首地址到写入完成的字节数
|
||
}
|
||
|
||
wlen = elen-(addr-eaddr);
|
||
|
||
// 判断是否需要擦除
|
||
for (i = (addr-eaddr); i < elen; i++) // 如果不能写入(存在0--1)
|
||
{
|
||
if ((rdata[i] & data[i]) != data[i]) // 与之后,和要写入数据相同,可以不擦除
|
||
{
|
||
erflag = 1; // 擦除标志
|
||
break;
|
||
}
|
||
}
|
||
|
||
// printf("elen=%d, wlen=%d, bufbeg=%d\r\n", elen, wlen, addr-eaddr);
|
||
|
||
if (erflag != 0)
|
||
{
|
||
SNFlash4kErase(eaddr, 1); // 擦除一个扇区
|
||
|
||
memcpy(&(rdata[(addr-eaddr)]), data, wlen); // 数据写入缓冲区
|
||
rslt = SNFlashWrData(eaddr, rdata, SNF_BYTES_PER_SEC); // 写入flash
|
||
|
||
printf("Erase 4K and wr\r\n");
|
||
}
|
||
else
|
||
{
|
||
// printf("wr to fls\r\n");
|
||
rslt = SNFlashWrData(addr, data, wlen); // 写入flash
|
||
}
|
||
|
||
if (rslt != 0)
|
||
{
|
||
break;
|
||
}
|
||
|
||
len -= wlen;
|
||
data += wlen;
|
||
addr += wlen; // 地址增加
|
||
eaddr += SNF_BYTES_PER_SEC;
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
|
||
//---------------------------------
|
||
|
||
// 函数功能: 等待Nor操作完成
|
||
// 返回值: 0, 正常
|
||
// -1, 超时
|
||
int SNFWaitNotBusyMs(u32 timeout)
|
||
{
|
||
u32 i;
|
||
int rst = -1;
|
||
|
||
for (i = 0; i < timeout; i++)
|
||
{
|
||
if (SNFIsdStatusBusy() == 0)
|
||
{
|
||
rst = 0;
|
||
break;
|
||
}
|
||
DelayMs(1); // 此处可替换为其他延时函数
|
||
}
|
||
|
||
return rst;
|
||
}
|
||
|
||
//---------------------------------
|
||
// 函数功能: 等待Nor操作完成
|
||
// 返回值:0 正常
|
||
// -1:超时
|
||
int SNFWaitNotBusy10Us(u32 timeout)
|
||
{
|
||
u32 i;
|
||
int rst = -1;
|
||
|
||
for (i = 0; i < timeout; i++)
|
||
{
|
||
if (SNFIsdStatusBusy() == 0)
|
||
{
|
||
rst = 0;
|
||
break;
|
||
}
|
||
DelayUs(10); // 此处可替换为其他延时函数
|
||
}
|
||
|
||
return rst;
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
void ShowSNFInfo(void)
|
||
{
|
||
u32 id;
|
||
|
||
printf("--------------nor flash info--------------\r\n");
|
||
|
||
id = SNFGetManufacDeviceID(); // 读取 制造商 id 和 设备 ID
|
||
printf("manufacturer id = 0x%x\r\n", HIBYTE(LOWORD(id)));
|
||
printf("device id = 0x%x\r\n", LOBYTE(LOWORD(id)));
|
||
|
||
id = SNFGetJedecID(); // 读取 jedec id
|
||
|
||
printf("manufacturer id = 0x%x\r\n", LOBYTE(HIWORD(id)));
|
||
printf("memory type = 0x%x\r\n", HIBYTE(LOWORD(id)));
|
||
printf("capacity = 0x%x\r\n", LOBYTE(LOWORD(id)));
|
||
|
||
SNFGetUniqueID(); // 8字节的唯一序列号
|
||
|
||
printf("------------------------------------------\r\n");
|
||
}
|
||
|
||
// NorFlash 测试
|
||
void SNFlashTest(char * para1, char * para2)
|
||
{
|
||
int p1, p2;
|
||
|
||
p1 = p2 = 0;
|
||
if (para1 != NULL && strcmp(para1, "") != 0)
|
||
{
|
||
p1 = atoi(para1);
|
||
}
|
||
if (para2 != NULL && strcmp(para2, "") != 0)
|
||
{
|
||
p2 = atoi(para2);
|
||
}
|
||
if (p1 == p2)
|
||
{
|
||
}
|
||
//--------------------------------
|
||
{
|
||
u8 buff[1024];
|
||
int i;
|
||
|
||
if (p1 == 0)
|
||
{// 从地址p2开始读取1K字节数据
|
||
memset(buff, 0, 1024);
|
||
DatFlashRdData(p2, buff, 1024);
|
||
printf("DatFlashRdData addr=0x%x,\r\n", p2);
|
||
for (i = 0; i < 1024; i++)
|
||
{
|
||
if ((i%16) == 0)
|
||
{
|
||
printf("\r\n%d:\t", i+1);
|
||
DelayMs(10);
|
||
}
|
||
printf("%02x ", buff[i]);
|
||
}
|
||
printf("\r\n");
|
||
}
|
||
else if (p1 == 1)
|
||
{// 从地址p2开始写入1K字节数据
|
||
printf("DatFlashWrDataWithErase addr=0x%x,\r\n", p2);
|
||
|
||
for (i = 0; i < 1024; i++)
|
||
{
|
||
buff[i] = p2 + i;
|
||
}
|
||
DatFlashWrDataWithErase(p2, buff, 1024);
|
||
printf("done \r\n");
|
||
}
|
||
else if (p1 == 3)
|
||
{// 从地址0x190000开始读取数据
|
||
int circle = p2;
|
||
int count = 0;
|
||
do
|
||
{
|
||
memset(buff, 0, 1024);
|
||
DatFlashRdData(0x190000+count*0x400, buff, 1024);
|
||
printf("DatFlashRdData addr=0x%x,\r\n", 0x190000+count*0x400);
|
||
for (i = 0; i < 1024; i++)
|
||
{
|
||
if ((i%16) == 0)
|
||
{
|
||
printf("\r\n%d:\t", count*1024+i+1);
|
||
DelayMs(10);
|
||
}
|
||
printf("%02x ", buff[i]);
|
||
}
|
||
printf("\r\n");
|
||
circle--;
|
||
count++;
|
||
if (circle <= 0)
|
||
{
|
||
break;
|
||
}
|
||
}while(1);
|
||
}
|
||
}
|
||
}
|
||
|