⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash编程操作.c

📁 Norflash通用的读写
💻 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 + -