Flash动画制作之nor flash驱动
小标 2018-03-08 来源 :网络 阅读 1019 评论 0

摘要:Nor Flash与Nand flash的不同之处在于Nor Flash的地址和数据线是不共用的,所以Nor Flash比较象ROM,是可以按地址自由读的,这样就非常适合存储代码,在开机时从Nor Flash中取代码来执行。在我的板子上有16M的Intel的Nor Flash E28F128J3A150,以此为例来研究一下Nor Flash的一些常用操作。E28F128J3A150每个sector是128k,擦除是按扇区操作了。

Nor Flash与Nand flash的不同之处在于Nor Flash的地址和数据线是不共用的,所以Nor Flash比较象ROM,是可以按地址自由读的,这样就非常适合存储代码,在开机时从Nor Flash中取代码来执行。在我的板子上有16M的Intel的Nor Flash E28F128J3A150,以此为例来研究一下Nor Flash的一些常用操作。E28F128J3A150每个sector是128k,擦除是按扇区操作了。

首先来看下E28F128J3A150与s3c2410的接口吧。

一般情况下ROM与s3c2410的接口我们可以在s3c2410的手册上看到,如下图所示

Flash动画制作之nor flash驱动

仔细看下16位和8位数据接口在地址线连接上的区别吧,16位的地址线是要移位的,A1接到A0上,这当然是比较容易理解的,位宽大了一倍,地址就少了一条。对于E28F128J3A150其实也是这样,不过又有点不一样,仔细看看E28F128J3A150的手册吧。下面给出接线图。

Flash动画制作之nor flash驱动 


不同之处E28F128J3A150貌似并没有移位,其实只是因为E28F128J3A150的A1就相对于别的16位ROM的A0,其A0就相当于他们的A(-1)是用来指示8位地址的,所以还是一样的。

来看看Flash操作的命令集吧

Flash动画制作之nor flash驱动

以几个比较重要的操作来说明比较容易懂

首先就是Read Identifier Codes

先给定我们的flash开始的地址吧,flash_addr=ioremap(0x0,0x1000000);

物理地址从0x0开始的0x1000000(16M)地址空间,这样得到了可访问的虚拟地址flash_addr

很简单,看命令表,先写一个命令      writew(0x90,flash_addr);

然后把Manufacture Code读回来              readw(flash_addr);

接着再读Device Code                      readw(flash_addr+2);

细节部分还是参考手册吧

其实内核已经MTD驱动完全支持Nor Flash的操作,所以不必要自己再写了。

不过在JTAG烧写flash的程序中可以加入对我们自己的flash的支持。

来看看其中对E28F128J3A150的烧写代码,分析一下。

int Strata_CheckID(int targetAddr)             //返回Manufacture Code
{
    _WR(targetAddr, 0x0090);   
    return _RD(targetAddr);                      //_WR和_RD都是半字操作
}
int Strata_CheckDevice(int targetAddr)       //返回Device Code
{
    _WR(targetAddr, 0x0090);
    return _RD(targetAddr+0x2);
}

看着Block Erase Flowchart再对照着Block Erase的函数看就比较能完全看懂了

Flash动画制作之nor flash驱动

