📄 flash编程操作.c
字号:
//定义Flash类型列表
#define FLASH_TYPE_NUM 5 //一共5种Flash类型
#define MB29LV650UE 1
#define HY29LV160T 2
#define HY29LV160B 3
#define AM29LV320DT 4
#define AM29LV320DB 5
const char product_info[][30]={"no flash","MB29LV650UE","HY29LV160T","HY29LV160B","AM29LV320DT","AM29LV320DB"};
const unsigned int SEC_NUM[]={0,128,35,35,71,71};
const unsigned int FLASH_SIZE[]={0,0x800000,0x200000,0x200000,0x400000,0x400000};
const unsigned int FLASH_ID[]={0,0x0422D7,0xAD22C4,0xAD2249,0x0122F6,0x0122F9}; //定义Flash类型号的变量
static int flash_type;
//将Flash识别的函数做如下扩充
int flash_init(void){
volatile unsigned short *_p=FLASH_BASE;
unsigned int flash_id,i;
flash_type=FLASH_SEC_NUM=0;
_p[0x555]=0x00AA; //第一周期的写操作
_p[0x2AA]=0x0055; //第二周期的写操作
_p[0x555]=0x0090; //第三周期的写操作
flash_id=_p[0x00]>>16; //第四周期的写操作
printk("FLASH Manufacture ID is 0x%X.\n\r",flash_id>>16);
flash_id|=_p[0x01];
printk("FLASH Product ID is 0x%X.\n\r",flash_id&0xffff);
_p[0x00]=0xf0; //退出识别状态
for(i=0;i<FLASH_TYPE_NUM;i++)
if(flash_id==FLASH_ID[i])flash_type=i;
printk("%s was found.\n\r",product_info[flash_type]);
return flash_type;
}
//再将Sec2Addr函数扩展如下
unsigned int Sec2Addr(unsigned int sec_index)
{
if(sec_index>SEC_NUM[flash_type])return 0xfffffffff; //出错处理
switch(flash_type){
case HY29LV160T:
switch(sec_index){ //for TOP Boot
case 32:return 0xFC000;
case 33:return 0xFD000;
case 34:return 0xFE000;
default:return sec_index<<15;
}
case HY29LV160B:
switch(sec_index){ //for Bottom Boot
case 0:return 0;
case 1:return 0x2000;
case 2:return 0x3000;
case 3:return 0x4000;
default:return(sec_index-3)<<15;
}
case MB29LV650UE:return sec_index<<15;
case AM29LV320DT:
if(sec_index<=63)return sec_index<<15;
else return 0x1f8000+((sec_index-63)<<12);
case AM29LV320DB: //71 sector
if(sec_index<=8)return sec_index<<12;
else return (sec_index-7)<<15;
}
return 0xffffffff; //出错处理
}
//以后如果要增加对新的Flash类型的支持,只需要修改Sec2Addr函数,前面的宏定义和一些常数变量即可。
//常用的函数flash_erase代码如下
int flash_erase(U32 start,U32 length){
U32 end,start_i,end_i,i;
start=start>>1,length=length>>1; //byte地址到Word地址转换
end=start+length; //计算Flash擦除范围的结束点
if(end>(FLASH_SIZE>>1)){
printk("out of flash range!\n\r");
return 0;
}
for(start_i=0;Sec2Addr(start_i)<=start;start_i++); //寻找第一个需要擦除的块
for(end_i=start_i;Sec2Addr(end_i)<end-1;end_i++); //寻找最后一个需要擦除的块
printk("erase range:sector %d to sector %d\n\r",start_i-1,end_i-1);
for(i=start_i-1;i<end_i;i++){ //依次逐个擦除需要擦除的块
if(flash_sec_erase(i)==0){
printk("sector erase faild!\n\r");
return 0;
}
}
return 1;
}
//flash_erase 函数只需要提供需要擦除的起始地址和长度,就可以将对应区域的所有块都擦除了,使用比较方便。
//给出一个flash编程的函数,这个函数只要给出需要编程的数据或代码的地址指针,需要编程的flash的偏移量和编程长度,就可以对已经擦除好的flash块进行编程了。
int flash_block_transfer(unsigned short *_p_source,unsigned int flash_offset,unsigned length)
{
volatile unsigned short *_p_target=Flash_BASE;
unsigned int i,target_address;
target_address=flash_offset>1; //byte地址到Word地址转换
length=length>>1; //byte地址到Word地址转换
for(i=0;i<length;i++,target_address++){ //按Word对Flash进行编程
_p_target[0x555]=0x00AA;
_p_target[0x2AA]=0x0055;
_p_target[0x555]=0x00A0;
_p_target[target_address]=_p_source[i];
if(!FlashDataToggle(target_address)){
printk("flash program failed!offset=%d\n\r",target_address);
return 0;
}
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -