EDN首页   博客首页

最新日志

发表于:2007/8/16 8:45:35
标签:无标签

0

忙碌的日子

 

 

    好久没有关注我的博客了,很多想写的东西都被滞留了下来。还是因为刚开始工作起来,事务比较繁忙,很多的知识需要请教学习。现在公司做手机驱动,软硬件的东西都要掌握,平衡协调起来真有些困难。一步一步慢慢来吧。

系统分类: 生活点滴   |    用户分类:    |    来源: 原创

评论(2) | 阅读(917)
发表于:2007/7/2 19:31:06
标签:无标签

1

工作的第一天

 

2007年-07-02,今天是我从大学毕业后真正开始上班的第一天,可是说实话,我怎么没有什么特殊的感觉呢。按照平时的习惯,每到一个新鲜的环境,我都要兴奋的睡不着觉了,奇怪!

本来4月份我到公司签约时,给我安排的是在电子二科做硬件研发的,后来再来公司报到时,人事部经理找我谈心,问将我调到软件科怎么样,我虽然感觉上无所谓,但是心里边还是有些担忧的。在过去的一年中,我参加了学院的科技创新项目,编写嵌入式系统的底层驱动程序,哎!那时感觉好累啊,真不如画画电路图来的有意思。而现在又让我搞软件设计,那我岂不要减寿十年了???

但是,天大的想法,也要先扛住,刚到公司就不服从安排那还得了,再说了,从军校出来这点作风还没有,那是白上学了。后来,经过和软件科的经理聊天,我乐了,呵呵,正和我意,让我做底层那一块,软硬都涉及的,还有ARM系统的设计,也正符合我的发展方向。既然这样,何乐而不为呢。

现在我就在软件科开始了自己的研发生涯了。祝福我自己能搞出点成绩来吧!!!

系统分类: 生活点滴   |    用户分类: 无分类    |    来源: 原创

评论(3) | 阅读(1026)
发表于:2007/6/25 12:49:33
标签:大学中唯一一篇不错的文章  

0

细雨微后,晨春待醒的时光,耳际不闻昨日的喧嚣,惟有聒碎妙闲的鸟声一片,密承着恋枕依衾的甜梦。清风中的羞枝,已有半株绯赤的繁英;翡翠的叶子和草茎,托着柔辉溢彩的水晶。

空气中,戎金滑过,静谧下的柳絮,如光华的白玉,所有醉人的美图都聚在此刻。

上课的号角沉寂后,绿意将校园染的更加妩媚,纤小的相思声把校园鸣的更加幽静。在青石浅水处,鸟儿在然跳跃。不远处的一抹粉红惹怒了蜂蝶,嗡嗡嘤嘤,忙碌的身姿正如这晨春中的莘莘学子。

午饭后的阳光,绚烂中洋溢着馥郁的花香,吸一口,地迥天高中让人酡然欲醉。路旁的淡粉色花瓣,早已盛不下淋漓的光泽。凝望着曲径伸向一片绿色中,想象就振翅腾飞向浩瀚的广宇。

渐渐,云霞占满了校园的上空。多彩的斜晖掠来,俯向园中各处,使展示者披上异彩的衣裳,竟然沾沾自喜,刹那间溶没在霞光的怀抱中。凉风散去,湖水映着月儿,点滴中闪着残辉。温柔的晨光与虫声交相挥应着,共创这夜的世界。

星为弦,月为丝,星辰之下轻舞姿,月掩色,花含羞,情意浓。

在这春夜的枝头,绽开一朵浅金的月儿花,伴着幽香飘溢在校园中。

系统分类: 生活点滴   |    用户分类:    |    来源: 原创

评论(4) | 阅读(979)
发表于:2007/6/5 19:13:28
标签:无标签

0

毕业论文答辩

 

        今天下午,进行了在学校最后的一次重大考验:毕业论文答辩。呵呵,顺利通过。我的毕业设计课题是《基于S3C2410的BootLoader程序设计》,设计一个通用的启动代码,有空整理发表一下,和大家探讨探讨。

系统分类: 生活点滴   |    用户分类:    |    来源: 原创

评论(0) | 阅读(1265)
发表于:2007/5/18 13:52:26
标签:基于ARM920T的FLASH的读写  

9

FLASH的读写

 

最近一直在致力于基于ARM920T的FLASH的读写,虽然这部分一般没有多少人屑于研究,认为比较简单(U-boot和VIVI中都有现成的支持程序),但对于初学的我,还是尽心尽力地学习一下,目的在于自己编写一个通用flash驱动程序,以下是前段时间对主要两种flash的认识,大致整理了一下

 

 

FLASH

    所谓Flash,是内存(Memory)的一种,但兼有RAMROM 的优点,是一种可在系统(In-System)进行电擦写,掉电后信息不丢失的存储器,同时它的高集成度和低成本使它成为市场主流。

    Flash 芯片是由内部成千上万个存储单元组成的,每个单元存储一个bit具有低功耗、大容量、擦写速度快、可整片或分扇区在系统编程(烧写)、擦除等特点,并且可由内部嵌入的算法完成对芯片的操作,因而在各种嵌入式系统中得到了广泛的应用。

作为一种非易失性存储器,Flash在系统中通常用于存放程序代码、常量表以及一些在系统掉电后需要保存的用户数据等。

常用的Flash8位或16位的数据宽度,编程电压为单3.3V。主要的生产厂商为INTELATMELAMDHYUNDAI等。Flash 技术根据不同的应用场合也分为不同的发展方向,有擅长存储代码的NOR Flash和擅长存储数据的NAND Flash。一下对NOR FlashNAND Flash的技术分别作了相应的介绍。

 

一.NOR Flash

1.      市场介绍

随着技术的发展,愈来愈多的电子产品需要更多的智能化,这也对这些产品的程序存储提出了更高的要求。Flash 作为一种低成本、高集成度的存储技术在电子产品领域的应用非常广泛。今天90%PC、超过90%的手机、超过50%Modem,都是用了Flash,如今Flash市场规模已经超过了100亿美元。

如此巨大的市场规模,也导致市场上的Flash 品牌层出不穷。在NOR Flash市场中,Intel公司是非常重要的一家生产厂商。Intel公司生产的Flash芯片多年来占据着市场的很大份额,而它的芯片封装形式和接口也成为业界标准,从而为不同品牌的Flash带来了兼容的方便。

2.      NOR Flash 的硬件设计和调试

首先,Flash 要通过系统总线接在处理器上,即保持一个高速的数据交换的通道。那么就必须了解一下Flash在系统总线上的基本操作。

1) 先了解一下处理器存储空间BANK的概念。以32位处理器S3C2410为例,理论上可以寻址的空间为4GB,但其中有3GB的空间都预留给处理器内部的寄存器和其他设备了,留给外部可寻址的空间只有1GB,也就是0X00000000~0X3fffffff,总共应该有30根地址线。这1GB的空间,2410处理器又根据所支持的设备的特点将它分为了8份,每份空间有128MB,这每一份的空间又称为一个BANK。为方便操作,2410独立地给了每个BANK一个片选信号(nGCS7~nGCS0)。其实这8个片选信号可以看作是2410处理器内部30根地址线的最高三位所做的地址译码的结果。正因为这3根地址线所代表的地址信息已经由8个片选信号来传递了,因此2410处理器最后输出的实际地址线就只有A26~A0(如下图1

点击看大图

1  2410内存BANK示意图

 

    2)以图2(nWAIT信号)为例,描述一下处理器的总线的读操作过程,来说明Flash整体读、写的流程。第一个时钟周期开始,系统地址总线给出需要访问的存储空间地址,经过Tacs时间后,片选信号也相应给出(锁存当前地址线上地址信息),再经过Tcso时间后,处理器给出当前操作是读(nOE为低)还是写(new为低),并在Tacc时间内将数据数据准备好放之总线上,Tacc时间后(并查看nWAIT信号,为低则延长本次总线操作),nOE 拉高,锁存数据线数据。这样一个总线操作就基本完成

 

点击看大图

2  nWAIT 信号的总线读操作

 

3NOR Flash的接口设计(现代的29LV160芯片)

29LV160存储容量为8M字节,工作电压为3.3V,采用56TSOP封装或48FBGA封装,16位数据宽度。29LV160仅需单3.3V电压即可完成在系统的编程与擦除操作,通过对其内部的命令寄存器写入标准的命令序列,可对Flash进行编程(烧写)、整片擦除、按扇区擦除以及其他操作。引脚信号描述和接口电路分别如图3和图4所示。

点击看大图

3 29LV160引脚信号描述

 

 

点击看大图

4  FLASH29LV160)接口电路

 

可以从信号引脚图3和总线操作图2看出,NOR Flash的接口和系统总线接口完全匹配,可以很容易地接到系统总线上。

 

3.      NOR Flash的软件设计

Flash 的命令很多,但常用到的命令就3种:识别、擦除、编程命令。以下就对3种命令作分别的简要介绍:

1)  NOR Flash的识别

29lv160_CheckId()

{

    U8 tmp;

    U16 manId,devId;

    int i;

    _RESET();

   

    _WR(0x555,0xaa);

    _WR(0x2aa,0x55);

    _WR(0x555,0x90);

    manId=_RD(0x0);

    devId=_RD(0x1);

 

    _RESET();  

    printf("Manufacture ID(0x22C4)=%4x, Device ID(0x2249)=%4x\n",manId,devId);

 

    if(manId == 0x22C4 && devId == 0x2249)

        return 1;

    else

        return 0;

}

NOR Flash 的识别程序由四个读写周期就可以完成,在Flash的相关命令表中可以查到相应ID识别的命令。

 

2)  NOR Flash的擦除

要对NOR Flash进行写操作,就一定要先进性擦除操作。NOR Flash 的擦除都是以块(sector)为单位进行的,但是每一种型号的Flashsector的大小不同,即使在同一片的Flash内,,不同sector的大小也是不完全一样的。

void 29lv160db_EraseSector(int targetAddr)

{

        printf("Sector Erase is started!\n");

 

    _RESET();

    _WR(0x555,0xaa);

    _WR(0x2aa,0x55);

    _WR(0x555,0x80);

    _WR(0x555,0xaa);

_WR(0x2aa,0x55);

_WR(BADDR2WADDR(targetAddr),0x30);  

return  _WAIT(BADDR2WADDR(targetAddr);   

 }

 

 

                                            

                      5  Erase Operation   

 

/**************

如上图5所示,擦除操作时还要有一个关键的操作擦除查询算法,即等待Flash擦除的过程,并返回擦除是否成功的结果。算法如右图6所示

****************/

Int  _WAIT(void)

{

unsigned int stateflashStatusold;

old=_RD(BADDR2WADDR(0x0));

while(1)

    {

        flashStatus=_RD(BADDR2WADDR(0x0));

        if( (old&0x40) == (flashStatus&0x40) )

            break;

        if( flashStatus&0x20 )

        {

        //printf("[DQ5=1:%x]\n",flashStatus);

        old=_RD(BADDR2WADDR(0x0));

        flashStatus=_RD(BADDR2WADDR(0x0));

        if( (old&0x40) == (flashStatus&0x40) )

            return 0;

        else return 1;

        }

        //printf(".");

        old=flashStatus;

    }                                            //printf("!\n");

    return 1;

}

6  Toggle Bit Algorithm

       

以上的方法为查询数据线上的一个特定位Toggle位。此外还有2种检测方法,一种为提供额外的Busy信号,处理器通过不断查询Busy信号来得知Flash的擦除操作是否完成,一般较少应用;一种为查询Polling位。

 

3)  NOR Flash 的编程操作

int 29lv160db_ProgFlash(U32 realAddr,U16 data)

