📄 memory_test.c
字号:
#define NULL 0
#define FLASH_BASE 0x00000000
#define DM_PG(x)
int DM_CNT = 0;
unsigned short ReadDeviceID(void)
{
unsigned short nDevID = 0;
volatile unsigned short * p;
unsigned char oldDmCnt;
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0xAA;
p = (volatile unsigned short *)FLASH_BASE + 0x2AA;
*p = 0x55;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0x90;
p = (volatile unsigned short *)FLASH_BASE + 0x01;
nDevID = *p; /*获得设备号*/
DM_CNT = oldDmCnt; //恢复到初始页
UnlockByreset();
return nDevID;
}
int EraseChip(void)
{
volatile unsigned short * p;
unsigned short data = 0;
unsigned char oldDmCnt;
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0xAA;
p = (volatile unsigned short *)FLASH_BASE + 0x2AA;
*p = 0x55;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0x80;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0xAA;
p = (volatile unsigned short *)FLASH_BASE + 0x2AA;
*p = 0x55;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0x10;
DM_CNT = oldDmCnt; //恢复到初始页
//对FLASH的擦除操作开始进行,我们需要等待并检查相关的数据来判断操作是否完成,
//或者操作失败
do
{
data = *p; //获取相关数据
if (data & 0x0080) //若擦除操作完成或成功,则data的最高位Bit7将被置为1
{
return 1;
}
else{}
}while ( (data & 0x0020) == 0); //若擦除操作正在进行,则data的Bit5置为0,继续等待
data = *p; //获取相关数据
if (data & 0x0080) //若擦除操作成功,则data的最高位Bit7将被置为1
return 1;
else
return 0;
}
//
int EraseSector(unsigned long addr)
{
volatile unsigned short * p;
unsigned short data = 0;
unsigned char oldDmCnt;
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0xAA;
p = (volatile unsigned short *)FLASH_BASE + 0x2AA;
*p = 0x55;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0x80;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0xAA;
p = (volatile unsigned short *)FLASH_BASE + 0x2AA;
*p = 0x55;
DM_CNT = oldDmCnt; //恢复到初始页
p = (volatile unsigned short *)FLASH_BASE + addr;
*p = 0x30;
do
{
data = *p; //获取相关数据
if (data & 0x0080)//若擦除操作完成或成功,则data的最高位Bit7将被置为1
{
return 1;
}
else{}
}while ( (data & 0x0020) == 0);
data = *p; //获取相关数据
if (data & 0x0080) //若擦除操作成功,则data的最高位Bit7将被置为1
{
return 1;
}
else
{
return 0;
}
}
int ReadFlash(unsigned long addr, unsigned long length, unsigned short * p)
{
unsigned long i;
if (NULL == p)
{
printf("Invalid polonger to buffer!\n");
return 0;
}
else{}
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
if (addr + length > 0x8000)
{
printf("Invalid length, the biggest address is out of range.\n");
return 0;
}
else{}
for (i = 0; i < length; i++)
{
*(p + i) = *(unsigned short *)(FLASH_BASE + addr + i*2);
}
return length;
}
int ReadSector(unsigned long addr, unsigned short * p)
{
unsigned long i;
unsigned long length = 0;
unsigned long sectorStartAddr = 0; //块起始地址
if (NULL == p)
{
printf("Invalid pointer to buffer!\n");
return 0;
}
else{}
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
if ( (DM_CNT & 0x1F) != 7) //若当前页不是第7页,则0页就是0块
{
length = 0x8000; //一个块32KWord
sectorStartAddr = 0;
}
else
{
if (addr < 0x4000)
{
length = 0x4000; //一个块16KWord
sectorStartAddr = 0;
}
else if (addr >= 0x4000 && addr < 0x6000)
{
length = 0x1000; //一个块4KWord
if (addr < 0x5000)
{
sectorStartAddr = 0x4000;
}
else
{
sectorStartAddr = 0x5000;
}
}
else if (addr >= 0x6000 && addr < 0x8000)
{
length = 0x2000; //一个块8KWord
sectorStartAddr = 0x6000;
}
else
{
printf("Invalid address, out of range.\n");
return 0;
}
}
for (i = 0; i < length; i++)
{
*(p + i) = *(unsigned short *)(FLASH_BASE + sectorStartAddr + i);
}
return length;
}
int ProgramFlash(unsigned long addr, unsigned short data)
{
volatile unsigned short * p;
unsigned short tmpData;
unsigned char oldDmCnt;
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned short *)(FLASH_BASE + 0x555);
*p = 0xAA;
p = (volatile unsigned short *)(FLASH_BASE + 0x2AA);
*p = 0x55;
p = (volatile unsigned short *)(FLASH_BASE + 0x555);
*p = 0xA0;
DM_CNT = oldDmCnt; //恢复到初始页
p = (volatile unsigned short *)(FLASH_BASE + addr);
*p = data;
//烧写操作需要0定的时间,要不断的检测烧写操作是否完成
do
{
tmpData = *p; //获取数据
if ( ((tmpData ^ data) & 0x0080) == 0)//若烧写成功,则tmpData 与 data的最高位与Bit7相同
return 1;
else{}
}while ( (tmpData & 0x0020) == 0); //若烧写还在进行,则tmpData的Bit5为0,否则完成
return 0;
}
int UnlockByProgram(unsigned long addr, unsigned short data)
{
volatile unsigned short * p;
unsigned short tmpData;
unsigned char oldDmCnt;
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned short *)(FLASH_BASE + 0xAAA);
*p = 0xA0;
DM_CNT = oldDmCnt; //恢复到初始页
p = (volatile unsigned short *)(FLASH_BASE + addr);
*p = data;
//烧写操作需要0定的时间,要不断的检测烧写操作是否完成
do
{
tmpData = *p; //获取数据
if ( ((tmpData ^ data) & 0x0080) == 0) //若烧写成功,则tmpData 与 data的Bit7相同
return 1;
else{}
}while ( (tmpData & 0x0020) == 0); //若烧写还在进行,则tmpData的Bit5为0,否则完成
return 0;
}
int WriteFlash(unsigned long addr, unsigned long length, unsigned short * p)
{
unsigned long i = 0;
if (NULL == p)
{
printf("Invalid polonger to buffer!\n");
return 0;
}
else{}
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
if (addr + length > 0x8000)
{
printf("Invalid length, the biggest address is out of range.\n");
return 0;
}
else{}
UnlockBypass(); //进入unlock bypass模式
for (i = 0; i < length * 2; i+=2)
{
if (UnlockByProgram(addr + i, *(p + i/2)) == 0)
{
UnlockByreset();
printf("Program Failed!\n");
return 0;
}
else{}
}
UnlockByreset();
return length;
}
int WriteSector(unsigned long addr, unsigned short * p)
{
unsigned long i;
unsigned long length = 0;
unsigned long sectorStartAddr = 0; //块起始地址
if (NULL == p)
{
printf("Invalid polonger to buffer!\n");
return 0;
}
else{}
if (addr > 0x8000)
{
printf("Invalid address, out of range.\n");
return 0;
}
else{}
if ( (DM_CNT & 0x1F) != 7) //若当前页不是第7页,则0页就是0块
{
length = 0x8000; //一个块32KWord
sectorStartAddr = 0;
}
else
{
if (addr < 0x4000)
{
length = 0x4000; //一个块16KWord
sectorStartAddr = 0;
}
else if (addr >= 0x4000 && addr < 0x6000)
{
length = 0x1000; //一个块4KWord
if (addr < 0x5000)
{
sectorStartAddr = 0x4000;
}
else
{
sectorStartAddr = 0x5000;
}
}
else if (addr >= 0x6000 && addr < 0x8000)
{
length = 0x2000; //一个块8KWord
sectorStartAddr = 0x6000;
}
else
{
printf("Invalid address, out of range.\n");
return 0;
}
}
UnlockBypass(); //进入unlock bypass模式
for (i = 0; i < length * 2; i+=2)
{
if (UnlockByProgram(sectorStartAddr + i, *(p + i/2)) == 0)
{
UnlockByreset();
printf("Program Failed!\n");
return 0;
}
else{}
}
UnlockByreset();
return length;
}
int UnlockBypass(void)
{
volatile unsigned short * p;
unsigned char oldDmCnt;
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0xAA;
p = (volatile unsigned short *)FLASH_BASE + 0x2AA;
*p = 0x55;
p = (volatile unsigned short *)FLASH_BASE + 0x555;
*p = 0x20;
DM_CNT = oldDmCnt; //恢复到初始页
return 1;
}
int UnlockByreset(void)
{
volatile unsigned char * p;
unsigned char oldDmCnt;
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned char *)FLASH_BASE;
*p = 0x90;
p = (volatile unsigned char *)FLASH_BASE;
*p = 0x00;
DM_CNT = oldDmCnt; //恢复到初始页
return 1;
}
int EraseSuspend(void)
{
volatile unsigned char * p;
unsigned char oldDmCnt;
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned char *)FLASH_BASE + 0xAAA;
*p = 0xB0;
DM_CNT = oldDmCnt; //恢复到初始页
return 1;
}
int EraseResume(void)
{
volatile unsigned char * p;
unsigned char oldDmCnt;
oldDmCnt = DM_CNT; //保存DM_CNT当前值,即保存当前页号
DM_PG(0); //映射到FLASH第0页,因为对FLASH操作的命令地址都是相对于第0页的
p = (volatile unsigned char *)FLASH_BASE + 0xAAA;
*p = 0x30;
DM_CNT = oldDmCnt; //恢复到初始页
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -