sd 卡驱动在2.6内核的编写.sd/mmc/sdio kernel,sd/mmc/sdio 内核
【转帖请注明出处:blog.csdn.net/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
[*] Support /etc/mdev.conf
[*] Support command execution at device addition/removal
mount -t tmpfs mdev /dev
mount -t sysfs sysfs /sys
mkdir /dev/pts
mount -t devpts devpts /dev/pts
mdev –s
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
#!/bin/sh
mount -t vfat /dev/mmcblk0p1 /mnt/sd
#!/bin/sh
sync
umount /mnt/sd
mdev的使用在busybox中的mdev.txt文档已经将得很详细了。但作为例子,我简单讲讲我的使用过程:
(1)在编译时加上对mdev的支持(我是使用的是busybox1.10.1):
Linux System Utilities --->
mdev
Support /etc/mdev.conf
Support command execution at device addition/removal
我在自己创建的根文件系统(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。
(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的目录下看到它。
上述语句也不一定要在初始化和清除阶段使用,可以根据需要在其它地方使用。
为mdev的运行准备环境 mdev需要改写/dev和/sys两个目录。所以必须保证这两个目录是可写的(一般会用到sysfs,tmpfs。所以要重新编译内核)。 然后在你的启动脚本文件中加入
/bin/mdev -s
·/etc/fstab
这是mount -a要读取的文本。根据需要编写。
sd 卡驱动在2.6内核的编写.sd/mmc/sdio kernel,sd/mmc/sdio 内核相关推荐
- sd 卡驱动--基于高通平台
点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...
- 详解sd协议以及裸机和u-boot中的sd卡驱动(2)
3. sd卡驱动 3.1 引入 经过第2章我们知道,要想实现读写sd卡,需要按照sd协议规定的基本传输单位(命令.响应.数据)以及流程(初始化.读.写),向sd卡发送信号或者从sd卡接收信号. 为了简 ...
- mini2440 linux移植开发实战指南,Linux-2.6.32.2内核在mini2440上的移植---移植SD卡驱动...
移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare下CentOS 5.5 ,1G内存. 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linu ...
- SD卡驱动分析(二)
三.下面分析一下高通的android2.3的代码中SD卡驱动的流程. 在kernel中,SD卡是作为平台设备加入到内核中去的,在/kernel/arch/arm/mach-msm/devices-ms ...
- Linux SD卡驱动开发(五) —— SD 卡驱动分析Core补充篇
Core层中有两个重要函数 mmc_alloc_host 用于构造host,前面已经学习过,这里不再阐述:另一个就是 mmc_add_host,用于注册host 前面探测函数s3cmci_probe, ...
- Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作
前面对SD卡控制器有了一个基本的介绍.其实SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法,当然不同的控制器对硬件控制的方法不尽相同,但是他们最终都能像core层提交一个统一的封装 ...
- Linux SD卡驱动
二.MMC/SD介绍及SDI主机控制器 首先我们来理清几个概念: MMC:(Multi Media Card)由西门子公司和首推CF的SanDisk于1997年推出的多媒体记忆卡标准. SD:(Sec ...
- Exynos4412 移植针对Samsung的Linux-6.1(二)SD卡驱动——解决无法挂载SD卡的根文件系统
系列文章目录 Exynos4412 移植针对Samsung的Linux-6.1(一)下载.配置.编译Linux-6.1 Exynos4412 移植针对Samsung的Linux-6.1(二)SD卡驱动 ...
- 战舰V3适配oneos系列03:添加SD卡驱动及文件系统
战舰V3系列03:添加SD卡驱动及文件系统 本系列以 oneos2.3.0 提供的 STM32F103ZE 模板为基础,将 oneos 在战舰 V3 上运行起来,并逐步适配相关外设,计划周更 本系列相 ...
最新文章
- Permission denied: make_sock: could not bind to address [::]:81 Apache 虚拟主机
- 美团五大最受欢迎的开源项目!
- 人工智能是这样理解真正的活过了
- query判断值是否为空,针对前台提交数据的校验
- Maven项目依赖管理工具
- docker搜索镜像
- JEECG-P3开发专题 - 开发环境搭建入门
- 视图引擎smarty 一
- redis数据类型-set集合
- 【SpringBoot_ANNOTATIONS】自动装配 01 @Autowired @Qualifier @Primary
- Java 综合性实验 Java源代码分析程序
- 搭建hadoop集群从裸机开始
- 微信小程序Radio为一组时,使用三元表达式始终选中默认值
- 干货 | SQL 外部联接 Outer Join
- SQL 压力测试实战
- 大学生用计算机,大学生计算机科学基础
- 三元运算符(三目运算符)
- Cuil搜尋引擎 挑戰Google
- [leetcode] 28. Implement strStr() 解题报告
- vue2.9.6版本下创建vue-cli脚手架