ImageVerifierCode 换一换
格式:DOCX , 页数:29 ,大小:252.90KB ,
资源ID:23275229      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/23275229.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(SD密码卡驱动程序设计.docx)为本站会员(b****1)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

SD密码卡驱动程序设计.docx

1、SD密码卡驱动程序设计 SD密码卡驱动程序设计指南SD卡(Secure Digital Memory Card),安全数码卡,是一种基于Flash的新一代存储设备,被广泛地用于便携式设备,例如移动电话、数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡拥有体积小,容量大、数据传输快、移动灵活及安全等优点。因其价格低廉,应用也越来越广泛,本章将重点介绍其驱动分析和移植过程。1.1 SD卡简介SD存储卡是专门为满足安全、大容量和内置于消费者的新型语音和视频电子设备中而设计的。SD内存卡将包含的机械保护装置,遵循SDMI标准,具有安全、快速、大容量等特性。SD卡的安全系统采用相互认证和“新密码

2、算法”以防止卡中的内容被非法使用。下面将从以下几个方面简单介绍SD卡协议内容。1.1.1 SD卡系统概念下面分别描述SD卡的读写特性、容量、速度、电压等特性和分类。 读写特性:根据读写特性可以将SD卡分为两种。一种为读/写卡,这种卡生产出来就是一张空白卡,专门用于记录用户的视频声音、图像的大容量记忆卡;另一种为只读卡,这种卡在制造时就定制了内容,其典型的应用是在软件、音频或视频等的发行媒体中。 支持电压:根据支持的电压可以将SD卡分为高电压SD卡和双重电压SD卡两类。 卡容量:根据卡的容量大小将SD分为两类型。一类为标准容量的SD卡,其支持的容量上线为2GB,包括2GB在内;另一种为高容量SD

3、卡,其容量超过2GB,最大可达32GB。 速度:根据速度类可以将SD卡分为4种速度类。类0,这种类型卡兼具所有类型的优点;类2,其速度大于等于2MB/S;类4,其速度大于等于4MB/S;类6,其速度大于等于6MB/S。高容量SD卡支持速度类描述,其性能相当于或超过类2。1.1.2 SD卡寄存器每张卡都有一系列寄存器的信息,寄存器的信息如表1.1所示。表1.1 SD卡寄存器信息名字宽 度描 述CID128卡识别号,每张卡都有唯一的识别号RCA16发布卡的地址,卡的局部系统地址,在初始化过程中,由主机和卡动态支持DSR16驱动级寄存器,配置卡的驱动输出CSD128卡的协议数据,关于卡的操作状态数据

4、SCR64卡配置寄存器,关于卡特性容量的信息OCR32操作状态寄存器SSR512SD状态,有关卡拥有的特性信息CSR32卡状态,有关卡状态的信息1.1.3 SD功能描述主机与卡之间的通信都是由主机控制的,主机发送的命令有两种类型,分别为广播命令和地址(点对点)命令。 广播命令:该命令是发给所有的卡,有些广播命令需要响应。 地址(点对点)命令:这些命令发往具体地址的卡,并且从这些卡生成响应。 卡识别模式:主机被复位或者在总线上寻找新卡时,主机处于该状态下。卡在复位以后和收到SEND_RCA命令以前都处于此模式下。 数据传输模式:卡在它们的RCA第一发布后进入数据传输模式。主机识别总线上所有的卡后

5、进入数据传输模式。下面通过表1.2说明卡的状态与操作模式之间的依赖关系,SD的每种状态都关联一种操作模式,其状态图将在随后进行介绍。表1.2 卡的状态和操作模式的对应关系卡 状 态操 作 模 式无活动状态无活动空闲态卡识别模式准备态识别态等待态数据传输模式传输态发送数据态接收数据态编程态断开态1操作状态的验证通过一系列过程后,主机才能识别卡。下面给出它们的通信过程。 在主机和卡通信前,主机不知道卡支持的电压,卡也不知道是否支持主机当前提供的电压。主机将发布一个复位命令(CMD0),带着它能提供给卡的电压信息。 为了验证SD卡的接口操作状态,主机发送SEND_IF_COND(CMD8),SD卡通

