嵌入式Linux系统中MMC卡驱动管理技术研究

发布者:ByteChaser最新更新时间:2012-05-17 来源: 单片机与嵌入式系统应用关键字:Linux系统  MMC卡  驱动管理技术 手机看文章 扫描二维码
随时随地手机看文章

引 言
    MMC(Multitmedia Card)是一种体积小巧、容量大、使用方便的存储器,目前在手机等嵌入式系统中有着广泛的应用。MMC通过卡内的一个集成片内控制器对MMC卡进行控制和管理,当主机正确地驱动MMC卡后,就可以像磁盘一样方便地存取数据。本文所研究与实现的Linux驱动程序,以Intel XScale的PXA250为硬件平台,在遵循MMC卡通信协议规范的基础上,实现了卡的底层读写。然后对传统的块设备驱动程序中的单块读写进行了改进,实现了集群读写技术,提高了卡的读写速度;同时增加了电源管理功能,满足了嵌入式系统低功耗的需求;增加了即插即用功能,方便了用户的使用。

1 MMC卡驱动程序的体系结构
    MMC 卡仅通过5个引脚与主机的控制器相连,通过串行协议与主机通信。MMC卡在硬件上的简单构造必然导致在实现驱动程序上的复杂。依据MMC卡的通信掷议规范和Linux驱动程序的结构,把驱动程序原有的底层驱动、守护线程、单块读写进行改进和扩展,其结构层次再划分为底层驱动、守护线程、集群读写、电源管理及热拔插管理5个部分,如图l所示。

    图1中各部分的功能为:
    ①底层驱动——处理直接涉及与MMC卡硬件寄存器端口的操作,包括:命令的发布和响应、中断响应和处理、PIO或者DMA通道数据传输等。
    ②集群读写——将磁盘相邻数据块的读写请求合并起来一起发布读写命令,以加快数据读写,并在读写中实现并发控制。
    ③电源管理——实现MMC卡的低功耗管理。 
    ④热拔插管理——实现MMC卡的即插即用功能。
    ⑤守护线程——响应文件系统的读写请求并启动对卡的1/O。

2 MMC卡驱动程序的实现
2.1 底层驱动
    底层驱动指的是直接对MMC卡进行操作。MMC卡采用串行的数据传输方式;是一种比较“精细”的卡,对它的操作比较复杂而且必须有准确的时序安排。以下从命令的发布和响应、中断响应和处理、DMA数据传输3个方面讲述如何进行底层读写驱动。

(1)命令发布和响应
    MMC卡的操作是通过对其18个控制寄存器的读写实现的。首先,设置时钟起停寄存器MMC_STRCPL的最低两位为01.关闭MMC卡内部时钟。然后,设置中断屏蔽寄存器MMC_LMASK的最低7位都为1,屏蔽所有对MMC控制器的中断,再向指定的MMC控制寄存器中写入命令参数,如时钟频率设置寄存器MMC_CLKRT,读写块数寄存器MMC_NOB,命令寄存器MMC_CMD等。最后,打开内部时钟,解除屏蔽的中断。这时,当前读写进程进入睡眠状态,等待中断处理程序的唤醒。

(2)中断响应和处理
    MMC卡在数据传输请求、内部时钟关闭、命令发布完毕、数据传输完毕的情况下都会产生中断,但足MMC卡的控制器只通过1裉GPIO23的引脚与CPU相连,用于中断信号线的复用;因此在中断处理程序中,必须首先判断到底是哪种原因产生的中断,然后再进行相应的处理。这里,MMC卡在正确发布读写命令以后,系统会产生1次中断,中断处理程序中读取MMC_IREG的值,判断命令已经发布成功,同时唤醒等待命令完成的进程。

    读写进程被中断唤醒后,首先读取MMC卡响应寄存器MMC_RES中的状态信息,再根据这些状态信息判断命令是否发布成功和卡的当前状态。如果这些状态信息表示命令执行成功,则通过读写缓冲寄存器MMC_RXFIFO和MMC_TXFIFO进行数据的读写(这里使用DMA进行数据传输,提高了数据的传输速度);如果返回的状态信息表明命令执行不成功,则根据状念信息进行相应的出错处理。