{

        _WR(0x555,0xaa);

        _WR(0x2aa,0x55);

        _WR(0x555,0xa0);

 

        _WR(BADDR2WADDR(realAddr),data);

           return  _WAIT(BADDR2WADDR(realAddr);

         

}

对擦除过的Flash进行编程比较简单,但仍然用到以上提到的查询算法,速度比较慢,一般为20uS,最长的达到500uS

 

二.NAND FLASH

NAND FLASH 在对大容量的数据存储需要中日益发展,到现今,所有的数码相机、多数MP3播放器、各种类型的U盘、很多PDA里面都有NAND FLASH的身影。

1.      Flash的简介

NOR Flash

u       程序和数据可存放在同一片芯片上,拥有独立的数据总线和地址总线,能快速随机地读取,允许系统直接从Flash中读取代码执行,而无需先将代码下载至RAM中再执行

u       可以单字节或单字编程,但不能单字节擦除,必须以块为单位或对整片执行擦除操作,在对存储器进行编程之前需要对块或整片进行预编程和擦除操作。

 

NAND FLASH

u       以页为单位进行读写操作,1页为256B512B;以块为单位进行擦除操作,1块为4KB8KB16KB。具有快编程和快擦除的功能

u       数据、地址采用同一总线,实现串行读取。随机读取速度慢且不能按字节随机编程

u       芯片尺寸小,引脚少,是位成本(bit cost)最低的固态存储器

u       芯片存储位错误率较高,推荐使用 ECC校验,并包含有冗余块,其数目大概占1%,当某个存储块发生错误后可以进行标注,并以冗余块代替

u       SamsungTOSHIBAFujistu三家公司支持采用NAND技术NAND Flash。目前,Samsung公司推出的最大存储容量可达8GbitNAND 主要作为SmartMedia卡、Compact Flash卡、PCMCIA ATA卡、固态盘的存储介质,并正成为Flash磁盘技术的核心。

2.      NAND FLASH NOR FLASH 的比较

1)       性能比较

    flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0

    由于擦除NOR器件时是以64128KB的块进行的,执行一个写入/擦除操作的时间为5s,与此相反,擦除NAND器件是以832KB的块进行的,执行相同的操作最多只需要4ms

    执行擦除时块尺寸的不同进一步拉大了NORNADN之间的性能差距,统计表明,对于给定的一套写入操作(尤其是更新小文件时),更多的擦除操作必须在基于NOR的单元中进行。这样,当选择存储解决方案时,设计师必须权衡以下的各项因素。

        ● NOR的读速度比NAND稍快一些。

        ● NAND的写入速度比NOR快很多。

        ● NAND4ms擦除速度远比NOR5s快。

        大多数写入操作需要先进行擦除操作。

        ● NAND的擦除单元更小,相应的擦除电路更少。

2)       接口差别

    NOR flash带有SRAM接口,有足够的地址引脚来寻址,可以很容易地存取其内部的每一个字节。

NAND器件使用复杂的I/O口来串行地存取数据,共用8位总线(各个产品或厂商的方法可能各不相同)。8个引脚用来传送控制、地址和数据信息。NAND读和写操作采用512字节的页和32KB的块为单位,这一点有点像硬盘管理此类操作,很自然地,基于NAND的存储器就可以取代硬盘或其他块设备。

3)       容量和成本

NAND flash的单元尺寸几乎是NOR器件的一半,由于生产过程更为简单,NAND结构可以在给定的模具尺寸内提供更高的容量,也就相应地降低了价格,大概只有NOR的十分之一。

NOR flash占据了容量为116MB闪存市场的大部分,而NAND flash只是用在8128MB的产品当中,这也说明NOR主要应用在代码存储介质中,NAND适合于数据存储,NANDCompactFlashSecure DigitalPC CardsMMC存储卡市场上所占份额最大。

4)       可靠性和耐用性

采用flahs介质时一个需要重点考虑的问题是可靠性。对于需要扩展MTBF的系统来说,Flash是非常合适的存储方案。可以从寿命(耐用性)、位交换和坏块处理三个方面来比较NORNAND的可靠性。

NAND闪存中每个块的最大擦写次数是一百万次,而NOR的擦写次数是十万次。NAND存储器除了具有101的块擦除周期优势,典型的NAND块尺寸要比NOR器件小8倍,每个NAND存储器块在给定的时间内的删除次数要少一些。

5)       位交换(错误率)

所有flash器件都受位交换现象的困扰。在某些情况下(很少见,NAND发生的次数要比NOR),一个比特位会发生反转或被报告反转了。一位的变化可能不很明显,但是如果发生在一个关键文件上,这个小小的故障可能导致系统停机。如果只是报告有问题,多读几次就可能解决了。当然,如果这个位真的改变了,就必须采用错误探测/错误更正(EDC/ECC)算法。位反转的问题更多见于NAND闪存,NAND的供应商建议使用NAND闪存的时候,同时使用EDC/ECC算法。

这个问题对于用NAND存储多媒体信息时倒不是致命的。当然,如果用本地存储设备来存储操作系统、配置文件或其他敏感信息时,必须使用EDC/ECC系统以确保可靠性。

6)       坏块处理

NAND器件中的坏块是随机分布的。以前也曾有过消除坏块的努力,但发现成品率太低,代价太高,根本不划算。NAND器件需要对介质进行初始化扫描以发现坏块,并将坏块标记为不可用。现在的FLSAH一般都提供冗余块来代替坏块如发现某个块的数据发生错误(ECC校验),则将该块标注成坏块,并以冗余块代替。这导致了在NAND Flash 中,一般都需要对坏块进行编号管理,让每一个块都有自己的逻辑地址。

7)       易于使用

可以非常直接地使用基于NOR的闪存,可以像其他存储器那样连接,并可以在上面直接运行代码。由于需要I/O接口,NAND要复杂得多。各种NAND器件的存取方法因厂家而异。在使用NAND器件时,必须先写入驱动程序,才能继续执行其他操作。向NAND器件写入信息需要相当的技巧,因为设计师绝不能向坏块写入,这就意味着在NAND器件上自始至终都必须进行虚拟映射。

8)       软件支持

