当前位置: 首页 > news >正文

Nor Flash读写方法

 

1、物理连接 (AM29LV160DB的NORFLASH)

2、读操作
读操作不需要命令序列,默认会进入读取状态

 U16 read_en29lv160ab(U32 addr)
{
       return *((volatile U16 *)(addr));
}

3、获取ID

    #define FLASH_base 0x00000000 //FLASH接到bank0上

    #define CMD_ADDR0 *((volATIle U16 *)(0x555*2+FLASH_base))
    #define CMD_ADDR1 *((volaTIle U16 *)(0x2aa*2+FLASH_base))
    #define CMD_ADDR2 *((volatile U16 *)(0xaaa*2+FLASH_base))
    /*** 读取 Am29LV800D 的ID ***/
    U32 Get_Am29LV800D_ID(void)
  {
   U32 i="0";
   U32 j="0";    CMD_ADDR0 = 0xaa; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0x90;
   i = (*(U16 *)(0*2+FLASH_base))<<16;//Manufacturer ID = 01
   CMD_ADDR0 = 0xaa; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0x90;
 
  j = *(U16 *)(1*2+FLASH_base);//device ID = 2249
   return 0;
  }
 

为什么对16bit的flash,在处理地址的时候要乘以2?
答:注意到16bit的flash的地址线,输入地址的A1连接到flash的A0引脚。例如16位的FLASH芯片,对于CPU,0x00和0x01表示2个不同的字节,但是从硬件连线上看,最低一位实际上是被丢掉了,所以在FLASH引脚端得到的都是0,也就是都指向FLASH的第一个WORD。
0x555到cpu端实际上是0x555>>1(右移动了一位),为了抵消这个,原0x555必须左移一位,也就是乘以2。


硬件为什么这么连接呢?

为什么用到volatile限定符?
答:volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。也就是对实时的硬件操作还是很有必要的。

4、擦除操作

编程前一定要先擦除.由于编程只能将'1'改写为'0',通过擦写可以将数据全部擦写为'1'.

 void Am29LV800D_SectorErase(U32 SA)
    {
    CMD_ADDR0 = 0xAA; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0x80;
    CMD_ADDR0 = 0xAA; CMD_ADDR1 = 0x55;//Word 模式命令序列
    *((volatile U16 *)(SA)) = 0x30;
    Waitfor_endofprg();//状态查询
    }

5、编程操作(写操作)

 

    int Am29LV800D_WordProg (U32 PA,U16 PD)
    {
    CMD_ADDR0 = 0xAA; CMD_ADDR1 = 0x55; CMD_ADDR0 = 0xA0;
    *((volatile U16 *)(PA)) = PD;// word模式,以上为4个命令周期
    return(Waitfor_endofprg());//状态查询
    }
6、查询状态(判断写操作是否完成)

NorFLASH 提供几个数据位来确定一个写操纵的状态,它们分别是: DQ2, DQ3, DQ5, DQ6,DQ7, and RY/BY#. 如上图所示.其中DQ7, RY/BY#引脚, 和 DQ6 中的每一个都提供了一种方法来判定一个编程或者擦除操纵是否已经完成或正在进行中.实际编程中只需要使用其中的一种.

DQ7:Data# Polling bit,DQ7在编程时的状态变化.
    在编程过程中从正在编程的地址中读出的数据的DQ7为要写进数据的补码.比如写进的数据为0x0000,及输进的DQ7为'0',则在编程中读出的数据为'1';当编程完成时读出的数据又变回输进的数据即'0'.
    在擦除过程中DQ7输出为'0';擦除完成后输出为'1';留意读取的地址必须是擦除范围内的地址.
RY/BY#:高电平表示'停当',低电平表示'忙'.
DQ6:轮转位1(Toggle Bit 1).
    在编程和擦除期间,读任意地址都会导致DQ6的轮转(0,1间相互变换)当操纵完成后,DQ6停止转换.
DQ2:轮转位2(Toggle Bit 2).当某个扇区被选中擦除时,读有效地址(地址都在擦除的扇区范围内)会导致DQ2的轮转.
    留意:DQ2只能判定一个特定的扇区是否被选中擦除.但不能区分这个快是否正在擦除中或者正处于擦除暂停状态.相比之下,DQ6可以区分NorFLASH是否处于擦除中或者擦除状态,但不能区分哪个快被选中擦除.因此需要这2个位来确定扇区和模式状态信息.