(3)DMA数据传输
    驱动程序中对MMC卡的数据读写是通过DMA通道进行传输的。为了保汪操作的连续性,驱动程序对MMC卡的输入和输出缓冲各设置1个DMA通道,在进行实际数据传输时,读写进程也进入睡眠状态,等待DMA数据传输完毕后,被DMA中断唤醒。实现一次读操作的伪代码如下:
Pxa_read_mmc(){

    关闭时钟,屏蔽中断;
    设置读写寄存器的内容; /*读写块数,起始块数,读写速度等*/
    打开时钟,发布读写命令;
    Interruptible_sleep_on(); /*进入可打断睡眠状态,等待中断程序的唤醒*/
    被中断程序唤醒,打开DMA通道,进行数据传输,再次进入可打断睡眠状态;
    被DMA传输完毕中断唤醒,发布结束传输命令,结束数据传输;

2.2 集群(clustering)读写和并发控制
2.2.1 传统的块设备驱动程序结构和不足
    块没备驱动程序是Linux系统中最复杂的驱动程序之一,参阅文献[3,4]可以详细了解Linux块设备驱动程序。这里简单介绍与集群读写相关的数据结构和操作。扇区(seetor)是块设备硬件传输数据的基本单位,而块(block)是块设备请求1次I/O操作所涉及的一组相邻扇区,每个块都需要有自己的内存缓冲区。缓冲区首部(buffer_head)是与每个缓冲区相关的数据结构,每次对块没备的I/O传输都必须经过块的缓冲区。

    Linux块没备驱动程序采取一种延迟I/O策略。当进程有I/O请求时,驱动程序延迟一段时间,把块设备上相连续的buffer_head结构关联在一起形成一个I/O请求描述符(struct request),再把request结构按照电梯算法排队到设备的请求队列(request_queue_t)。这样实际执行I/O传输时,顺次处理对应块设备的请求队列。
    对于request结构的电梯排队算法,避免由于频繁的移动磁头而导致块设备性能下降;然而,目前在Linux块设备驱动程序中,对一个request结构中的各个buffer_head结构分别发布I/O读写命令,会导致每次对一个buffer_head的输入/输出时,磁头都会停顿一段时间,进行 DMA数据读写。这样频繁的磁头启停会导致磁盘性能下降。[page]

2.2.2 集群读写的实现
    传统的块设备驱动程序中每次发布读写命令都只对一个buffer_head缓冲而导致块设备性能下降。针对这一问题,我们对传统块设备进行改进,实现了集群读写。由于每一个request结构的buffer_head结构链对应的物理块都是相邻的,因此为进行集群读写创造了条件。request结构中的 nr_sectors表示该request结构需要读写的块数。进行读写时,一次性发布读写块数为nr_seetors,读入块设备内容到requem结构指向的第一个buffer_head结构对应的内存区域。在一个buffer_head结构的缓冲区读写满了以后,就调整读写缓冲区地址为下一个 buffer_head所指向的缓冲区,同时配合DMA进行数据传输,提高了读写速度。对一个request结构操作完成以后,释放request结构资源。实现集群读操作伪码如下:
Read_mmc(){

    发布读写命令,读入的数据块数为一个rcquest一>nr_sectors的块数;
    缓冲区的指针指向第1个bh结构所指的缓冲区;
    while(数据还没有读完){
    读入数据到buffer_head结构所指定的缓冲区;/*调用Pxa_read_mmc()*/
    调整缓冲区的指针到下一个buffer_head结构所指向的缓冲区;
    }

}

2.2.3集群读写中的并发控制
    如果I/O请求队列request_queue_t是在内核中的许多地方都被访问的,则该队列就成为了临界资源。为了对该队列进行互斥保护,Linux2.4中所有的请求队列都受一个单独的全局自旋锁io_request_lock的保护。所有对清求队列的操作必须要求拥有该锁并禁止中断,然而,在驱动程序拥有这个锁的同时,其他任何读写请求不能排队到系统的任何块设备上,其他读写处理函数也不能运行。为了尽量减轻由于驱动程序长期的拥有该锁而导致系统性能下降的问题,在实现集群读写时必须遵循以下原则:

    ①对请求队列进行读写操作时要获得锁;
    ②对请求队列操作完毕后释放请求锁;
    ③为了减少占用锁的时间,可先把队列中的request结构从队列中取下来,再打开锁,然后在开锁的情况下对取下的request结构进行操作。

    基于以上原则,读/写处理函数的伪码如下所示:
mmc_request_fn()
    whilc(1){
    加锁io_request_lock;
    读取当前mmc卡请求队列的第一个请求结构request;
    释放锁io_request_lock;
    if(request为空)
    cxit(O); /*没有可以处理的队列,返回*/
    read_mmc(); /*调用集群读写函数*/
    加锁io_request_lock;
    在queue结构中取处理完毕的request结构,释放request资源;
    释放锁io_request_lock;
    }

}