6、过分析SEND_IF_COND命令参数检查操作状态的有效性,主机通过检查SD分析后的响应来判断电压的有效性。 如果SD能够操作在提供的电压下,则发回的响应带上提供的电压,且检验模式被设置在命令参数中。如果SD卡不支持主机提供的电压,则不响应且保持在空闲态下。在发送ACMD41命令初始化高容量SD卡前,强制发送CMD8命令。 强制低电压主机在发送CMD8前发送ACMD41。万一双重电压SD卡没有收到CMD8命令且工作在高电压状态,在这种情况下,低电压主机不发送CMD8命令给卡,则收到ACMD41后进入无活动状态。 SD_SEND_OP_COND(ACMD41)命令是为SD卡主机识别卡或电压不匹配

7、时拒绝卡的机制而设计的。主机发送命令操作数代表要求的电压窗口大小。如果SD卡在所给的范围内不能实现数据传输,将放弃下一步的总线操作而进入无活动状态。操作状态寄存器也将被定义。 在主机发出复位命令(CMD0)后,主机将先发送CMD8再发送ACMD41命令重新初始化SD卡。卡的识别模式的状态可以用下面的状态图1.1表示。图1.1 卡在识别模式下的命令流程2卡的初始化和识别处理当总线被激活后,主机就开始卡的初始化和识别处理。初始化处理设置它的操作状态和设置OCR中的HCS比特位命令SD_SEND_OP_COND(ACMD41)开始。HCS比特位被设置为1表示主机支持高容量SD卡。HCS被设置为0表示

8、主机不支持高容量SD卡。3数据传输模式卡的识别模式结束后,主机时钟fpp(数据传输时钟速率)将保持为 fOD(卡识别模式下的时钟),因为有些卡对操作时钟有限制。主机必须发送SEND_CSD(CMD9)来获得卡规格数据寄存器内容,如块大小、卡容量等。广播命令SET_DSR(CMD4)配置所有识别卡的驱动阶段。它对DSR寄存器进行编程以适应应用总线布局、总线上的卡数目和数据传输频率。SD卡数据传输模式下的状态图,如图1.3所示。1.2 SD卡驱动程序分析SD卡驱动程序包括驱动的注册和注销、设备接口函数和I/O操作。在linux-2.6.29内核MMC子系统中支持SD卡驱动。本节对MMC源码进行分析

9、,后面将介绍SD卡驱动移植过程。MMC子系统在driver/mmc目录下进行描述,该目录下包括host、core、card这3个文件夹,下面分别对这3个部分进行介绍。1.2.1 host驱动部分host驱动部分是针对不同类型主机的驱动,支持的开发板包括atmel、S3C等。这里就以S3C系统为例介绍host部分的主要内容。1驱动的注册函数驱动的注册函数s3cmci_init(),用于注册平台设备驱动。static int _init s3cmci_init(void) platform_driver_register(&s3cmci_2440_driver); /注册平台设备驱动 return

10、 0;2驱动注销函数驱动注销函数s3cmci_exit(),用于注销平台设备驱动。static void _exit s3cmci_exit(void) platform_driver_unregister(&s3cmci_2440_driver); /注销平台设备驱动3接口函数平台设备接口函数包括probe、remove、shutdown、suspend、resume。其结构如下:static struct platform_driver s3cmci_2440_driver = .driver.name = s3c2440-sdi, .driver.owner = THIS_MODULE,

11、 .probe = s3cmci_2440_probe, .remove = _devexit_p(s3cmci_remove), .shutdown = s3cmci_shutdown, .suspend = s3cmci_suspend, .resume = s3cmci_resume,;4探针函数探针函数s3cmci_probe(),用于分配s3cmci_host结构体,然后对该结构体进行设置。对结构体mmc_host进行设置,将结构体mmc添加到主机。static int _devinit s3cmci_probe(struct platform_device *pdev, int i

12、s2440) struct s3cmci_host *host; struct mmc_host *mmc; int ret; /*为主机设备分配空间*/ mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev-dev); if (!mmc) ret = -ENOMEM; goto probe_out; /*对host结构体各个字段进行设置*/ host = mmc_priv(mmc); host-mmc = mmc; host-pdev = pdev; host-is2440 = is2440; /*设置平台数据*/ host-pdata

13、 = pdev-dev.platform_data; if (!host-pdata) pdev-dev.platform_data = &s3cmci_def_pdata; host-pdata = &s3cmci_def_pdata; /*初始化自旋锁,自旋锁在使用前应该被初始化*/ spin_lock_init(&host-complete_lock); /*函数tasklet_init ()用于初始化一个tasklet,参数pio_tasklet是软中断响应函 数*/ tasklet_init(&host-pio_tasklet, pio_tasklet, (unsigned long

14、) host); /*结构体参数设置*/ host-sdiimsk = S3C2440_SDIIMSK; host-sdidata = S3C2440_SDIDATA; host-clk_div = 1; host-dodma = 0; host-complete_what = COMPLETION_NONE; host-pio_active = XFER_NONE; host-dma = S3CMCI_DMA; /*获取平台资源信息*/ host-mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); /*该函数的任务是检查申请的资源是否可

15、用,如果可用则申请成功,并标志为已经使用,其他 驱动想再申请该资源时就会失败*/ host-mem = request_mem_region(host-mem-start, RESSIZE(host-mem), pdev-name); /*系统在运行时,外设的I/O内存资源的物理地址是已知的,由硬件的设计决定。但是CPU 通常并没有为这些已知的外设I/O内存资源的物理地址预定义虚拟地址范围,驱动程序并不能 直接通过物理地址访问I/O内存资源,而必须将它们映射到内核虚地址空间内(采用页表), 然后才能根据映射所得到的内核虚地址范围,通过访内指令访问这些I/O内存资源。*/ host-base =

16、 ioremap(host-mem-start, RESSIZE(host-mem); /*获取设备的中断号*/ host-irq = platform_get_irq(pdev, 0); if (host-irq = 0) dev_err(&pdev-dev, failed to get interrupt resouce.n); ret = -EINVAL; goto probe_iounmap; /*向系统申请中断*/ if (request_irq(host-irq, s3cmci_irq, 0, DRIVER_NAME, host) dev_err(&pdev-dev, failed

17、 to request mci interrupt.n); ret = -ENOENT; goto probe_iounmap; /*关闭中断*/ disable_irq(host-irq); /*给定端口号转换为中断号*/ host-irq_cd = s3c2410_gpio_getirq(host-pdata-gpio_detect); /*添加irq_cd的中断号为IRQ_EINT16且设置GPG8脚为16号中断的输入引脚*/ host-irq_cd = IRQ_EINT16; s3c2410_gpio_cfgpin(S3C2410_GPG8, S3C2410_GPG8_EINT16);

18、 /*获取dma通道的控制权*/ s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL); /*获取时钟响应给时钟的生产者producer()*/ host-clk = clk_get(&pdev-dev, sdi); /*当时钟源运行的时候通知系统,参数host-clk 为时钟源*/ clk_enable(host-clk); /*获得当前时钟频率*/ host-clk_rate = clk_get_rate(host-clk); /*下面是对mmc结构体参数的设置*/ mmc-ops = &s3cmci_ops; mmc-ocr_

19、avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc-caps = MMC_CAP_4_BIT_DATA; mmc-f_min = host-clk_rate / (host-clk_div * 256); mmc-f_max = host-clk_rate / host-clk_div; if (host-pdata-ocr_avail) mmc-ocr_avail = host-pdata-ocr_avail; mmc-max_blk_count = 4095; mmc-max_blk_size = 4095; mmc-max_req_size = 4095

20、 * 512; mmc-max_seg_size = mmc-max_req_size; mmc-max_phys_segs = 128; mmc-max_hw_segs = 128; /*注册带CPU频率的host驱动*/ s3cmci_cpufreq_register(host); /*初始化mmc*/ mmc_add_host(mmc); /*设置驱动数据*/ platform_set_drvdata(pdev, mmc); return 0;5mmc接口函数mmc子系统的接口函数包括request、set_ios、get_ro、get_cds。其结构如下:static struct m

21、mc_host_ops s3cmci_ops = .request = s3cmci_request, /实现命令和数据的发送 .set_ios = s3cmci_set_ios, /根据核心层传来的ios来设置硬件IO .get_ro = s3cmci_get_ro, /从GPIO口读取,判断卡是否写保护 .get_cd = s3cmci_card_present, /从GPIO口读取,判断卡是否存在;6传递结构体为mmc_request类型的请求函数s3cmci_request()用于CORE部分发送mrq请求。static void s3cmci_request(struct mmc_h

22、ost *mmc, struct mmc_request *mrq) struct s3cmci_host *host = mmc_priv(mmc); host-status = mmc request; host-cmd_is_stop = 0; host-mrq = mrq;/*如果卡准备就绪,则通过s3cmci_send_request ()发送请求,将mrq赋给host-mrq,如果卡没有准备就绪,则调用mmc_request_done ()终止请求*/ if (s3cmci_card_present(mmc) = 0) dbg(host, dbg_err, %s: no mediu

23、m presentn, _func_); host-mrq-cmd-error = -ENOMEDIUM; mmc_request_done(mmc, mrq); else/*函数s3cmci_send_request ()首先判断是否为发送数据命令,如果为发送数据则通过函数s3cmci_send_request ()建立数据,然后判断是否为dma方式,如果为dma方式则通过dma方式发送数据,否则采用fifo方式发送数据。如果为命令则通过函数s3cmci_send_command()发送命令*/ s3cmci_send_request(mmc);1.2.2 core驱动部分core驱动部分完

24、成不同协议和规范的实现,包括设置在1.1节中介绍的有关SD卡相关的状态或修改状态、修改寄存器等操作。1用于卡的探测和初始化函数mmc_sd_init_card()在重启时,函数mmc_sd_init_card()参数oldcard中包含准备初始化的卡,该函数检测卡的有效性,并对该卡初始化。该函数首先让卡的状态回到空闲态,然后设置操作状态寄存器,接着进行SD卡主机识别或电压匹配,正确识别和匹配后,读取卡的识别号;比较读取的CID与原来的CID是否相同,不相同则需要重新为卡分配结构体;最后对卡进行设置和初始化。static int mmc_sd_init_card(struct mmc_host

25、*host, u32 ocr, struct mmc_card *oldcard) struct mmc_card *card; int err; u32 cid4; unsigned int max_dtr; BUG_ON(!host); WARN_ON(!host-claimed); /*改变状态寄存器OCR的值时,需要卡的状态回到空闲态。等待1ms让卡响应*/ mmc_go_idle(host); /*SD_SEND_IF_COND是用于验证SD卡接口操作状态的有效性命令(CMD8)。如果 SD_SEND_IF_COND指示为符合SD2.0标准的卡,则设置操作状态寄存器ocrbit30指

26、示能 够处理块地址SDHC卡*/ err = mmc_send_if_cond(host, ocr); if (!err) ocr |= 1 raw_cid, sizeof(cid) != 0) err = -ENOENT; goto err; card = oldcard; else /*为卡分配结构体*/ card = mmc_alloc_card(host, &sd_type); if (IS_ERR(card) err = PTR_ERR(card); goto err; /*设置卡的类型*/ card-type = MMC_TYPE_SD; memcpy(card-raw_cid,

27、cid, sizeof(card-raw_cid); if (!mmc_host_is_spi(host) /*获得卡的RCA,该寄存器表示发布卡的地址,卡的局部系统地址,在初始化过程中, 由主机和卡动态支持*/ mmc_send_relative_addr(host, &card-rca); /*设置总线模式*/ mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); if (!oldcard) /*获得卡CSD,该寄存器表示卡的协议数据,关于卡的操作状态数据*/ mmc_send_csd(card, card-raw_csd); /*卡的CSD结构的解码

28、*/ mmc_decode_csd(card); /*卡的CID结构解码*/ mmc_decode_cid(card); if (!mmc_host_is_spi(host) /*选择卡,后续的命令都依赖该操作*/ mmc_select_card(card); if (!oldcard) /*获得卡的SCR,该寄存器表示卡配置寄存器,关于卡特性容量的信息*/ mmc_app_send_scr(card, card-raw_scr); /*解码SCR结构*/ mmc_decode_scr(card); /*获得卡的switch信息*/ mmc_read_switch(card); /*尝试转化为高速*/ mmc_switch_hs(card); /*计算总线速率*/ max_dtr = (unsigned int)-1; if (mmc_card_highspeed(card) if (max_dtr card-sw_caps.hs_max_dtr) max_dtr = card-sw_caps.hs_max_dtr; else if (max_dtr card-csd.max_dtr) max_dtr = card-csd.max_dtr; /*设置可能的最高主机的时钟*/ mmc_set_clock(host, max_dtr

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1