当讨论软件支持的时候,应该区别基本的读//擦操作和高一级的用于磁盘仿真和闪存管理算法的软件,包括性能优化。在NOR器件上运行代码不需要任何的软件支持,在NAND器件上进行同样操作时,通常需要驱动程序,也就是内存技术驱动程序(MTD)NANDNOR器件在进行写入和擦除操作时都需要MTD。使用NOR器件时所需要的MTD要相对少一些,许多厂商都提供用于NOR器件的更高级软件,这其中包括M-SystemTrueFFS驱动,该驱动被Wind River SystemMicrosoftQNX Software SystemSymbianIntel等厂商所采用。驱动还用于对DiskOnChip产品进行仿真和NAND闪存的管理,包括纠错、坏块处理和损耗平衡。

在掌上电脑里要使用NAND FLASH 存储数据和程序,但是必须有NOR FLASH来启动。除了SAMSUNG处理器,其他用在掌上电脑的主流处理器还不支持直接由NAND FLASH 启动程序。因此,必须先用一片小的NOR FLASH 启动机器,在把OS等软件从NAND FLASH 载入SDRAM中运行才行。

9)       主要供应商

NOR FLASH的主要供应商是INTEL ,MICRO等厂商,曾经是FLASH的主流产品,但现在被NANDFLASH挤的比较难受。它的优点是可以直接从FLASH中运行程序,但是工艺复杂,价格比较贵。

NAND FLASH的主要供应商是SAMSUNG和东芝,在U盘、各种存储卡、MP3播放器里面的都是这种FLASH,由于工艺上的不同,它比NORFLASH拥有更大存储容量,而且便宜。但也有缺点,就是无法寻址直接运行程序,只能存储数据。另外NAND FLASH非常容易出现坏区,所以需要有校验的算法。

 

3NAND Flash的硬件设计

NAND FLASH是采用与非门结构技术的非易失存储器8位和16位两种组织形式下面以8位的NAND FLASH进行讨论。

1)      接口信号

NOR Flash相比较,其数据线宽度只有8bit,没有地址总线,I/O接口可用于控制命令和地址的输入,也可用于数据的输入和输出,多了CLEALE来区分总线上的数据类别。

信号

类型

描述

CLE

O

命令锁存使能

ALE

O

地址锁存使能

nFCE

O

NAND Flash片选

NFRE

O

NAND Flash读使能

nFWE

O

NAND Flash写使能

NCON

I

NAND Flash配置

R/nB

I

NAND Flash Ready/Busy

 

2)      地址结构

NAND FLASH主要以页(page)为单位进行读写,以块(block)为单位进行擦除。FLASH页的大小和块的大小因不同类型块结构而不同,块结构有两种:小块(图7)和大块(图8),小块NAND FLASH包含32个页,每页512+16字节;大块NAND FLASH包含64页,每页2048+64字节。

点击看大图

7  小块类型NAND FLASH

 

 

点击看大图

8  大块类型NAND FLASH

其中,512B(或1024B)用于存放数据,16B64B)用于存放其他信息(包括:块好坏的标记、块的逻辑地址、页内数据的ECC校验和等)NAND设备的随机读取得效率很低,一般以页为单位进行读操作。系统在每次读一页后会计算其校验和,并和存储在页内的冗余的16B内的校验和做比较,以此来判断读出的数据是否正确。

大块和小块NAND FLASH都有与页大小相同的页寄存器,用于数据缓存。当读数据时,先从NAND FLASH内存单元把数据读到页寄存器,外部通过访问NAND FLASH I/O端口获得页寄存器中数据(地址自动累加);当写数据时,外部通过NAND FLASH I/O端口输入的数据首先缓存在页寄存器,写命令发出后才写入到内存单元中。

 

3)      接口电路设计(以下以2410K9F1208U为例)

2410处理器拥有专门针对 NAND设备的接口,可以很方便地和NAND设备对接,如图9所示。虽然NAND设备的接口比较简单,容易接到系统总线上,但2410处理器针对NAND设备还集成了硬件ECC校验,这将大大提高NAND设备的读写效率。当没有处理器的ECC支持时,就需要由软件来完成ECC校验,这将消耗大量的CPU资源,使读写速度下降。

点击看大图

9 S3C2410NAND FLASH接口电路示意图

 

3NAND FLASH 的软件编写和调试

    NAND设备的软件调试一般分为以下几个步骤:设置相关寄存器、NAND 设备的初始化、NAND设备的识别、NAND设备的读擦写(带ECC校验 )

    NAND设备的操作都是需要通过命令来完成,不同厂家的命令稍有不同,以下一Samsung公司的K9F1208U0M命令表为例介绍NAND设备的软件编写。

点击看大图

2  K9F1208U0M  Command Sets

 

1)      根据2410寄存器定义如下的命令宏

#define NF_CMD(cmd) {rNFCMD=cmd;}

#define NF_ADDR(addr)   {rNFADDR=addr;}

#define NF_nFCE_L() {rNFCONF&=~(1<<11);}

#define NF_nFCE_H() {rNFCONF|=(1<<11);}

#define NF_RSTECC() {rNFCONF|=(1<<12);}

#define NF_RDDATA()     (rNFDATA)

#define NF_WRDATA(data) {rNFDATA=data;}

#define NF_WAITRB()    {while(!(rNFSTAT&(1<<0)));}

        //wait tWB and check F_RNB pin.

 

2)      NAND 设备的初始化

static void NF_Init(void)                          //Flash 初始化

{

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);                                            //设置NAND设备的相关寄存器

    // 1  1    1     1,   1      xxx,  r xxx,   r xxx       

    // En 512B 4step ECCR nFCE="H" tACLS   tWRPH0   tWRPH1

   

    NF_Reset();

}

static void NF_Reset(void)                           //Flash重置

{

    int i;

 

    NF_nFCE_L();

    NF_CMD(0xFF);                      //reset command

    for(i=0;i<10;i++);                  //tWB = 100ns

    NF_WAITRB();                        //wait 200~500us;

    NF_nFCE_H();

}

 

3)      NAND设备的识别                    //#define ID_K9F1208U0M  0xec76

static U16 NF_CheckId(void)                            //Id 辨别