2.3 守护线程
    在MMC卡驱动程序初始化的时候,启动守护线程mme_block_thread。它平时处于睡眠状态,当有对MMC卡的读/写请求时,mmc_blok_thread被唤醒。该线程调用上述读/写处理函数mmc_request_fn(),处理完毕后再进入睡眠状态。

2.4 电源管理
    嵌入式系统一般有低功耗要求,当某设备长期没有运行时,就应该停止给该设备供电,以减少电能消耗。在内核中有一个需要注册的电源管理设备的队列 pm_list,同时也有电源管理线程kpowered,它的优先级是所有运行进程中最低的。当系统长时间没有进程运行时,kpowered被唤醒,扫描 pm_list队列各个注册的设备。如果发现该设备长期没有运行,则向该设备发出PM_SUSPEND事件;而当设备重新开始使用时,则向pm_list 队列发出:PM_RESUME事件。

    在MMC卡驱动模块中注册了电源管理的回调函数mme_block_callback,即 pm_register(PM_UNKNOWN_DEV,0,mme_pm_callback)。这样MMC卡就注册到了pm_list队列中去了。当有电源事件时,就触发mmc_pm_callback函数。该函数处理各种电源事件。

    程序中的电源事件有两种:
    ①PM_SUSPEND事件。该事件使MMC卡进入省电模式。这时驱动程序保存MMC卡的当前状态和重要寄存器的内容,如时钟寄存器MMC_CLKRT和状态寄存器MMC_STAT等。然后,设置MMC卡的供电GPIO为高电平,关闭MMC卡的电源供应,没置MMC卡在时钟使能寄存器CKEN的相应位为 O,关闭MMC卡的时钟脉冲。这时,MMC卡就进入了省电模式。
    ②PM_RESUME事件。该事件使MMC卡进入正常工作模式。这时程序恢复在进入省电模式前保存的寄存器,打开电源供应和时钟脉冲,MMC卡恢复到正常的工作模式。
    当然电源事件也可以由用户进程自愿触发。在文件系统的接口file_operaion io_control中留有电源理管理接口,用户可以通过io_contol向卡发送电源事件请求。

2.5 热插拔管理
    在手机、PDA等嵌入式系统中,都要求提供对设备的即插即用功能,使用户无须安装驱动程序就可以即时使用设备。Linux在系统层和应用层都要对热插拔事件进行处理。在系统层,一方面要探测MMC卡的热插拔事件,分配或释放系统资源,并驱动MMC卡;另一方面,要将此事件准确及时地通知给应用层,应用层则根据热插拔事件作相应的处理。

    在操作系统层,需要注册一个字符型设备mmc_plug文件,用于应用层探测MMC卡的热插拔事什。CPU通过GPIO12引脚与MMC卡相连,用于卡插拔的中断探测。同时驱动程序巾设置一个信号量MMC_EVENT,它取MMC_INSERT和MMC_REMOVAL两个值。当卡插入和或者拔出时,在中断处理程序中被分别设置为MMC_INSERT和MMC_REMCOVAL;并同时传给字符设备mmc_plug,供上层的应用程序使用。为了让应用层能够知晓卡的拔插事件,在字符设备mmc_plug使用异步I/O机制poll,需要接收内核拔插事件的进程通过poll在一个等待队列上睡眠,当有卡拔插事件时产生中断,中断处理程序唤醒在队列上等待的进程。上层进程在被唤醒后就读取字符设备,获取所发生的事件。

    在应用层,进程通过select机制监听MMC卡所发生的热插拔事件,在没有拔插事件的时候,进程进入阻塞状态,让出CPU资源;当发生热拔插事件时,系统唤醒通过poll加入到等待队列中的进程,然后应用层通过read函数得到MMC卡的热插拔事件,进行相应的应用层处理。当然,应用层也可以通过 write方法通知系统层对卡进行处理。

结语
    本文研究实现的MMC卡驱动程序,其实现的集群读写证明有稳定而较高的读/写速度;增加了电源管理功能,降低了电源的功耗,满足了嵌入式系统低功耗的要求;增加的即插即用功能,大大方便了用户的使用。驱动程序的体系结构是实现嵌入式系统块设备驱动的一种好方法。

关键字:Linux系统  MMC卡  驱动管理技术 引用地址:嵌入式Linux系统中MMC卡驱动管理技术研究

上一篇:嵌入式LINUX系统的静/动态集成调试模式
下一篇:基于MiniGUI的多进程图形用户界面的研究

推荐阅读最新更新时间:2024-03-16 12:59

