sd 卡驱动在2.6内核的编写.sd/mmc/sdio kernel,sd/mmc/sdio 内核

SDIO驱动(6)命令的构建和发送 MMC子系统是主从式的架构,数据的传输由host通过命令进行请求和发送。这里分析命令的构建和发送。 阅读详情

【转帖请注明出处:blog.youkuaiyun.com/lanmanck】


sd卡驱动主要参照已有的文件即可,2410,9260都挺好。其实写驱动主要是搞清楚工作流程即可。我这里写一些心得与大家分享下,基于2.6.24:


1、主要的结构体:

static const struct mmc_host_ops my_mci_ops =
{
    .request    = my_mci_request,    //命令数据请求
    .set_ios    = my_mci_set_ios,    //设置时钟电源等
    .get_ro        = my_mci_get_ro,    //判断卡是否写保护,readonly

   //新内核还有.set_ro
};

一般的电路板会用gpio来判断卡是否插入,卡是否可以关电源等。这个跟芯片、SD卡座的连接方式有关,不是全部一致。

我们要做的就是.requet和.set_ios函数。

2、首先启动的时候上层会通过调用mmc_detect_change()去枚举卡,这个是照协议来的。在上层的函数中,会先.set_ios来设置sd卡模块的时钟、数据宽度等等。然后调用.request来发送命令、数据请求。

在我们的驱动中,一般是在.request判断要发送的命令、数据类型,然后根据相应的情况设置寄存器的相应位。然后发送命令后,在中断里判断命令是否响应超时还是ok。如果超时就设置返回值为错误,否则设置为正确(0)。然后调用mmc_rquest_done()来结束本次请求。

注意,一定是调用mmc_rquest_done()后上层才会进行下一步操作,否则系统就会死等。


精华之处就在于.rquest函数,其流程大致如下:

1)、先通过request->cmd的flags来判断命令是否需要response、是长还是短response,是否需要data等。根据这些就可以设置你的cmd寄存器。

2)、如果有数据传输的话,那么需要设置相关的dma或者其他方式来操作,这个2410和9260都有很好的范例。

3)、最后写你的寄存器,一般是命令cmd,参数arg,块数blocks,块大小block_size。然后就等待中断吧


中断也很有讲究,因为sd卡协议很繁琐,所以中断里面也必须处理比较多的事件。比如在枚举过程中,上层会发送一些非当前卡的命令,比如插的是sd卡,但发了个cmd5来探测是不是sdio,那么在中断里肯定会收到响应超时,即response timeout的错误。这时候就要返回该错误,让上层知道这个命令对当前卡是没有效的。

另外有数据读写时,因为上层先发命令,所以中断会有好多个。第一个是命令ok的中断,第二个是dma传输完毕的中断,第三个是fifo达到阀值的中断,等等。如果用dma,那么fifo阀值中断可以关掉。但是仍然需要区分另外2个中断。这个可以再request的时候设置一个标志位来判断,方法有很多。

因为传输数据时,块设备用的是scatter(散布表)方面的知识,所以在dma准备阶段会进行dma缓冲区映射请求。等数据读写完毕后再注销该次dma的映射。要注意的是,在注销dma映射时最好不要放到中断里面 ,这可以通过tasklet等来实现。


3、最后说下结构体的几个成员:

.request原型为static void my_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)

函数参数中,mmc基本上是给mmc_rquest_done用的,我们主要用struct mmc_request *mrq.定义为:

struct mmc_request {
    struct mmc_command    *cmd;
    struct mmc_data        *data;
    struct mmc_command    *stop;

    void            *done_data;    /* completion data */
    void            (*done)(struct mmc_request *);/* completion function */
};


这里我们不需要全部用,主要用cmd即可,有时候根据芯片的sd卡模块功能还要用stop.解析如下:

cmd :包含了命令的属性,是否有数据。cmd->opcode就是命令索引,而cmd->data就是有没有数据。实际上struct mmc_request里面的data会赋值给cmd的data,例如:cmd->data = data;所以我们就用cmd即可。其他都是系统用,不用管。

stop :在sd卡协议中,多块读写时需要在最后给卡发一个cmd12来停止数据传输,所以stop就是干这个用的,而且stop->opcode肯定是12,而且stop->data = NULL。不信各位看官可以判断一下,我反正试着好像是这么一回事。

看2410和9260,一般是在命令完成的时候发cmd12,但是我觉得应该是dma传输完毕后的中断发cmd12。这个没有试,因为我做的驱动中,sd模块有个功能就是自动发停止命令,而且我可以收到自动命令的中断。所以这个stop对我来说也没有用。