{

    int i;

    U16 id;

   

    NF_nFCE_L();

    NF_CMD(0x90);

    NF_ADDR(0x0);

   

    for(i=0;i<10;i++);                  //wait tWB(100ns)

   

    id=NF_RDDATA()<<8;                  // Maker code(K9F1208U:0xec)

    id|=NF_RDDATA();                    // Devide code(K9F1208U:0x76)

   

    NF_nFCE_H();

    return id;

}

4)      NAND 的擦操作

static int NF_EraseBlock(U32 block)

{

    U32 blockPage=(block<<5);

    int i;

    NF_nFCE_L();

   

    NF_CMD(0x60[q1] );                            // Erase one block 1st command

 

    NF_ADDR(blockPage&0xff);                 // Page number="0"

    NF_ADDR((blockPage>>8)&0xff);  

    NF_ADDR((blockPage>>16)&0xff);

 

    NF_CMD(0xd0[q2] );                           // Erase one blcok 2nd command

   

   for(i=0;i<10;i++);                       //wait tWB(100ns)//??????

 

    NF_WAITRB();                            // Wait tBERS max 3ms.

    NF_CMD(0x70);                           // Read status command

 

    if (NF_RDDATA()&0x1)                    // Erase error

    {  

        NF_nFCE_H();

    Uart_Printf("[ERASE_ERROR:block#=%d]\n",block);

        return 0;

    }

    else

    {

        NF_nFCE_H();

        return 1;

    }

}

 

5)      NAND 的读操作

static int NF_ReadPage(U32 block,U32 page,U8 *buffer)        //Flash

{

    int i;

    unsigned int blockPage;

    U8 ecc0,ecc1,ecc2;

    U8 *bufPt=buffer;

    U8 se[16];    

   

    page=page&0x1f;                                 //32

    blockPage=(block<<5)+page;                      //1Bolck包含32

    NF_RSTECC();                                    // Initialize ECC

   

    NF_nFCE_L();   

    NF_CMD(0x00);                                   // Read command

    NF_ADDR(0);                                     // Column = 0

    NF_ADDR(blockPage&0xff);                        //

    NF_ADDR((blockPage>>8)&0xff);                   // Block & Page num.

    NF_ADDR((blockPage>>16)&0xff);                  //

 

    for(i=0;i<10;i++);                              //wait tWB(100ns)

   

    NF_WAITRB();                                    // Wait tR(max 12us)

    for(i=0;i<512;i++)

    {

        *bufPt++=NF_RDDATA();                       // Read one page

}

/************************ECC校验***************************/

    ecc0=rNFECC0;                              //利用2410自带的硬件ECC校验

    ecc1=rNFECC1;

    ecc2=rNFECC2;

[q3]     for(i=0;i<16;i++)

    {

        se[i]=NF_RDDATA();                          // Read spare array

                                                    //读页内冗余的16B

    }

       NF_nFCE_H();   

 

    if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2])   //未知使用哪一种软件规范?

    {                                               //比较数据结果是否正确

    Uart_Printf("[ECC OK:%x,%x,%x]\n",se[0],se[1],se[2]);

        return 1;

    }

    else

    {

    Uart_Printf("[ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x]\n",

        se[0],se[1],se[2],ecc0,ecc1,ecc2);

        return 0;

    }      

}

 

6)      NAND 的写操作

static int NF_WritePage(U32 block,U32 page,U8 *buffer)             //Flash

{

    int i;

    U32 blockPage=(block<<5)+page;

    U8 *bufPt=buffer;

 

    NF_RSTECC();                                // Initialize ECC

   

    NF_nFCE_L();

    NF_CMD(0x0[q4] );                                //?????\\Read Mode 1

    NF_CMD(0x80);                               // Write 1st command,数据输入

    NF_ADDR(0);                                 // Column 0

    NF_ADDR(blockPage&0xff);       

    NF_ADDR((blockPage>>8)&0xff);               // Block & page num.

    NF_ADDR((blockPage>>16)&0xff); 

 

    for(i=0;i<512;i++)

    {

    NF_WRDATA(*bufPt++);                    // Write one page to NFM from buffer

    } 

   

    seBuf[0]=rNFECC0;

    seBuf[1]=rNFECC1;

    seBuf[2]=rNFECC2;

    seBuf[5]=0xff;                          // Marking good block

   

    for(i=0;i<16;i++)

    {

    NF_WRDATA(seBuf[i]);                    // Write spare array(ECC and Mark)

    } 

[q5] 

    NF_CMD(0x10);                           // Write 2nd command

   

    for(i=0;i<10;i++);                      //tWB = 100ns. ////??????

 

    NF_WAITRB();                            //wait tPROG 200~500us;

 

    NF_CMD(0x70);                           // Read status command  

   

    for(i=0;i<3;i++);                       //twhr=60ns

   

    if (NF_RDDATA()&0x1)                    // Page write error

    {  

        NF_nFCE_H();

    Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);

    return 0;

    }

    else

    {

        NF_nFCE_H();

    #if (WRITEVERIFY==1)

    //return NF_VerifyPage(block,page,pPage);  

    #else

    return 1;

    #endif

    }

}

 

以下讨论一下NAND 设备上所支持的文件系统,大概现在有以下几种:

A.       JFFS2(没有坏块处理,支持大容量存储的时候需要消耗大量的内存,大量的随机访问降低了NAND设备的读取效率)和YAFFS(速度快,但不支持文件的压缩和解压)

B.       支持DiskOnChip设备的TRUEFFSTrue Flash File System. TRUEFFSM-Systems公司为其产品DiskOnChip开发的文件系统,其规范并不开放。

C.       SSFDCSolid State Floppy Disk Card)论坛定义的支持SM卡的DOS-FATSM卡的DOS-FAT文件系统是由SSFDC论坛定义的,但它必须用在标准的块设备上。

对于大量用在各类存储卡上的NAND 设备而言,他们几乎都采用FAT文件系统,而在嵌入式操作系统下,还没有驱动程序可以直接让NAND设备采用文件系统,就技术角度来说,FAT文件系统不是很适合NAND设备,因为FAT文件系统的文件分区表需要不断地擦写,而NAND设备的只能有限次的擦写。

 

    在上面已经很明显的提到,NAND设备存在坏块,为和上层文件系统接口,NAND设备的驱动程序必须给文件系统提供一个可靠的存储空间,这就需要ECCError Corection Code)校验,坏块标注、地址映射等一系列的技术手段来达到可靠存储目的。

    SSFDC软件规范中,详细定义了如何利用NAND设备每个页中的冗余信息来实现上述功能。这个软件规范中,很重要的一个概念就是块的逻辑地址,它将在物理上可能不连续、不可靠的空间分配编号,为他们在逻辑空间上给系统文件提供一个连续可靠的存储空间。

3给出了SSFDC规范中逻辑地址的标注方法。在系统初始化的时候,驱动程序先将所有的块扫描一遍,读出他们所对应的逻辑地址,并把逻辑地址和虚拟地址的映射表建好。系统运行时,驱动程序通过查询映射表,找到需要访问的逻辑地址所对应的物理地址然后进行数据读写。     

 

 

 

 

 

 

                3 冗余字节定义

字节序号

内容

字节序号

内容

512

用户定义数据

520

256BECC校验和

513

521

514

522

515

523

块逻辑地址

516

数据状态

524

517

块状态

525

256BECC校验和

518

块逻辑地址1

526

519

527

 

4给出了块逻辑地址的存放格式,LA表示逻辑地址,P代表偶校验位。逻辑地址只有10bit,代表只有1024bit的寻址空间。而SSFDC规范将NAND设备分成了多个zone,每个zone 内有1024块,但这物理上的1024块映射到逻辑空间只有1000块,其他的24块就作为备份使用,当有坏块存在时,就可以以备份块将其替换。

4  逻辑地址格式

D7

D6

D5

D4

D3

D2

D1

D0

 

0

0

0

1

0

LA9

LA8

LA7

518   523字节

LA6

LA5

LA4

LA3

LA2

LA1

LA0

P

519   524字节

 

有了以上的软件规范,就可以对NAND设备写出较标准的ECC校验,并可以编写检测坏块、标记坏块、建立物理地址和逻辑地址的映射表的程序了。

 

static int NF_IsBadBlock(U32 block)             //检测坏块

{

    int i;

    unsigned int blockPage;

    U8 data;

   

    blockPage=(block<<5);       // For 2'nd cycle I/O[7:5]

   

    NF_nFCE_L();   

    NF_CMD(0x50);       // Spare array read command

    NF_ADDR(517&0xf);   // Read the mark of bad block in spare array(M addr="5") [q6] 

    NF_ADDR(blockPage&0xff);    // The mark of bad block is in 0 page

    NF_ADDR((blockPage>>8)&0xff);   // For block number A[24:17]

    NF_ADDR((blockPage>>16)&0xff);  // For block number A[25]

 

   for(i=0;i<10;i++);               // wait tWB(100ns) //?????

   

    NF_WAITRB();                    // Wait tR(max 12us)

   

    data=NF_RDDATA();

 

    NF_nFCE_H();   

 

    if(data!=0xff)

    {

        Uart_Printf("[block %d has been marked as a bad block(%x)]\n",block,data);

        return 1;

    }

    else

    {

        return 0;

    }

}

 

static int NF_MarkBadBlock(U32 block)                       //标记坏块

{

    int i;

    U32 blockPage=(block<<5);

 

    seBuf[0]=0xff;

    seBuf[1]=0xff;   

    seBuf[2]=0xff;   

    seBuf[5]=0x44;                              // Bad blcok mark="0"[q7] 

   

    NF_nFCE_L();

    NF_CMD(0x50);                               //????

    NF_CMD(0x80);                               // Write 1st command

   

    NF_ADDR(0x0);                               // The mark of bad block is

    NF_ADDR(blockPage&0xff);                    // marked 5th spare array

    NF_ADDR((blockPage>>8)&0xff);               // in the 1st page.

    NF_ADDR((blockPage>>16)&0xff);             

   

    for(i=0;i<16;i++)

    {

    NF_WRDATA(seBuf[i]);                        // Write spare array

    }

 

    NF_CMD(0x10);                               // Write 2nd command

   

    for(i=0;i<10;i++);                          //tWB = 100ns. ///???????

 

    NF_WAITRB();                                // Wait tPROG(200~500us)

 

    NF_CMD(0x70);

   

    for(i=0;i<3;i++);                           //twhr=60ns////??????

   

    if (NF_RDDATA()&0x1)                        // Spare arrray write error

    {  

        NF_nFCE_H();

        Uart_Printf("[Program error is occurred but ignored]\n");

    }

    else

    {

        NF_nFCE_H();

    }

 

    Uart_Printf("[block #%d is marked as a bad block]\n",block);

    return 1;

}

 

int search_logic_block(void)                    //建立物理地址到逻

//辑地址的映射表

{

    unsigned int block,i,blockPage,logic_no,zone,zone_i;

    U8 SE[16];

    for(i=0;i<BLOCK_NR;i++)                         //初始化全局变量

        lg2ph[i]=space_block[i]=0xffff;

    logic_number=0;

    space_nr=0;

 

    NF_nFCE_L();

    zone=BLOCK_NR/1024;                             //确定NAND设备中zone

//的个数

 

    for(zone_i=0;zone_i<zone;zone_i++)

    {

        //搜索每个zone 内逻辑地址和物理地址的映射关系

        for(block=0;block<1024;block++)

        {

            blockPage=((block+zone_i*1024)<<BLOCK_ADDRERSS_SHIFT);

        NF_WATIRB();                                //等待R/B#信号有效

       

        NF_CMD(0x50);                               // 读取每个block内部第

//0Page内冗余的16个字节

        NF_ADDR(0);                                 // Column 0

        NF_ADDR(blockPage&0xff);       

        NF_ADDR((blockPage>>8)&0xff);               // Block & page num.

        NF_ADDR((blockPage>>16)&0xff);

 

        NF_WATIRB();                                //等待R/B#信号有效

        for(i=0;i<16;i++)  se[i]=NF_RDDATA();       // Write spare array

        NF_WATIRB();

 

        if(se[5]!=0xff)[q8]                              //检测是否存在坏块

            printk("\n\rphysic block %d is bad block\n\r",block);

        else if(se[7]!=se[12][q9] )

            printk("block address1:%d!=block address2 %d\n\r",se[7],se[12]);

        else if((se[6][q10] &0xf8)==0x10)

        {

            //计算该block对应的逻辑地址

            logic_no=((0x7&se[6])<<7)+(se[7]>>1)+zone_i*1000;

            if(lg2ph[logic_no]!=0xffff)             //说明有2block拥有相

//同的逻辑地址

                printk("physical block %d and block %d have the same logic number %d\n",lg2ph[logic_no],block,logic_no);

            else lg2ph[logic_no]=block;             //将该block的逻辑地址

//关系记入lg2ph

            logic_number++;                        

        }

        else if(se[7]==0xff)                        //说明该block尚未编号

        {space_block[space_nr]=block;

        space_nr++;

        }

        }

    }

    printk("there are totally %d logic blocks\n\r",logic_number);

    NF_nFCE_H();

    return logic_number;

}

