Chinaunix首页 | 论坛 | 博客
  • 博客访问: 970581
  • 博文数量: 214
  • 博客积分: 10173
  • 博客等级: 上将
  • 技术积分: 1867
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-18 13:48
文章分类

全部博文(214)

文章存档

2012年(1)

2010年(13)

2009年(5)

2008年(98)

2007年(97)

分类: LINUX

2007-08-22 15:48:40

基于NOR闪存设备的MTD驱动程序

摘要:uClinux系统下的闪存设备驱动程序开发,采用S3C44B0X处理器。使用Flash存储器接口电路、JFFS2文件系统,操作MTD芯片和硬件设备驱动的相关信息。并通过调用相关函数向系统加入和删除MTD原始设备、注册和注销原始设备的使用者。MTD在系统启动后自动识别支持CFI或JEDEC接口的FLASH芯片,之后通过查询命令读取CFI查询结构。

    关键词:MTD;NOR闪存;uClinux;接口;驱动程序

    引言

     uClinux是面向无存储器管理单元(MMU)的处理器嵌入式操作系统,可在Flash上运行,也可加载到内存中运行。S3C44B0X是三星公司生产的基于32位RISC的ARM7TDMI内核的处理器。故采用S3C44B0X处理器,介绍在uClinux操作系统下闪存设备驱动程序的开发过程。

    硬件设计

    硬件描述
     Hynix公司的Flash存储器HY29LV160具有16位数据宽度,单片存储容量为16Mbit(2Mbyte),A[19:0]为地址线,DATA[19:0]为数据线(DQ15可作为LSB地址A-1的输入),nBYTE是8/16bit数据带宽选择,nCE为片选信号线,nOE为输出激活,nWE为输入激活,nRESET为复位信号线。NRY/BY为就绪/繁忙信号,指示HY29LV160编程或擦除操作,可在2.7V~3.6V电压范围内进行读、编程(烧写)和擦除操作。读写数据需设置nCE、cOE和nWE,从闪存上读取数据时,将nCE和nOE设置为低电平,nWE为高电平;向闪存上写数据时,将nWE和nCE设置成低电平,nOE为高电平。

     Flash存储器接口电路
    采用三星公司的ARM处理器S3C44B0X和一片HY29LV160构建Flash存储器系统,如图1为16位模式Flash与处理器S3C44B0X的基本接法。

   
    图1  Flash与处理器S3C44B0X的基本接法

     Flash存储器在系统中通常用于存放程序代码,系统上电或复位后获取指令并开始执行,因此,应将存有程序代码的Flash存储器配置到Bank0,即将S3C44B0X的nGCS0接至HY29LV160的片选端nCE。输出使能端nOE接S3C44B0X的nOE;写使能端nWE接S3C44B0的nWBE0;将模式选择nBYTE上拉,使HY29LV160工作在16位数据模式;RY/BY(就绪/繁忙)指示HY29LV160编程或擦除操作的工作状态。HY29LV160地址总线A[19~0]与S3C44B0X的地址总线ADDR[19~0]相连,16位数据总线DQ[15~0]与S3C44B0X的低16位数据总线DATA[15~0]相连。

     MTD驱动程序的设计

    文件系统控制
    在uClinux下采用的文件系统控制层次如图2。内存文件控制块包括JFFS、JFFS2、块设备和字符设备等,针对闪存设备,采用JFFS2文件系统。

   
    图2  文件系统控制层次

    底层驱动主要完成文件系统对Flash芯片的访问控制,如读、写、擦除操作。在uCLinux中这部分功能是通过调用MTD驱动实现。相对于常规块设备驱动程序,使用MTD驱动程序的主要优点在于MTD驱动程序是专门为基于闪存的设备所设计的,通常有更好的支持、更好的管理和更好的基于扇区的擦除和读写操作的接口。

     MTD原始设备描述
    所有组成MTD原始设备的Flash芯片必须是同类型(无论是interleave还是地址相连),在描述MTD原始设备数据结构中采用同一结构描述组成Flash芯片。每个MTD原始设备有一个mtd_info结构,其中的priv指针指向一个map_info结构,map_info结构中的fldrv_priv指向一个cfi_private结构,cfi_private结构的cfiq指针指向一个cfi_ident结构,chips指针指向一个flchip结构的数组。其中mtd_info、map_info和cfi_private结构用于描述MTD原始设备,因为组成MTD原始设备的NOR型Flash相同,cfi_ident结构用于描述Flash芯片信息;而flchip结构用于描述每个Flash芯片专有信息。MTD数据结构具体如下:

     structmtd_info{
     int(*read)(structmtd_info*mtd,loff_tfrom,size_tlen,
size_t*retlen,u_char*buf);    //读操作
     int(*write)(structmtd_info*mtd,loff_tto,size_tlen,
size_t*retlen,constu_char*buf);    //写操作
     int(*read_ecc)(structmtd_info*mtd,loff_tfrom,size_tlen,
size_t*retlen,u_char*buf,u_char*eccbuf);
     int(*write_ecc)(structmtd_info*mtd,loff_tto,size_tlen,
size_t*retlen,constu_char*buf,u_char*eccbuf);
     int(*read_oob)(structmtd_info*mtd,loff_tfrom,size_t
     len,size_t*retlen,u_char*buf);
     int(*write_oob)(structmtd_info*mtd,loff_tto,size_tlen,
size_t*retlen,constu_char*buf);
    ..
     int(*lock)(structmtd_info*mtd,loff_tofs,size_tlen);    //加锁操作
     int(*unlock)(structmtd_info*mtd,loff_tofs,size_tlen);
     int(*suspend)(structmtd_info*mtd);    //低功耗模式,暂停供电
     void(*resume)(structmtd_info*mtd);    //重新开始
     void*priv;}

    综上所述,MTD分为:①硬件参数,如块的大小、内存类型等;②函数指针,指向操作函数。

    MTD函数中read()和write()函数实践上调用了NOR设备的read_ecc()和write_ecc()函数;read_ecc()函数中要根据校验码,进行ECC校验;read_oob读取OOB空间中的数据(校验码),不单独进行校验。最后一个字段void*priv很有用,在程序中,这个字段指向map_info结构。

    设备添加和注册
    在uClinux系统里,通过调用下面函数向系统加入和删除一个MTD原始设备、注册和注销一个原始设备的使用者。

     intadd_mtd_device(structmtd_info*mtd)

    该函数功能是加入一个MTD原始设备,参数mtd为被加入的原始设备。此函数返回0时,表示成功;返回1表示mtd_table已满。至于要删除一个mtd设备,系统通过del_mtd_device函数实现。


voidregister_mtd_user(structmtd_notifier*new)

    该函数功能是加入MTD原始设备的使用者(即MTD设备,MTD块设备或字符设备)。参数new为新MTD设备的mtd_notifier。系统通过函数unregister_mtd_user注销MTD原始设备使用者。

     NOR型Flash芯片驱动

     MTD在系统启动后需要自动识别支持CFI或JEDEC接口的Flash芯片。为了确定一个Flash是否是一个CFI使能的flashmemory器件,首先要往Flash的地址0x55H写入数据0x98H,然后从Flash的地址0x10H处开始连续读取3个存储单元中的内容,如果数据总线返回的3个存储单元的字符分别为'Q','R'和'Y',那么该器件是一个CFI使能的Flash。在识别Flash为CFI使能器件后,通过查询命令来读取CFI查询结构,数据地址和含义在cfi_ident.h文件中。探测CFI接口Flash设备程序在文件cfi_probe.c中,设备类型为“cfi_probe”。用JEDEC(电子电器设备联合会)标准设备模仿CFI接口,探测JEDEC设备程序在jedec_probe.c中,JEDEC设备类型为“jedec_probe”。所有芯片由chipreg.c的do_map_probe()程序驱动。

     MTD原始设备相关信息

    设计时,需要对HY29LV160编写相关的程序,包括该MTD原始设备的起始物理地址、大小、分区情况、读写函数、初始化和清除程序。

     (1)定义HY29LV160在系统中的起始地址、大小、总线宽度。

     (2)定义flash分区。根据需要对内存分区:包括用来存放uClinuX内核、根文件系统以及其它不需要更改的程序代码或数据的只读区、和用来存放需要动态存储的一些用户数据的可读写区。

     (3)Flash字节、半字、字的读写操作函数。

     (4)初始化flash函数int_initinit_s3c44b0(void)。该操作主要包括:①调用do_map_probe()检测搜索MTD设备。检测方式有:cfi_probe和iedec_probe,该方法在iedec_probe.c文件中定义。另外,jedec_probe.c中定义各种iedec_probe类型芯片信息,linux版本不包含SST39VFl60,需要手动添加;②调用add_mtd_partitions()以将your_partiton的各个分区加入mtd_table。

     (5)清除flash函数staticvoid_exitcleanup_s3c44b0(void)。该操作清除flash,是通过调用del_mtd_partitions、删除mtd_table中的MTD设备。

    结语

    目前,Flash的存储器由于其安全性高、存储密度大、体积小、价格便宜,是嵌入式领域中常用存储器。MTD为Flash和上层间提供抽象接口,可理解为Flash的设备驱动程序。通过该接口,可像读写普通文件一样对Flash设备进行读写操作。

阅读(1869) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~