DQ5: 超时位(Exceeded Timing Limits),当编程或擦除操纵超过了一个特定内部脉冲计数是DQ5=1;这表明操纵失败.当编程时把'0'改为'1'就会导致DQ5=1,由于只有擦除擦做才能把'0'改为'1'.当错误发生后需要执行复位命令(见图1-1)才能返回到读数据状态.
DQ3: (扇区擦除计时位)Sector Erase Timer,只在扇区擦除指令时起作用.当擦除指令真正开始工作是DQ3=1,此时输进的命令(除擦除暂停命令外)都被忽略.DQ3=0,是可以添加附加的扇区用于多扇区擦除.
    以上讲了这些状态为,实际只需要使用几个就行,比较简单的就是选择DQ5,DQ6/DQ2.如下例.

int Waitfor_endofprg(void)
    {
    volatile U16 FLASHStatus,old;
    old=*((volatile U16 *)0x0);//先读一次状态
    while(1)
    {
    FLASHStatus=*((volatile U16 *)0x0);//再读一次状态
    if( (old&0x40) == (FLASHStatus&0x40) ) break;//比较DQ6.相同说明设备已经停当
    if( FLASHStatus&0x20 ) //判定DQ5,为'1'则超时
    {
    old=*((volatile U16 *)0x0);
    FLASHStatus=*((volatile U16 *)0x0);//在读取比较一次.由于可能在超时前恰好完成操纵.
    if( (old&0x40) == (FLASHStatus&0x40) )
    return 1;
    else return 0;
    }
    old=FLASHStatus;
    }
    return 1;
    }
7、内核虚拟地址

如果在Linux内核驱动中使用,而不是arm中使用,需要对物理地址进行虚拟转换

iomap_label_addr=(BYTE*)ioremap(FLASH_base,SECT_SIZE);

8、nor flash应用

nor flash可以直接写入二进制代码,在嵌入式的uboot中有很好的应用

9、遗留问题

为了保证读写过程不被打断,在内核驱动中要不要关闭中断?

local_irq_disable()
local_irq_enable()

转载于:https://www.cnblogs.com/mingziday/archive/2011/12/01/2271159.html

相关文章:

  • 幻灯片的实现
  • Linux下常见音频格式之间的转换方法
  • HTML,CSS的命名的习惯总结.
  • QSound 类
  • 一个月学会VC++2012 3.我们动手吧!
  • 啤酒游戏及其牛鞭效应的vensim模拟
  • {右键我的电脑无法打开计算机管理}解决方法
  • OGC标准介绍 10
  • PowerShell1.0 与2.0中的异常处理比较
  • 啤酒游戏及其牛鞭效应的模拟之二级模式
  • 委托(delegate)实现自定义控件的AutoPostBack功能
  • 啤酒游戏的牛鞭效应分析之供应链4层模式
  • 基于Eclipse的Hadoop应用开发环境配置
  • 特殊字符保存到SQL数据库的问题
  • 博客~希望给我一个新的天地,学习,工作,生活,情感~
  • Bootstrap JS插件Alert源码分析
  • C++11: atomic 头文件
  • Django 博客开发教程 8 - 博客文章详情页
  • ES6核心特性
  • JavaScript 一些 DOM 的知识点
  • JAVA并发编程--1.基础概念
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • Netty源码解析1-Buffer
  • PHP面试之三:MySQL数据库
  • QQ浏览器x5内核的兼容性问题
  • WePY 在小程序性能调优上做出的探究
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 关于extract.autodesk.io的一些说明
  • 观察者模式实现非直接耦合
  • 记一次和乔布斯合作最难忘的经历
  • 区块链将重新定义世界
  • 在weex里面使用chart图表
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • Nginx实现动静分离
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 如何在招聘中考核.NET架构师
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • #14vue3生成表单并跳转到外部地址的方式
  • (11)MSP430F5529 定时器B
  • (12)目标检测_SSD基于pytorch搭建代码
  • (6)STL算法之转换
  • (Git) gitignore基础使用
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (四)Linux Shell编程——输入输出重定向
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一)基于IDEA的JAVA基础10
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)项目管理杂谈-我所期望的新人
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET关于 跳过SSL中遇到的问题
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • @Autowired和@Resource装配