这段代码的主要作用就是产生数组lg2ph[],这个数组的含义就是“块物理地址=lg2ph[逻辑地址]”。

 

 

 


 [q1]发出擦除命令

 [q2]确认并擦除

 [q3]2410处理器的功能

 [q4]为什么要有一个读取的命令???

 [q5]读取ECC并写入16字节中

 [q6]参看表3

 [q7]标记块状态  517字节

 [q8]块状态

 [q9]块逻辑地址1和块逻辑地址2

 [q10]块逻辑地址1

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(10) | 阅读(14030)
发表于:2007/4/26 15:05:44
标签:坛经  

2

坛经

 

         搞技术的,在闲暇之余,看看金刚经、坛经,领悟一下前辈的人生大道,揣摩自己的路程和人生经历,其实挺多感悟的。虽然看不透那么大的佛学哲理,但心会突然间静下来,难得!!!

 

身是菩提树,心如明镜台;
时时勤拂拭,勿使惹尘埃。


菩提本无树,明镜亦非台;
本来无一物,何处惹尘埃。

有情来下种,因地果还生;
无情亦无种,无性亦无生。


心平何劳持戒,行直何用修禅;
恩则孝养父母,义则上下相怜;
让则尊卑和睦,忍则众恶无喧;
若能钻木取火,淤泥定生红莲;
苦口的是良药,逆耳必是忠言;
改过必生智慧,护短心内非贤;
日用常行饶益,成道非由施钱;
菩提只向心觅,何劳向外求玄;
听说依此修行,天堂只在眼前。


心地无非自性戒,心地无痴自性慧,
心地无乱自性定。
不增不减自金刚,身去身来本三味。

系统分类: 生活点滴   |    用户分类:    |    来源: 原创

评论(0) | 阅读(843)
发表于:2007/4/4 17:48:44
标签:无标签

3

太阳能且USB充电系统设计

点击看大图点击看大图

 

第一次,独自全身心的投入到一个完整实践项目中,题目起草、可行性分析、原理设计、PCB设计、焊接、测试,写报告等。哈哈,终于小有成就,以上就是我的成品,比起第一次的PCB设计有很大进步,虽说还需很大的努力改进,但前进之路还算明朗点击看大图

系统分类: PCB   |    用户分类: 无分类    |    来源: 原创

评论(13) | 阅读(1232)
发表于:2007/4/4 16:50:38
标签:无标签

0

学的精还是学的博:寄语大学生

学以致用,历来如此。怎么学也一直是个问题。古代人由于知识交流手段贫乏,博学历来是学者们追求的目标。读万卷书,曾经是多少学子毕生的梦。

    今天,情况已经有了巨大的不同,信息太多了,一个博学的人未必知道得比一个会用google百度的人多。时代变了,学习方法也要变。

    我们学习的目标是什么呢?在下以为,学习的目的是通过学习的过程学习怎么去学习。说得绕口一些,其实会意者应该比较多。一个电子工程师,一生都是在学习中渡过的,最值钱的本事不是知道什么,而是怎么去知道下一个。

    所以,建议年轻的同学们静下心来,选择一个方向学精。任何东西你下上功夫搞透,都会让你脱胎换骨,你也能应付更复杂的新问题了。那些看起来知道的东西很多,却没有深度的人,其实根本经不起考验。

    我写程序只会用汇编和c,别的基本不会。写了多少呢?几十万行应该有了。有一次给一个朋友写一个java的程序,从上手到写完,也就两个小时不到,当然,程序逻辑也不复杂。看了几十年的手册,知道怎么看是最有效的,所以对于一个全新的东西掌握起来也就没那么复杂了。话又说回来了,一个c程序好久都无法取得进展的事情现在还有,原因是那个东西没搞透。

    电子行业的分工越来越细,分支越来越多,复杂度越来越高,工具也越来越多。初学者在学习工具的过程中会消耗掉很大一块精力,你如果同时掌握了几种工具,你几乎就没有精力去研究点有用的具体技术内容。精通一点,触类旁通,这次是正确的学习方法。

    现在招聘经常会明确指明应聘者应掌握的工具等条件,很多同学觉得工作难找,也不知道那块云彩能下雨,多学一种技能总是有好处吧。我想告诉大家的是,学生时期,少点功利性要更好一些,在这个略显浮躁的社会环境中,入静的本领越强,你将来的成就也就越大一些。

    所以,精是基础,博也是需要的。这里的博还不是那种功利性的博,素质的培训远比浅尝辄止的所谓博学重要。一个学电子的学生,浏览些机械类的课程,更进一步学学天文、物理什么的不是用处不大。看看人文类的书籍?

    有些东西我觉得非常重要:写一手好字,好文章?说一口标准的普通话?得体的与别人交流?健美的心理素质?

    祝同学们早日成功 

系统分类: 自由话题   |    用户分类: 无分类    |    来源: 转贴

评论(1) | 阅读(804)
发表于:2007/4/4 16:49:38
标签:无标签

1

年轻工程师怎样修炼成为“高手?