另外就是sd卡自动挂载的问题,我转帖一个,挺好用的:

http://blog.chinaunix.net/u3/97319/showart_2099947.html

 

mdev是busybox中的一个udev管理程序的一个精简 版,他也可以实现设备节点的自动创建和设备的自动挂载,只是在实现的过程中有点差异,在发生热插拔时间的时候,mdev是被hotplug直接调用,这时 mdev通过环境变量中的 ACTION 和 DEVPATH,来确定此次热插拔事件的动作以及影响了/sys中的那个目录。接着会看看这个目录中是否有“dev”的属性文件,如果有就利用这些信息为 这个设备在/dev 下创建设备节点文件。
下面是如何让我们的系统支持mdev。
 
1.在使用busybox制作根文件系统的时候,选择支持mdev
Linux System Utilities  --->  
           [*] mdev     
           [*]   Support /etc/mdev.conf
           [*]     Support command execution at device addition/removal
2.在文件系统添加如下内容
Vim /etc/init.d/rcS
        mount -t tmpfs mdev /dev
        mount -t sysfs sysfs /sys
        mkdir /dev/pts
        mount -t devpts devpts /dev/pts
echo /sbin/mdev>/proc/sys/kernel/hotplug
        mdev –s
这些语句的添加在mdev的手册中可以找到。
3.添加对热插拔事件的响应,实现U盘和SD卡的自动挂载。
Vim /etc/mdev.conf
        mmcblk[0-9]p[0-9] 0:0 666 @ /etc/sd_card_inserting
        mmcblk[0-9] 0:0 666 $ /etc/sd_card_removing
        sd[a-z] [0-9] 0:0 666 @ /etc/usb/usb_inserting
        sd[a-z] 0:0 666 $ /etc/usb/usb_removing
红色部分,是一个脚本,脚本内容可以根据我们的需要定制,可以实现挂载,卸载或其他一些功能。
如下是自动挂载和卸载的脚本:
/etc/sd_card_inserting
        #!/bin/sh
        mount -t vfat /dev/mmcblk0p1 /mnt/sd
/etc/sd_card_removing
        #!/bin/sh
        sync
        umount /mnt/sd
 
项目中要用到这样的功能,插入U盘时,要求自动检测到U盘的插入,并自动启动应用程序。
 
我的根文件系统是用busybox构建的,其中,设备文件的生成是使用busybox中的mdev生成。Mdev除了生成设备文件外,还能检测到设备的插入拨出,即热插拨检测。那么,自动检测U盘的插入,mdev本来就可以做到,不用再做研究了,问 题是如何自动启动程序呢?这就要使用mdev.conf文件了,此文件在根文件系统的/etc目录下。Mdev检测到设备插入后,会根据此文件中的规则自 动做一些相关的事。于是,我就写了如下一条规则,sda[0-9] 0:0 600 @(/autostart) 让mdev在检测到U盘插入后,自动运行autostart脚本。 做到这一步都没困难,busybox的文档就有详细说明,不多解释了。
 
但我要启动的是一个QT4 embedded的程序。大家都知道,运行这样的程序是要配置一些相关环境变量的,比如,我的程序要使用到tslib的一些环境变量,一般是在/etc /profile文件中进行配置。我也在此文件中配置了相关环境变量,但发现用手工方法启动QT程序,环境变量是起作用的,程序工作正常。但是我用 autostart脚本启运此程序,却发现环境变量没起作用。百思不得其解,想到很多办法都没有解决。最 后,在PC上的linux发行版中运行QT程序时,得到启发,我发现QT程序相关的环境变量只在当前的控制台中起作用。那么,mdev自动起动 autostart是不是另起了一个控制台呢?于是在atutostart的脚本中加入QT的相关环境变量设置,问题得到了解决。

-----------------------------------------------------------------------------------------
 
mdev是busybox自带的一个简化版的udev,适合于嵌入式的应用埸合。其具有使用简单的特点。它的作用就是在系统启动和热插拔或动态加载驱动程序时,自动产生驱动程序所需的节点文件。 在以busybox为基础构建嵌入式linux的根文件系统时,使用它是最优的选择。
mdev使用
mdev的使用在busybox中的mdev.txt文档已经将得很详细了。但作为例子,我简单讲讲我的使用过程:
(1)在编译时加上对mdev的支持(我是使用的是busybox1.10.1):
    Linux System Utilities  --->
    mdev          
    Support /etc/mdev.conf
    Support command execution at device addition/removal
 
(2)在启动时加上使用mdev的命令:
我在自己创建的根文件系统(nfs)中的/linuxrc文件中添加了如下指令:
#挂载/sys为sysfs文件系统
    echo "----------mount /sys as sysfs"
    /bin/mount -t tmpfs mdev /dev
    /bin/mount -t sysfs sysfs /sys
    echo "----------Starting mdev......"
    /bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
    mdev -s
注意:是/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug,并非/bin/echo /bin/mdev > /proc/sys/kernel/hotplug。
busybox的文档有错!!
 
(3)在你的驱动中加上对类设备接口的支持。
  在驱动程序的初始化函数中,使用下述的类似语句,就能在类设备目录下添加包含设备号的名为“dev”的属性文件。并通过mdev在/dev目录下产生gpio_dev0的设备节点文件。
  my_class = class_create(THIS_MODULE, "gpio_class");
  if(IS_ERR(my_class)) {
    printk("Err: failed in creating class./n");
    return -1;
  }
  /* register your own device in sysfs, and this will cause mdev to create corresponding device node */
  class_device_create(my_class, NULL, MKDEV(gpio_major_number, 0), NULL, "gpio_dev%d" ,0);
  在驱动程序的清除程序段,加入以下语句,以完成清除工作。
  class_device_destroy(my_class, MKDEV(gpio_major_number, 0));
  class_destroy(my_class);
  需要的头文件是linux/device.h,因此程序的开始应加入下句
  #include <linux/device.h>
  另外,my_class是class类型的结构体指针,要在程序开始时声明成全局变量。
  struct class *my_class;
  上述程序中的gpio_major_number是设备的主节点号。可以换成需要的节点号。gpio_dev是最终生成的设备节点文件的名子。%d是用于 以相同设备自动编号的。gpio_class是建立的class的名称,当驱动程序加载后,可以在/sys/class的目录下看到它。
  上述语句也不一定要在初始化和清除阶段使用,可以根据需要在其它地方使用。
 
(4)至于/etc/mdev.conf文件,可有可无,不影响使用,只是添加了些功能。
关于mdev的使用方法,我在网上找到一篇中文版的。大家可以到我上传的资源中下载。    
 
要想真正用好mdev,适当知道一下原理是必不可少的。现在简单介绍一下mdev的原理:
 
执行mdev -s:以‘-s’为参数调用位于/sbin目录写的mdev(其实是个链接,作用是传递参数给/bin目录下的busybox程序并调用它),mdev扫 描 /sys/class 和/sys/block中所有的类设备目录,如果在目录中含有名为“dev”的文件,且文件中包含的是设备号,则mdev就利用这些信息为这个设备在 /dev下创建设备节点文件。一般只在启动时才执行一次 “mdev -s”。
 
热插拔事件:由于启动时运行了命令:echo /sbin/mdev > /proc/sys/kernel/hotplug ,那么当有热插拔事件产生时,内核就会调用位于/sbin目录的mdev。这时mdev通过环境变量中的 ACTION 和DEVPATH,(这两个变量是系统自带的)来确定此次热插拔事件的动作以及影响了/sys中的那个目录。接着会看看这个目录中是否有“dev”的属性 文件,如果有就利用这些信息为这个设备在/dev 下创建设备节点文件。
 
最后,附上我在工作中编写的一段简单的gpio控制驱动程序。此程序没有什么功能,主要是做一些测试用的。有兴趣的朋友可以用它测试一下上述的mdev的使用方法。我用的是友善公司的mini2440开发板。
 
补充:1
为mdev的运行准备环境
mdev需要改写/dev和/sys两个目录。所以必须保证这两个目录是可写的(一般会用到sysfs,tmpfs。所以要重新编译内核)。
然后在你的启动脚本文件中加入
/bin/mdev -s
补充2:
 ·/etc/fstab
这是mount -a要读取的文本。根据需要编写。
KeyBindingsEditor.app 修改osx快捷键的app,不用多说了,看教程: http://blog.csdn.net/lanmanck/article/details/39646619 立即下载

相关推荐

CANSniffer

CAN通讯分析软件, 常用于电动汽车BMS开发 CAN报文分析. 可以细致的解析CAN报文.显示曲线,图表等.

STM32+Keil 如何使用printf函数?

【lanmanck原创】 Keil不支持Host-semi机制,即不支持直接在IDE打印字符串。 那么只能通过程序向硬件串口发数据了,这样调用的时候用自定义的函数即可,也很方便,例如: void send_char_to_usart(unsigned char c){} 但是可否直接使用printf函数呢?毕竟人家都做好了,我们给他定一个打印输出的接口就可以了,答案是肯定的,看ST的官

LYJ个人博客,记录技术、八卦、生活,分享各种心得,期待与朋友们一同进步 4万+

mupdf-1.16.0-windows.zip

开源pdf库

SDIO EMMC中ADMA和SDMA简介

(Simple Direct Memory Access)是两种不同的DMA(直接内存访问)模式,用于优化主机控制器与存储器(如eMMC)之间的数据传输效率。(Scatter-Gather I/O),通过链表或描述符表管理多个分散的数据块,无需CPU干预。提供更完善的错误报告机制(如描述符错误状态位),支持更精细的错误恢复流程。描述符结构更复杂,支持链式或多级描述符,可灵活配置多个数据传输任务。需要更复杂的主机控制器硬件支持(如支持64位地址和描述符链表)。错误处理较为基础,通常依赖主机控制器的中断机制。

1704

串口调试软件(带图形显示)

自己写的带图形显示的串口助手,自动回复,自动发送,ModScan主模式,CRC校验,

电力拖动自动控制.pdf

电力拖动自动控制pdf,电力拖动自动控制

winusb —— 不再为你的usb设备编写驱动

【blog.csdn.net/lanmanck】 曾几何时我们找工作还发现有个驱动工程师职位,月薪也不低,没接触过的人代码压根看不懂。 今天可好了,如果不太追求差异化,不用驱动也能让系统与USB设备通信了,Linux就不说了,libusb很好用,现在说下windows的。 Winusb是从XP-SP2起微软提供的一个类似libusb与usb设备通信的中间件,通过它我们就不需要再费奏折的研究和...

爬行的菜鸟的博客 1万+

利用Android系统漏洞实现后台弹窗(外弹)

关键:从 Android 8.0(API 26)开始,禁止使用 context.sendBroadcast() 发送隐式广播(即没有指定 setPackage() 或明确组件的广播)。demo核心代码展示利用Android显示系统和广播系统的漏洞实现在后台弹窗的功能,支持最新Android15,16版本。核心功能都是在so层去做,大量使用了jni反调, 如果要上架到应用市场,需要对代码做进一步混淆,加固以应对市场安全扫描。3,开启虚拟显示窗口,这是个透明像素窗口。5,可开启一个线程,调用这个外弹窗口。

2018,再出发~ 1316

linux sd卡驱动分析,基于mini2440,sdio mmc sd卡驱动编写(2),一些初始化流程

最近要让s3c2440在linux2.6.18上 支持4G的SD卡.原文地址:http://linux4u.wikidot.com/mmc-controller-driver==============================================================linux-2.6.2x的mmc驱动与linux-2.6.1x的mmc驱动

LYJ个人博客,记录技术、八卦、生活,分享各种心得,期待与朋友们一同进步 9229

基于DNN、CNN与SVM的串联电弧故障智能检测:从原理到嵌入式部署

在电气安全与工业物联网领域,时间序列分类是处理传感器信号、实现状态监测与故障诊断的核心技术。其原理在于从连续的信号数据中提取有效特征,并利用机器学习模型识别异常模式。这项技术的核心价值在于能够实现设备预测性维护、提升系统安全性并降低运维成本,广泛应用于智能电表、电机健康监测、电力设备保护等场景。本文聚焦于电气安全中的一个具体且危险的隐患——串联电弧故障的检测。针对这一隐蔽性强、传统方法误报率高的问题,项目深入实践了三种主流AI模型:深度神经网络、卷积神经网络和支持向量机。通过对比DNN的通用特征学习能力、C

weixin_31860973的博客 413

Proteus快速入门(最详细教程)

Proteus 是一款用于嵌入式单片机仿真的软件,用于在打PCB板之前对软件程序和硬件电路的正确性进行仿真验证。1.所以Proteus一般会和Keil软件进行联合仿真,在Proteus中绘制系统的电路图,在Keil软件中编写对应的程序后生成Hex文件。2.Proteus的仿真结果仅供参考,只能在一定程度上验证系统的可能性。实际实物系统还需要进行进一步的调试。以上即为本次分享的Proteus入门教程的全部内容,希望可以能够帮助到各位道友。

ediykk的博客 15万+

SD卡驱动分析(二)

三.下面分析一下高通的android2.3的代码中SD卡驱动的流程。           在kernel中,SD卡是作为平台设备加入到内核中去的,在/kernel/arch/arm/mach-msm/devices-msm7627a.c中: static void __init msm7x2x_init(void) -> static void __init msm7x27a_in

DaDaDaDaDa曹鑫 3118

中国30米逐年植被净初级生产力(NPP)数据集(1982年至今CASA模型)

1.3 气温、降水、地表太阳辐射数据 气温和降水数据月度空间插值数据是基于全国2400多个站点的日观测数据,在计算各气象要素月值的基础上,基于Anusplin软件插值生成的1982年以来各月度30米分辨率气温和降水栅格数据,插值过程中引入高程作为协变量。气温单位为℃,降水单位为mm。1.2 土地覆盖数据 土地覆盖数据来源于1985 年-2020年全球30米精细地表覆盖动态监测产品,该数据集包含29个地表覆盖类型,进行拼接、裁剪、重分类和重采样处理,获得8期250米分辨率的植被类型数据。

地球资源数据云的官方博客 2839

SDIO驱动总结

内核:Linux 2.6.35.7 硬件:三星的s5pv210平台 SDIO驱动包括SDIO 控制器驱动和SDIO卡驱动,属于主从结构类型,相信看过usb驱动的朋友会更容易理解SDIO的驱动框架。 本文初略分析了SDIO控制器驱动与SDIO卡驱动的调用过程,待以再对SDIO做进一步分析。 1. SDIO 控制器驱动 三星的s5pv210平台使用的SDIO控制器涉及到的驱动文件主要.\ d

myxmu的专栏 1313

微信小程序内容安全审核:从API调用到工程化落地的全流程实践

内容安全是互联网应用开发中的基础性技术环节,尤其在用户生成内容(UGC)场景下,它直接关系到平台的合规性与用户体验。其核心原理通常结合了关键词过滤、自然语言处理(NLP)和计算机视觉(CV)等技术,通过AI模型对文本、图像、音频进行多维度风险识别。这项技术的价值在于,它不仅是满足监管要求的必要手段,更是构建健康社区生态、保护品牌声誉、实现产品长期稳定运营的基石,广泛应用于社交、电商、社区论坛等各类UGC平台。本文聚焦于微信小程序生态,深入剖析其官方提供的内容安全解决方案,详细解读如何将文本同步检测与多媒体异

weixin_28622215的博客 452

在 ABAP 平台上搭建 OAuth 2.0 Server:架构、流程、权限与落地实战

摘要:本文为SAP ABAP开发人员提供将ABAP平台配置为OAuth 2.0授权服务器的实战指南。重点介绍两种授权流程(授权码和SAML Bearer)的实现方案,包括核心事务配置(SOAUTH2/SAML2)、授权对象(S_SCOPE)管理以及端点交互规范。通过具体配置清单和三类典型集成场景(第三方Web应用访问OData、企业集成平台调用、BTP应用对接)的落地示例,帮助读者快速构建安全的OAuth 2.0服务架构。文档强调SSL/TLS基础安全、scope最小授权原则以及授权与令牌端点的标准交互模式

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 308

linux2.6内核SD Card Driver详细解析之一

linux2.6内核SD Card Driver详细解析之一 版权声明:本文为博主原创文章,未经博主允许不得转载。 *************************************************************************************************************************** 作者:EasyWa

lxy190598463的博客 762

基于 Qt C++ 的 2D 动画制作工具

你可以修改它的中心坐标 (X, Y)、宽度 (W)、高度 (H),或点击 "选择颜色" 按钮改变其填充色。* **图形视图 (`QGraphicsView` 和 `QGraphicsScene`)**: 用于显示和编辑当前帧的内容。

寒寒豆豆软件公司的博客 114

Linux SDIO驱动

Wi-Fi/蓝牙Combo卡:最经典用例,一张卡在系统中生成独立的网络接口和蓝牙设备。嵌入式外设:如SDIO接口的GPS、NFC、Zigbee模块,常用于物联网设备和单板计算机。局限性:性能瓶颈:SDIO协议本身的带宽(通常最高约50-100 MB/s)和延迟不及PCIe或USB 3.0,限制了高性能应用。协议复杂性:初始化、中断协商等机制比纯存储卡复杂,增加了驱动调试难度。适用性:仅适用于SDIO设备,不用于SD存储卡(用MMC总线)或其他总线设备。

2301_79302469的博客 304

17、Nimble 包开发与并行编程指南

本文介绍了Nimble包的开发与版本管理流程,涵盖语义化版本控制规范及发布步骤;深入探讨了Nim中的并行编程基础,包括并发与并行的区别、threads模块与threadpool模块的使用方法及其差异;分析了线程执行的不确定性、线程池的优势,并提供了线程同步和资源管理的实践示例,帮助开发者高效构建稳定、高性能的Nim应用程序。

wine的专栏 56

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: dma使用的几个概念。burst,burst size,length
下一篇: HEX文件格式,ihex,hex解析
#Page#
博客等级 码龄23年 1691粉丝 360原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值