📄 flashtest.c
字号:
#include <csl.h>
#include <csl_emif.h>
#include <csl_chiphal.h>
#include <csl_gpio.h>
#include <csl_pll.h>
#include <stdio.h>
#include "EmifConfig.h"
#include "date.h"
void ChipErase(void); //FLASH擦除函数
void EraseCheck(void);
void BurnBlock(Uint16* pdata,Uint16 FlashDstAddr,Uint16 nWords); //FLASH连续烧写函数
void BurnWord (Uint16 Addr, Uint16 Val); //对FLASH写入一个字
void WriteCommand(Uint16 Addr, Uint16 Value);
Uint16 ReadFlash(Uint16 Addr);
void BurnInfoPrtf(void);
void WriteOrEraseIsOver(void); //判断D6位,确定FLASH写或者擦写操作是否结束
void EntryID(void); //进入读FLASH ID模式
void ExitID(void); //退出读ID 模式( EntryID 与 ExitID 应成对使用)
void Lockout(void); //对BOOT区上锁
void SetGpio01HiAddr(Uint16 Addr); //FLASH 高两位操作(A14 A15)
void Delayus(Uint16 nusSum);//延时2us程序
void Delays(Uint16 nsSum);
#define FLASH_BASE_ADDR 0x200000 //linear base word address
#define FLASH_SIZE 0xFFFF
#define PROG_SIZE 0xffff
#define FCP5 (FLASH_BASE_ADDR+0x5555) //flash command port 5
#define FCPA (FLASH_BASE_ADDR+0x2aaa) //flash command port A
PLL_Config MyConfig = {
1, /* iai */
1, /* iab */ /* F=[晶振频率/(div+1)]*pllmult */
31, /* pllmult */ /* 通过调节pllmult值来调节工作频率 */
3 /* div */ /* F=[24/(3+1)]*31=186MHz 约5.3ns */
};
Uint16 ErrorBurnAddrTab[1000];
Uint16 AddrTabCnt=0;
#pragma DATA_SECTION(ErrorBurnAddrTab,".my_sect");
void main()
{
Uint16 *DataSource;
DataSource=(Uint16*)0x800e; //数据区起始地址(0x8000b)+2字
IRQ_globalDisable(); //禁止所有可屏蔽的中断源
CSL_init(); //初始化
PLL_config(&MyConfig);
CHIP_RSET(XBSR,0x0281); //EMIF为全EMIF接口
EMIF_config(&Config_emif); //配置EMIF
GPIO_pinDirection(GPIO_PIN0,GPIO_OUTPUT); //将IO0和IO1设成输出口
GPIO_pinDirection(GPIO_PIN1,GPIO_OUTPUT);
//延时时间测试
/*
while(1)
{
GPIO_pinWrite(GPIO_PIN0,0);
Delayus(30);
GPIO_pinWrite(GPIO_PIN0,1);
Delayus(40);
}
*/
Delayus(100);
EntryID(); // 读ID
Delayus(100);
ExitID(); // 退出读ID模式
Delayus(100);
ChipErase(); // Flash 擦除
Delayus(100);
EraseCheck(); // Flash 擦除校验
Delayus(100);
BurnBlock(DataSource,FLASH_BASE_ADDR,PROG_SIZE); // Flash块烧写
Delayus(100);
BurnInfoPrtf(); // 打印烧写信息
while(1){}
}
/*************************************
子程序
**************************************/
/*********** FLASH 擦除 **************/
void ChipErase(void)
{
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0x80);
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0x10);
WriteOrEraseIsOver();
}
/*********** 擦除校验 ****************/
void EraseCheck(void)
{
Uint16 i;
Uint16 ErrorFlag=0;
Uint16 EraseTemp;
for(i=0;i<FLASH_SIZE;i++)
{
EraseTemp=ReadFlash(i);
if(EraseTemp!=0xFFFF)
ErrorFlag++;
}
if(ErrorFlag==0)
printf("\nChipErase is successful! \n");
else
printf("ChipErase failed %d times!\n",ErrorFlag);
}
/********** FLASH 烧写************/
void BurnBlock(Uint16 * pdata,Uint16 FlashDstAddr,Uint16 nWords)
{
Uint16 i,j;
Uint16 ReadTemp;
for(i=0;i<nWords;i++)
{
BurnWord(i,*(pdata+i)); //flash_date[i]) ;
ReadTemp=ReadFlash(i);
if(ReadTemp!=*(pdata+i)) //判断是否烧写成功
{
for(j=0;j<10;j++) //烧写失败,重复对该单元烧写 10 次
{
BurnWord(i,*(pdata+i));
}
ReadTemp=ReadFlash(i); //重复烧写5次后,判断是否烧写成功
if(ReadTemp!=*(pdata+i))
{
ErrorBurnAddrTab[AddrTabCnt]=i; //失败!纪录烧写失败单元的地址
AddrTabCnt++;
}
}
}
}
/******************************************
FLASH 单个字的读写操作
在对FLASH的读写操作中,传递参数中的地址
是FLASH的空间地址而不是EMIF空间地址
*******************************************/
/********* 向 FLASH 烧一个字 ********/
void BurnWord (Uint16 Addr, Uint16 Val)
{
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0xa0);
WriteCommand(Addr,Val);
WriteOrEraseIsOver();
Delayus(20);
}
/********** 写控制或数据命令 ***********/
void WriteCommand(Uint16 Addr, Uint16 Value)
{
SetGpio01HiAddr(Addr);
*(volatile Uint16 *)(FLASH_BASE_ADDR+Addr)=Value;
}
/********* 读 FLASH ********/
Uint16 ReadFlash(Uint16 Addr)
{
Uint16 Value;
SetGpio01HiAddr(Addr);
Value=*(volatile Uint16 *)(FLASH_BASE_ADDR+Addr);
return(Value);
}
/*********打印烧写信息*******/
void BurnInfoPrtf(void)
{
Uint16 i;
if(AddrTabCnt==0)
{
printf("\nFlash burn succeful! \n");
}
else
{
printf("\nFlash burn failed %d times!\n",AddrTabCnt);
for(i=0;i<AddrTabCnt;i++)
{
printf("Flash Burn Error Adderss is : %x! \n",ErrorBurnAddrTab[i]);
}
}
}
/********* 操作结束标志判断 *************/
void WriteOrEraseIsOver(void)
{
volatile Uint16 LastToggleBit,CurrentToggleBit;
LastToggleBit= (*(volatile Uint16 *)(FLASH_BASE_ADDR))&0x40;
CurrentToggleBit=(*(volatile Uint16 *)(FLASH_BASE_ADDR))&0x40;
while(1)
{
if(LastToggleBit==CurrentToggleBit)
break;
LastToggleBit=CurrentToggleBit;
CurrentToggleBit=(*(volatile Uint16*)(FLASH_BASE_ADDR))&0x40;
}
}
/***********进入读 FLASH ID模式****************/
void EntryID(void)
{
int Manufacturer_code;
int Device_Code;
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0x90);
Manufacturer_code = ReadFlash(0x0);
Device_Code = ReadFlash(0x1);
if(Manufacturer_code==0x001f)
{
printf("Manufacturer code: 001f\n");
}
else
{
printf("Manufacturer code error!\n");
}
if(Device_Code==0x0087)
{
printf("Device code: 0087\n");
}
else
{
printf("Device code error!\n");
}
}
/*************退出读 FLASH ID模式*************/
void ExitID(void)
{
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0xf0);
}
/*********** 对 FLASH 前 8K 字上锁 ***********/
void Lockout(void)
{
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0x80);
WriteCommand(0x5555,0xaa);
WriteCommand(0x2aaa,0x55);
WriteCommand(0x5555,0x40);
}
/********** 高两位地址设置 ***********/
void SetGpio01HiAddr(Uint16 Addr)
{
Uint16 A14,A15,Temp;
Temp=Addr>>14;
A14=Temp&0x01;
A15=Temp>>1;
GPIO_pinWrite(GPIO_PIN0,A14); //14
GPIO_pinWrite(GPIO_PIN1,A15); //15
Delayus(2);
}
/**********延时函数***************/
void Delayus(Uint16 nusSum) //186 MHz工作频率下,延时 N个us;
{
int i,j,k;
for(i=0;i<nusSum;i++)
{
k=0; //使程序不进行编译优化处理;
for(j=0;j<13;j++)
{
k=0;
}
}
}
void Delays(Uint16 nsSum) //延时 N个s;
{
int i,j,k;
for(i=0;i<nsSum;i++)
{
k=0;
for(j=0;j<100000;j++)
{
k=0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -