加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > 单片机学习

嵌入式Linux 中CF卡的驱动和管理技术研究

时间:2013-09-08  来源:123485.com  作者:9stone
       在嵌入式Linux系统中,为了在没有PCMCIA控制器的情况下仍然要利用CompactFlash存储卡(简称CF卡)作为存储设备,作者从CF卡的硬件特性入手,在系统层基于CF卡的memory寻址访问方式来改造CF卡的低层驱动,并在应用层实时管理CF卡的热插拔事务,最终实现了一个利用CF卡作为方便快捷的存储设备的嵌入式Linux系统。
1  引言
近年来,形式多样的嵌入式数字化产品已经开始成为继PC机之后的一大信息处理工具。这些产品大都需要数据的转储和备份功能。Flash存储卡由于其存储密度高、易于编程和再编程、读写速度快、成本低等特征而成为嵌入式系统中一种比较理想的存储设备。CompactFlash存储卡(简称CF卡)是目前嵌入式系统中应用最为广泛的flash存储卡。目前对CF卡的大多数应用,都是用一个PCMCIA控制器来实现对CF卡的操作。然而在嵌入式系统中,硬件设计应该尽可能简单,从而降低成本,以至许多嵌入式Linux系统中没有PCMCIA控制器而仍然利用CF卡作为存储设备。此时CF卡是如何工作的了?这就是本文主要探讨的问题。
2  CF卡的硬件特性
CF卡通过一个50引脚的连接器与主机相连。在CF卡内,有一个集成的片上控制器,这个控制器管理着接口协议、数据存储和恢复、错误处理和诊断、电源管理和时钟控制。当主机正确地驱动CF卡后,用户就可以像使用磁盘一样方便地利用CF卡存储数据。
一般地,CF卡分为3种寻址访问模式,每一种模式在系统上反映为如何来访问其地址空间。通过对CF卡的属性存储空间进行配置,可以得到CF卡的不同的寻址访问模式:
(1) I/O
模式:通过访问CF卡的内部IO寄存器所指向的16字节数据块,实现对CF卡的通用存储空间进行寻址访问,一般利用系统提供的中断进行读写事务处理。
(2) Memory
模式:将CPUCF卡的地址线和数据线进行直连,通过访问其通用存储空间的16字节数据块来实现对CF卡的寻址访问。
(3) True IDE
模式(与大多数磁盘驱动器兼容):将标准的PC-ATA磁盘I/O寻址空间1F0h-1F7h3F6h-3F7h (primary)或者 170h-177h 376h-377h (secondary)作为寻址端口, 同时使用中断IRQ14 (或者其他可用的IRQ)进行事务处理。
其中,CF卡控制器在Memory模式下能够最快地响应操作命令。该模式较好地满足了嵌入式系统的实时性要求,而且在此模式下CF卡插槽结构简单,设计成本低,因此本文选择Memory寻址模式进行研究。
3 系统设计
本文以ARM系列的EP7312[2]为模板,用Linux作为操作系统,开发了用CF卡作为其存储设备的嵌入式系统。该系统用一个50针的简单插槽,将CF卡的地址线和数据线与CPU直接相连,从而省去了PCMCIA控制器。CF卡的驱动程序主要是改造Linux中原有的IDE程序,不使用中断事务处理方式,让CF卡在Memory模式下进行8位寻址。同时,该系统用一个后台程序来管理CF卡的热插拔事务。图1给出了系统中CF卡的驱动程序结构图。
3.1 CF卡的配置                                           
在对CF卡进行存储操作之前,驱动要对它进行必要的配置。
首先,驱动在系统中设置传输CF卡信号的GPIO,并为其分配好寻址用的IO端口。在Memory模式下,CF卡的IO端口即为其通用存储空间的16字节数据块。
其次,对CF卡的属性存储空间进行配置。CF卡有48位属性寄存器:属性选项寄存器:(BASE + 00H)、卡配置和状态寄存器:(BASE + 02H)、针替换寄存器:(BASE + 04h)、套接字拷贝寄存器:(BASE+ 06h)。它们的基址(BASE)为属性存储空间中的200H。由于CF卡在系统中使用Memory模式,且没有用到中断,故将属性选项寄存器配置为0x00。其他属性寄存器一般保持默认值,配置状态寄存器、针替换寄存器、套接字拷贝寄存器的默认值分别为0x800x2e0x00。为保证能够在Memory方式下正确地使用CF卡,驱动要对这些属性寄存器的值进行验证,若这些值与默认值不匹配,则要将其值设置为默认值。
3.2 CF卡的底层驱动
要实现CF卡的存储备份功能,则要求CF卡必须能够正确地接收并响应系统对它的I/O请求;这主要通过CF卡的底层驱动来实现。
3.2.1 发布ATA命令
首先,驱动要正确地接收系统对CF卡的I/O请求,进而向CF卡发布ATA命令。CF卡的ATA命令集分为3。每类命令都要求CF卡在接收到命令时处于不忙(BSY=0)状态且有数据请求(DRQ=1)时才能处理CF卡缓冲区中的数据流,如读(0x20)、写(0x30)、擦除(0xc0)、格式化(0x50)等命令。
CF卡发布ATA命令,首先要填写CF卡的命令控制块。在发布读写命令时,要注意CF卡的寻址方式。CF卡支持C/H/SCylinder/Head/Sector)和LBALogical Block Addressing)寻址模式。
Head       Sector     Cylinder High    Cylinder Low
27     24   23     16  15        8   7       0Bit