void Strata_EraseSector(int targetAddress)
{
    unsigned long ReadStatus;
    unsigned long bSR5;
    unsigned long bSR7;
    _WR(targetAddress, 0x0020);      //擦除命令first cycle
    _WR(targetAddress, 0x00d0);    //擦除命令second cycle
    _WR(targetAddress, 0x0070);      //读状态寄存器命令
    ReadStatus=_RD(targetAddress);  //读状态寄存器
bSR7=ReadStatus & (1<<7);
while(!bSR7 )       //需要判断状态寄存器的第7位
    {
        _WR(targetAddress, 0x0070);
        ReadStatus=_RD(targetAddress);
        bSR7=ReadStatus & (1<<7);
    }
    _WR(targetAddress, 0x0070);
    ReadStatus=_RD(targetAddress); 
bSR5=ReadStatus & (1<<5);          
if (bSR5==0)
    {
        printf("Block @%xh Erase O.K. "n",targetAddress);
    }
    else
    {
        _WR(targetAddress, 0x0050);      //// Clear Status Register
        error_erase=1;  
    }
_RESET(); //就相当于_WR(targetAddress, 0x00ff),回到Read Array的状态。
}

很清晰的流程吧。

Byte/Word Program Flowchart

Flash动画制作之nor flash驱动

 

共两种Program方式可以把数据写到Flash中,一般也只用到这种就可以了

int Strata_ProgFlash(U32 realAddr,U16 data)
{
    unsigned long ReadStatus;
    unsigned long bSR4; 
    unsigned long bSR7;   
    _WR(realAddr, 0x0040);
    _WR(realAddr, data);
    _WR(realAddr, 0x0070);
    ReadStatus=_RD(realAddr);
    bSR7=ReadStatus & (1<<7);
    while(!bSR7)
    {
        _WR(realAddr, 0x0070);
        ReadStatus=_RD(realAddr);
        bSR7=ReadStatus & (1<<7);
    }
    _WR(realAddr, 0x0070);
    ReadStatus=_RD(realAddr);
    bSR4=ReadStatus & (1<<4);
    if (bSR4==0)
    {
        //printf("Successful Program!!"n");
    }
    else
    {
        _WR(realAddr, 0x0050);      // Clear Status Register
        error_program=1;        
    }
    _RESET();
    return 0;
}

以上这种写会很慢,以致于JTAG烧写相当得慢。

Flash动画制作之nor flash驱动

 

int Strata_unprotect_sector(int targetAddr)         //去除sector的写保护
{ 
   int SR7,SR3,SR4,SR5,ReadStatus; 
   int res=0; 
   _WR(targetAddr,0x0050); //Clear Status Register 
   _WR(targetAddr,0x0060); //First bus cycle 
   _WR(targetAddr,0x00D0); //Second bus cycle 
   _WR(targetAddr,0x0070); 
   ReadStatus=_RD(targetAddr); 
   SR7=ReadStatus & (1<<7); 
   while(!SR7) 
   { 
     _WR(targetAddr,0x0070); 
     ReadStatus=_RD(targetAddr); 
     SR7=ReadStatus & (1<<7); 
   }                                                                       
     _WR(targetAddr,0x0070); 
     ReadStatus=_RD(targetAddr); 
     SR3=ReadStatus & (1<<3); 
     SR4=ReadStatus & (1<<4); 
     SR5=ReadStatus & (1<<5); 
     if(SR3) {printf("Voltage Range Error"); res=-1;} 
     if(SR4 && SR5) {printf("Command Sequence Error"); res=-2;} 
     if(SR5) {printf("Clear Block Lock-Bits Error"); res=-3;} 
     _RESET(); 
     return res; 
}

另外按照write to buffer的流程自己写了一个函数,没有test,不想再去烧写了,太烦了,就这样好了。

void Strata_buffer_program(int blockAddress,int tagetAddress,U16* buf)
{
    unsigned long ReadStatus;
    unsigned long bSR4;    
    unsigned long bSR7;
    int i;
       do {
              _WR(blockAddress, 0x00E8);
        _WR(blockAddress, 0x0070);
        ReadStatus=_RD(blockAddress);
        bSR7=ReadStatus & (1<<7);
       } while(!bSR7);
    _WR(blockAddress, 0x001F);
       for(i=0;i<=0x1F;i++)
              _WR(targetAddress+2*i, *(buf+i));
       _WR(blockAddress, 0x00D0);
       do {
        _WR(blockAddress, 0x0070);
        ReadStatus=_RD(blockAddress);
        bSR7=ReadStatus & (1<<7);
       } while(!bSR7);
    _WR(blockAddress, 0x0070);
    ReadStatus=_RD(blockAddress); 
    bSR4=ReadStatus & (1<<4); 
    if (bSR4==0)
    {
        //printf("Successful Program!!"n");
    }
    else
    {
        _WR(blockAddress, 0x0050);
        error_program=1;
    }
    _RESET(); 
}


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标常用软件Flash频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程