注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

我的博客

笨笨猫

 
 
 

日志

 
 

关于linux 2.6 mmc/sd驱动  

2011-07-19 14:39:32|  分类: s3c-linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
关于linux 2.6 mmc/sd驱动

    linux 2.6 中的mmc/sd驱动分为以下几方面的内容
        1. sysfs 层的总线类型处理: 注册一组 mmc 类型处理函数, 标志为 "mmc"
        2. mmc/sd 快设备管理:注册一个块设备和一组 mmc 总线类型的 driver 子函数, 实现块设备的队列管理等
        3. mmc/sd host管理: 实现 host 的管理
        4. 针对特定的mcu实现一个host驱动实例:主要是注册一个 host实体,中断处理函数,io设置函数,请求处理函数等
     
    以上1.2.3基本是不需要修改的,需要处理的就是 4.要做的工作.当有卡插入时,由4中实现的插卡中断激活卡初始化程序和总线探测函数. 由mmc总线探测函数会调用块设备的探测函数,在卡设备探测函数中会初始化块设备的请求队列和注册一个gendisk实体(以后文件系统会通过gendisk实体访问 mmc 块设备),同时在sysfs中建立真正的 mmc/sd 设备.块设备通过具体的 host 注册的io设置函数和请求函数与具体的host通讯.

Host与Card两种工作模式:
卡识别模式:
host在reset后将处于卡识别模式,并开始寻找总线上的新卡;
Card在reset后将一直处于此种模式直到收到SET_RCA命令(CMD3)

数据传输模式:
Card一旦收到RCA信号将进入数据传输模式,Host在识别出总线上所有的
卡后将进入数据传输模式

MMC/SD命令格式:
command :48bits 6B
start bit|transmission bit|command index|argument|crc|end bit

CMD1: GO_IDLE_STATE
CMD4:SET_RELATIVE_ADDR
CMD7:SET_DSR
CMD8:SELECT/DESELECT_CARD
CMD9:SEND_CSD
CMD10:SEND_CID
CMD12:STOP_TRANSMISSION
CMD13:SEND_STATUS
CMD16:SET_BLOCKLEN
CMD17:READ_SINGLE_BLOCK
CMD18:READ_MULTIPLE_BLOCK

Response:
R1,R3,R6:
start bit:0|transmission bit:0:card response|Response content:|end bit:1
total:48bit
response content:
R1 response:status information
R3 response:OCR reg
R6: RCA

R2:格式类上面,但content=cid or csd total length=136 bits

RCA reg在SPI模式下是不可用的

SD卡要有6个寄存器:但有一个是可选的
CID: must
RCA:must
DSR:optional 用于配置卡的输出驱动能力
CSD: must 卡特殊数据寄存器
SCR:must 卡配置寄存器
OCR:操作条件寄存器

SD卡无外部reset信号,上电后直接进入预先定义好的状态,然后一个CMD0实现软reset

当MMC Host有Card插入时,检测是否为存储卡,如果是存储卡,为此卡申请
请求队列处理函数及gen_disk,并向系统注册为一个块设备

根据MMC Host硬件控制器,实现并注册一个Host到MMC Core中

控制器驱动通过mmc_host_ops的函数指针来完成硬件相关操作

底层驱动指的是直接对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.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向卡发送电源事件请求

热插拔管理

  在手机、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卡驱动程序,其实现的集群读写证明有稳定而较高的读/写速度;增加了电源管理功能,降低了电源的功耗,满足了嵌入式系统低功耗的要求;增加的即插即用功能,大大方便了用户的使用。驱动程序的体系结构是实现嵌入式系统块设备驱动的一种好方法。
  评论这张
 
阅读(997)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017