由于CF卡是一种大容量的存储设备(市场上已经有容量为4GBCF卡),因此,这里用LBA寻址模式来访问CF卡。寻址模式的选择通过ATA寄存器组中的Drive/Head寄存器来配置。根据I/O请求得到CF卡的块号block,利用该块号来计算CF卡的LBA地址。取block的低28位,依次对应CF卡的柱面低位寄存器、柱面高位寄存器、扇区寄存器、设备/磁头寄存器,如图2所示。将这些参数值和ATA命令值按8位方式写入相应寄存器中,即完成了一次ATA命令发布。
CF
卡的其他ATA命令发布方式与读写命令类似,这里就不再讨论。

3.2.2
命令响应
在填写ATA命令控制块后,CF卡要对这些命令做出响应,如读写命令要求从CF卡内读写数据等。如何处理CF卡的这些命令响应是关键。将CF卡中通用存储空间的I/O端口注册于IDE管理程序,利用IDE的磁盘管理程序来管理CF卡的命令请求。但是,IDE管理是利用中断来响应对各个设备的命令请求的,而CF卡在Memory方式下发送完ATA命令后没有产生中断,也就是说在硬件上CF卡的Memory方式没有可利用的中断。这就要求采用不同于通用IDE管理的命令响应处理方式。
可以利用轮询的方法来处理命令响应。在发送完ATA命令后,IDE管理程序设置相应于该命令的处理函数,并立即进入命令该处理函数。在各个命令处理函数内部,通过定时轮询的方式查看CF卡的状态寄存器。若CF卡的状态与命令状态匹配,则进行相应的数据处理。如:发送的是读命令且探测到CF卡的状态位中有数据请求且CF卡不忙,就立即按8位方式进行操作,将CF卡的数据寄存器上的数据串行化输出到系统缓冲区中。若CF卡的状态与命令状态不匹配,则继续等待;超时则进入出错处理。

3.2.3
出错处理
     在发布完ATA命令后,由于受外部环境(如CPU负荷高、自然条件恶劣等)的影响,以及CF卡内在电气特性的某种不稳定性,都可能造成CF卡没有接收到该命令或者接收命令出错。尽管发生出错的概率很低,但驱动仍应该应对这种偶然情况进行处理。一方面,IDE管理程序应该返回到对CF卡发送命令之前的状态,以便重新发送该ATA命令。这一点在IDE管理程序中已经实现。另一方面,CF卡本身要恢复到一般正常状态,以便重新接收ATA命令。这又可以有两种方法。一种是通过IDECF卡发送 Reset 信号,这要求CF卡从硬件上支持。另一种是纯软件方式。CF卡的属性选项寄存器有一个SRESET位,通过读写该寄存器,可以达到让CF卡实现软重置的目的。但有一点需要注意的是,在将该寄存器中SRESET置位后,等待一段时间后仍应该将其恢复到初始状态,这样才能达到软重置的目的。为了节约硬件成本,这里采用软重置的方法。

3.2.4
文件组织
在系统中将CF卡作为块设备进行注册。由于DOS文件系统的通用性,采用VFAT16位的DOS)文件系统对CF卡上的内容进行组织。驱动为文件系统提供应用接口[3],即标准的IDE文件操作,包括打开、释放、IO控制等,它们面向文件系统对CF卡的数据请求。
3.3 对热插拔事件的管理
嵌入式存储设备的一大特色就是能够做到即插即用。系统只有准确、及时地响应热插拔事件,才能方便快捷地实现存储卡的存储备份功能。在Linux中,系统层和应用层都要对热插拔事件进行处理。在系统层,一方面要探测CF卡的热插拔事件,分配或释放系统资源,并驱动CF卡;另一方面,要将此事件准确及时地通知给应用层。应用层则根据热插拔事件作相应的处理,给用户提供相应于CF卡的方便、快捷的用户接口。
因此,下面分别在操作系统层和应用层进行设计来实现热插拔管理。

3.3.1
操作系统层
为方便CF卡的热插拔管理,在操作系统层注册一个字符型设备CF_MGR文件。
1)探测热插拔事件
探测CF卡的热插拔事件,可以利用中断或者定时器。中断固然能够实时地检测CF卡的热插拔事件,但它需要硬件上的支持。结合嵌入式硬件尽量简单的特点,这里用定时器技术来探测CF的热插拔事件。
REG_FLAG
DETECT_FLAG
事件
1
1
CF卡拔出
1
0
无事件,CF卡在插槽中
0
0
CF卡插入
0
1
无事件,CF卡不在槽中
系统定时检查两个信号量,利用这两个信号的值来判断CF卡的插入拔出事件。一个是CF卡注册标志(REG_FLAG),初始值为0。当CF卡插入并被驱动后,REG_FLAG变为1;当CF卡拔出并被卸载后,REG_FLAG变为0。另一个信号值(DETECT_FLAG)反映连接在CF卡插槽上的CD1CD2信号值。这是从硬件上来实现的:当CF卡在插槽中时,DETECT_FLAG0;而当CF卡不在插槽中时,DETECT_FLAG1。通过REG_FLAGDETECT_FLAG的值的组合,管理设备来判断所发生的CF卡的热插拔事件及其状态,如表1
2)与应用层通信接口
Linux进程可以转入休眠状态以等待某个特定事件,当该事件发生时这些进程能够被再次唤醒。内核实现这一功能的技术要点是把等待队列(wait queue)和每一个事件联系起来。CF_MGR管理文件初始化一个等待队列,以备将CF卡的热插拔事件通知给其他进程。当系统定时检查出热插拔事件时,就唤醒该等待队列。内核遍历相应队列,唤醒休眠的任务让它投入运行状态。
管理设备通过一系列文件操作跟应用层通信,如openreleasereadpollioctl等。其中,read用来将要处理的CF卡的热插拔事件传递给应用层,write反馈应用层处理完的事件,而poll将管理设备的等待信号插入等待队列,以便发生热插拔事件时唤醒该等待队列,并返回该设备可读的信息。
3.3.2 应用层
良好的用户接口是嵌入式存储设备能否便于使用的关键。在应用层,一方面程序要及时监CF卡所发生的热插拔事件,另一方面,在没有任何事件发生的情况之下应该停止程序的运行,让出抢占的系统资源,进入阻塞状态,让程序最小程度的占用CPU 资源。为达到此目的,采用Linux中的Select阻塞机制。
首先将CF卡系统层的管理设备的文件描述符加入到Select文件描述符集合中,然后阻塞这些文件描述符。当发生热插拔事件时,系统层唤醒poll加入到等待队列中的等待信号,并将该设备文件可读的信息传给应用层。然后应用层通过read函数得到CF卡的热插拔事件,调用应用层事件处理器,并将该事件通过write反馈到系统层。这样,就完成了一个Select循环。应用层通过Select阻塞方式可以及时地探测到CF卡的热插拔事件。
应用层事件处理器负责将CF卡的当前的状态信息提供给用户,并给用户进行方便、快捷的存储管理提供接口。一方面,当发生CF卡插入事件时,将CF卡挂接到指定目录下;另一方面,当发生CF卡拔出事件时,将文件系统设置到一个安全的状态,并释放所用到的CF资源。
4 结论
通过以上系统设计,CF卡在此嵌入式系统中实现了如下功能:支持VFAT文件系统,让CF卡在各种系统中通用,真正实现转储功能;根据硬件设计要求,实现memory方式访问;根据已有的总线宽度,按8位方式对数据进行访问;能够方便地对CF卡进行热插拔。

分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->单片机学习
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门