本人做过技术开发工作多年,从焊电路板的小工程师逐渐做到项目经理、研发经理,现在做到总工程师,作为工程师有亲身的感受,作为研发主管,对工程师的性格、心理和知识结构有非常深入的了解,现在把自己的一点感悟与大家分享,希望大家批评指正,欢迎补充完善。

     有强烈的好奇心。这是成为高手的必要条件,喜欢新生事物,对问题喜欢刨根问底,以钻研为乐趣。那种得过且过,敷衍了事,仅仅把工作当作饭碗的人连熟手都成不了,更何况高手。有好奇心的人,可以为解决一个问题通宵干,躺在床上也在寻思解决方案,这样的人就是高手的胚子!

     做事谨慎细致,考虑问题全面。技术工作来不得半点粗心马虎,否则问题多多,后患无穷。甚至给生产、产品品质造成重大影响,给公司造成重大经济损失。马虎的人不可能成为优秀的工程师,只可能当当助手,哪个上司敢把项目交给一个马大哈?改,难呐,本性难移!趁早找个理由炒他鱿鱼!

     模拟、数字,高频、低频,软件、硬件,模具、结构,甚至文字功底也必不可少(撰写产品使用手册、工艺指导书等等也可看出一个人的专业水准)具备完善的知识体系。企业中的工程师不是研究学问,也没指望成为科学家,是为企业的产品服务的。因此,全面的知识架构对于迅速完成产品开发任务非常重要,复合型人才更为难得。既然是高手,当然十八般兵器样样精通,否则,难以独挑大梁,只能做配角。没有全面的知识,要上升到项目经理、研发经理层面是不可能的。企业中的工程师必须时刻关注成本、生产工艺、用户需求、测试环境、采购渠道、配套厂家工艺水平等等许多方面,一点不慎后续问题就冒出来了。你的设计再好,工艺性差,车间生产装配调试困难,导致生产成本急剧上升,或者配套厂家工艺水平达不到又有什么用?或者器件采购困难,经常影响按期交货也同样对企业不利。时刻提醒自己,产品是赚钱的工具,自己才能的张扬要服从这一大前提。这里要特别提醒那些学历高,某方面技术精深,但对企业运作、生产工艺、生产流程、物流管理、行销模式、市场调查、用户心理是“二把刀”的人,不要自恃一点DSP皮毛就以为可以天下无敌,谦虚地深入基层,熟悉一切,虚心学习其他方面的知识,才有大为!

     思路开阔,能从市场、用户和生产工艺角度考虑产品开发。唯技术至上的人,思路狭隘,即使聪明过人,只能扮演一个处理具体问题的小角色。企业的唯一目标是赚钱,能赚钱就是好产品,不能赚钱就等于零。这就能解释为什么很多研究所、大学开发的产品填补了多少多少空白,但在产业化过程中却总赚不到钱,最后落满灰尘。企业的工程师,务必坚持市场第一,用户至上的开发思路,你的工作仅仅是开发出低成本的、工艺性好的、品质稳定的,最关键是满足目标用户需求的产品,不能凭想象发挥,自以为是,要知道,用户永远是对的,你不能让他们服从你的思路,你每天窝在实验室,对市场又了解多少?,对消费心理又知道多少,别自以为聪明,道听途说几句话就轻易下结论!

     现实、灵活的开发思路是高手的重要特征。企业的产品开发是和市场紧密联系在一起的,不是国家拨款的基础理论研究。树立市场化的研发策略是高手必备的素质!不要指望你能搞出超英赶美的世界级产品,你现在的实验条件、项目管理水平、人员素质、资金投入、信息交流等等和人家相比差了十万八千里,你凭什么搞出世界级的东西?家电巨头投下数亿元开发手机,高手云集,十余年了,手机的核心技术还是人家的。你做过的电路、编写过的程序千万人做过,你只不过东拼西凑地组合出了一个东西而已,必须要清醒地、谦虚地认识到这一层面。因此,在开发过程中,不要一切都自己开发、研究,大胆地借鉴国外的东西,绝大多数产品人家早已经普及,不妨照搬其中的功能模块,再结合自己实际情况,去搞开发才是高明的做法。再者别人的产品经过现场用户的使用,许多隐患已经消除,水平再高的人做的新产品也会从用户哪里反馈回来一些缺陷,直接模仿别人的产品,即可消除许多缺陷点。同时,可以大大缩短研发周期,减少研发费用,抢先一步推向市场,绝对是上策。当然,受到专利保护的技术要注意,仔细看看相关法律,在法律允许范围内从事,体会一下总还是有办法的!

     这里要一再强调,我所指的是“企业里受欢迎的高手!”不是科学院里的专家,不是陈景润!这是截然不同的概念。企业里的高手,不仅仅要了解技术、工艺以及生产方面的知识,团队意识,管理才能,协调沟通能力,系统规划能力,甚至语言表达能力都是很重要的,这些是高手的综合素质的体现。

     特别对毕业2-4年的年轻工程师提个醒,要清楚认识自己,知道自己的斤两,不要以为做过2-3个项目就飘飘然,人家也是那样过来的!其实还差得远!等到了二十七、八岁,你会逐渐明白的。学海无涯,除过极个别特殊天才人物,大家都是普通人,互有长短,谦虚谨慎,心态平和是成就大事的基础,总那么浮躁,狂妄,藐视他人,将导致团队合作困难,同事关系紧张,项目的进展必然不顺利,从而延长成为高手的时间,单纯从技术来看,不过在某个狭小领域有小小心得而已,距离经验丰富、技能全面的高手还有八年抗战的历程。一般来讲,毕业5-6年,技术初步达到全面成熟(那些得过且过的人,二十年也成熟不了,现在几十岁来应聘的人也不少,水平还是马马乎乎),再逐渐吸收管理知识、市场知识等其他企业里所涉及的方面的技能,30岁左右基本圆满已经非常不简单了!时刻要有谦和的心态,是在团队中脱颖而出的必须条件。

系统分类: 自由话题   |    用户分类: 无分类    |    来源: 转贴

评论(0) | 阅读(664)
发表于:2007/3/23 13:40:07
标签:BootLoader介绍  

1

评论(0) | 阅读(1095)
2Next >Total , Page /