基于51单片机的SD读卡器MMC存储器
硬件设计 程序设计 #include reg52.H #define F_OSC 11059200//晶振平率Hz #define F_BAUD 9600 #define RELOAD 256-F_OSC/12/32/F_BAUD #define CR 0x0D //回车 //定义SD卡需要的4根信号线 sbit SD_CLK = P1^4; sbit SD_DI = P1^6; sbit SD_DO = P1^5; sbit SD_CS = P1^7; unsigned char xdata DATA ; //定义512字节缓冲区,注意需要使用 xdata关键字 //=================
[单片机]
基于51单片机的SD<font color='red'>卡</font>读卡器<font color='red'>MMC</font>存储器
OK6410A 开发板 (八) 117 linux-5.11 OK6410A linux系统调用
访问内核空间,linux提供了系统调用,分为多类, 1.文件系统相关的接口open,read,等file_operations中的接口(具体有什么,看具体文件系统) 2.进程控制 3.进程通信 4.内存管理 5.系统控制 reboot 6.用户管理 如何查看当前运行或者编译的 linux系统中有多少个 系统调用,以及分别是什么 编译时 : cat System.mmap |grep sys_ , 这里面不仅包括系统调用,还有一些其他的东西,例如 sys_mmap_pgoff // 注意:sys_mmap_pgoff 不是 系统调用 编译时 : arch/arm/kernel/e
[单片机]
Linux系统初学者的常见问题解决集结大全
一、 如何建立多用户 提醒大家一句,别一直使用root用户,因为root用户在系统中有着至高无上的权力,一不小心就可能破坏系统。比如我们想删除/temp目录下的文件却将命令不小心输成“rm / temp(在‘/’后多了一个空格)”,那么就极可能删去根目录下的所有文件。 再者,“Linux是一个真正意义上的多任务、多用户系统”,不体会一下Linux的特色岂不可惜。为了方便自己和别人使用,就在Linux系统下多建几个用户吧。 输入“adduser newuser”,回车,屏幕对命令没有一点儿反应,错啦?不,实际上,系统已接受了新用户。你应该接着输入命令 “passwd newuser”,屏幕将提示输入口令,再次输入确认
[嵌入式]
基于ARM920T的嵌入式Linux系统的构建
前言 目前,嵌入式操作系统的种类很多,如VxWorks,Windows CE和Linux等。在这些操作系统中,Linux是发展最快,应用最广泛的。由于使用费用、开放源代码程度和使用习惯等各方面因素,Linux是得到较多推广的操作系统之一。由于Linux支持从x86到嵌入式处理器的多种处理器,使得Linux桌面PC上开发的很多资源可以轻松的移植到各种嵌入式平台上,这种便利使得在嵌入式系统中使用Linux操作系统具有很大吸引力。 开发环境 硬件环境 本系统中使用目标平台S3C2410(SAM SUNG公司使用ARM920T处理器内核开发的一款嵌入式处理器)。ARM920T核由ARM9TDMI,存储管理单元(MM
[单片机]
基于ARM920T的嵌入式<font color='red'>Linux系统</font>的构建
ARM linux系统调用的实现原理
  大家都知道linux的应用程序要想访问内核必须使用系统调用从而实现从usr模式转到svc模式。下面咱们看看它的实现过程。   系统调用是os操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。   at91rm9200处理器对应的linux2.4.19内核系统调用对应的软中断定义如下:   #if defined(__thumb__) //thumb模式   #define __syscall(nAME) \\   "push {r7} \\t" \\   "mov r7, #" __sys1(__NR_##name) " \\t"
[单片机]
s3c2440上MMC/SD驱动的分析(一)
一、开发环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二、MMC/SD介绍及SDI主机控制器 首先我们来理清几个概念: MMC:(Multi Media Card)由西门子公司和首推CF的SanDisk于1997年推出的多媒体记忆卡标准。 SD:(Secure Digital Memory Card)由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制的新一代记忆卡标准,已完全兼容MMC标准。 SDIO:(Secure Digital Input and Output
[单片机]
基于Linux系统的软PLC设计
引言 可编程控制器(PLC,Programmable LogicController)经过几十年的发展,现在已经成为了最重要、最可靠、应用场合最广泛的工业控制微型计算机。然而,人们在使用过程中也逐渐发现了传统PLC的缺点:兼容性差,由于生产厂家众多,各种机型互不兼容,没有统一的标准,难以构造统一的硬件结构;封闭、扩展能力差:产品能力的功能实现依赖硬件;对使用者的要求高:现行的PLC 产品,其编程方式要求使用者对PLC的硬件结构、电器原理、编程指令都要有相当的了解;可维护性差:PLC 出现故障时需要专业人员用专业工具进行检测和维修;成本较高,传统PLC 被几家厂商所垄断,性价比增长缓慢。这些问题都制约着传统PLC 的发展。近年来,
[工业控制]
Linux系统下USB摄像头驱动开发
USB摄像头以其良好的性能和低廉的价格得到广泛应用。同时因其灵活、方便的特性,易于集成到嵌入式系统中。但是如果使用现有的符合Video for Linux标准的驱动程序配合通用应用程序,难以充分利用USB带宽,帧速不高,不易满足实时监控等要求。本文首先介绍在Linux系统下USB摄像头驱动编制的一般方法,然后说明在此基础上如何提高帧速。 1 Linux系统中的USB摄像头驱动程序 USB设备驱动程序完全符合通用设备驱动的准则,不同的是内核提供了一些特别的API函数,方便驱动注册、销毁自己,例如usb_reSister()和usb_dereSister();2.4版的内核还提供了对于hotplug的支持。 1.1 USB摄像头
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved