免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 10391 | 回复: 5
打印 上一主题 下一主题

[BootLoader] 【记录】将Uboot 2011.06中mmc驱动移植到uboot 1.1.6的过程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-08-15 21:52 |只看该作者 |倒序浏览

【记录】将Uboot 2011.06中mmc驱动移植到uboot 1.1.6的过程

时间:2011-8-14

作者:crifan

联系方式:green-waste (at) 163.com

---------------------------------------------------------------------------

附上代码:

u-boot-1.1.6_20100601_newMMC USB_20110814.7z (1.16 MB, 下载次数: 968)

---------------------------------------------------------------------------

【背景】

硬件:

(1)TQ2440,CPU是S3C2440,带SD/MMC控制器。

(2)自己的金士顿的1GB的SD卡

软件:

(1)TQ2440的uboot 1.1.6

(2)自己已经移植旧的mmc的驱动成功,可以实现mmcinfo, fatls mmc 0, fatload mmc 0 addr file, 但是旧的mmc中检测出来的sd卡的容量不对,原因是由于READ_BL_LEN是 15,大于12了,用的计算方法是错误的。

详情参见:

【记录】在TQ2440的uboot中添加SD/MMC支持 + 添加USB Mass Storage支持 + 解决fatls乱码问题

http://bbs.chinaunix.net/thread-3577777-1-2.html

【目的】

想要实现正确检测我的1GB的SD卡的容量,所以要把正确的mmc驱动移植过来。

而目前最新的uboot 2011.06版本的中,已经有最新的mmc驱动,但是和uboot 1.1.6比,mmc的整个架构都变了,需要把mmc部分,整个都改了,再添加对应的底层函数,才可以。

【将Uboot 2011.06中mmc驱动移植到uboot 1.1.6的全过程】

1. 添加文件,修改makefile等准备工作

先是把mmc最直接相关的cmd_mmc.c,整个替换了

这样就支持了更多的mmc相关的命令了:

mmcinfo

mmc rescan

mmc part

mmc list

mmc dev

fatls mmc 0

fatload mmc 0 addr filename

同时,替换了最新的mmc.h头文件,该文件包含了对应的sd/mmc所有的命令等定义。

由于旧的uboot中在board.c的start_armboot()中没有mmc初始化部分,所以也要填上对应内容:

#ifdef CONFIG_GENERIC_MMC


puts("MMC:
");


mmc_initialize(gd->bd);

#endif

而后再去添加对应的makefile等,使得编译通过,不多细说。

2. s3c_mmc_init()

用beyondcompare,将uboot 2011.06和uboot 1.1.6相比较,发现新的mmc驱动框架中,主要实现几个核心函数即可,此处我的sd/mmc控制器是三星的S3C2440的,所以简称为s3c,对应的第一个要实现的函数为:

/* this is a weak define that we are overriding */

int board_mmc_init(bd_t *bd)

{


return s3c_mmc_init(bd);

}

中的:s3c_mmc_init()

其中,主要是初始化mmc中一些核心的参数,主要代码是:


mmc->send_cmd = s3cmmc_send_cmd;


mmc->set_ios = s3cmmc_set_ios;


mmc->init = s3cmmc_init;

将挂上发送命令,设置总线宽度/频率等,初始化三个函数的指针


mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS;

告诉sd host支持4bit模式 即High Speed即50MHz模式


mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;

此处电压是参考其他驱动写上的,具体含义没有深入去了解


mmc->f_max = get_PCLK();


mmc->f_min = 400*1000;

设置所支持的最大和最小频率


mmc->block_dev.part_type = PART_TYPE_DOS;

设置sd卡分区的类型是DOS,即常见的FAT分区


mmc->b_max = 0;

设置最大的block数目,0为没限制,mmc系统会自动初始化

都设置好了,再去调用


mmc_register(mmc);

上述内容都设置好了,然后就是分别去实现上述三个核心的函数:

3. s3cmmc_init()

init函数中,主要就是初始化sd的硬件相关的部分

其主要代码和之前旧的差不多,只是把blocksize设置,频率设置,等等,都放到了setios函数或者send_cmd函数中了而已,没有太多需要解释的,参考之前代码即可。

4. s3cmmc_set_ios()

set_ios中,主要就是两个:

(1)当传入的参数中clock不为0时候,去根据所需要的频率去设置对应的SDIPRE寄存器即可;

(2) 根据传入的总线宽度,此处即1或者4,1就是最开始的默认的,4就是对应的wide bus,设置对应的SDIDCON寄存器即可。

5. s3cmmc_send_cmd()

发送命令,这个函数可以个大头,需要花不少精力的。

通过看uboot 2011.06中其他mmc驱动的实现,大概看懂了此处,mmc发送命令的函数,其实处理了两个事情,一个是发送普通命令,二是对于数据的读写,其实也是通过发送对应对应的命令,然后读写对应数据的。

即普通的发送命令,只需要发送命令即可;

而包括数据读写的命令,参数是放在data中的,data不为空的时候,就不仅仅要发送对应的命令,还要接着读写数据的。

此处暂时不去实现数据的write,只考虑read的情况,目的是实现相关的命令fatls mmc 0和fatload mmc 0 addr file。

(1)单纯的发送命令

关于发送命令,之前也已经有了对应的函数send_cmd,把旧函数,拿过来,改一下,也基本就实现了。

【关于发送命令之后的response】

另外需要提及一点的是,如果发送命令需要反馈response的,对于

cmd->resp_type中有MMC_RSP_PRESENT的,那么至少要返回一个response,而如果是长的response,即MMC_RSP_136,是需要返回四个response的,详情参考代码。

【使用readl/writel时候,需要传入寄存器的地址而不是寄存器的值】

另外还有点要说明的,对于用writel/readl,readb/writeb等函数来代替直接寄存器操作的,传入的寄存器地址,是需要是地址的,而不能是寄存器的值,即:

原先读一个寄存器:csta = sdi->SDICSTA;

现在用readl时,要传入寄存器的地址,要这样调用:csta = readl(&sdi->SDICSTA);

而不能是csta = readl(sdi->SDICSTA);

关于这点,也是参考了别的代码和调试,才发现这点的。

【诡异问题:S3C2410_SDICMDCON_SENDERHOST的含义】

不过,这里在调试代码过程中,发现一个有点诡异的问题,那就是,对于设置command control寄存器的时候,原先代码是:

ccon |=S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;

其中

#define S3C2410_SDICMDCON_SENDERHOST
(1<<6)

但是对应的S3C2410和S3C2440的datasheet中,都没有提到这一点,而只是网上这些S3C2410和S3C2440的sd卡驱动的参考代码,包括uboot和kernel中的,却有这个位的设置,而如果去掉这一位的设置,命令就无法正常发送。

虽然看名字S3C2410_SDICMDCON_SENDERHOST知道大概是host是sender,但是对于这一位的具体含义是什么,还是不懂,希望如果有知情的可以解释一下。

(2)带读数据的命令的发送和之后的数据读取

但是对于带读数据的命令的发送,包括MMC_CMD_READ_MULTIPLE_BLOCK=CMD17读块数据和MMC_CMD_SEND_EXT_CSD=CMD8读扩展CSD等等,就不仅仅要先发送命令,还要接着读对应的数据才可以的。

对于read block等命令,其处理的时候,要先设置好datasize寄存器,

再根据之前设置的SDIDCON 中的bus width是1还是4,决定设置数据控制寄存器中是S3C2440_SDIDCON_DS_WORD还是S3C2440_SDIDCON_DS_BYTE,

等设置好了SDIDCON之后,接着再去发送对应的带数据读的命令,然后接着处理的流程和之前旧的代码是一样的,即先去fifosta中找到fifo中有多少个数据,然后一个个读取,每次读取1个字节还是4个字节,由之前的bus width决定。

等读完当前fifo了再去重复读取fifosta,再去判断有多少个字节数据需要读取,

这样一点点把数据读出来即可。

读数据的过程中,需要通过读取SDIDSTA得知数据的状态是否正常,如果有错误,比如超时,CRC错误等,就退出。

此部分流程,基本和旧的代码没太大区别。

但是代码调试过程中,这部分代码,在读取数据部分,始终出错,让我调试了很久,最后找到原因,竟然是自己不小心,在读取了SDIDCON的值后,忘了把原来的bus width那一位给设置回去,所以再之前去设置bus width=4=word之后,此处还是用bus width=1=byte的模式来读数据,所以出现第一次读SDIFSTA而获得的FIFO中的字节数,竟然是有奇数的,比如0x1c7,而不是期望的64啊之类的,应该是4的倍数的,最后加上对应的正确的设置后,后面的读取数据就都对了。

【未解决的疑问:CMD8和CMD13超时】

在最后可以成功读数据之后,却也还是发现有两个命令会超时:

MMC CMD8 Timeout

MMC CMD13 Timeout

具体原因未知。有待后期再去找原因,或者哪个高手告知一下原因。

最后贴上可以成功检测出我的1GB的SD卡的log信息:

EmbedSky> help mmc

mmc read addr blk# cnt

mmc write addr blk# cnt

mmc rescan

mmc part - lists available partition on current mmc device

mmc dev [dev] [part] - show or set current mmc device [partition]

mmc list - lists available devices

EmbedSky> mmcinfo

MMC CMD8 Timeout

MMC CMD13 Timeout

Status Error: 0x002D0032

Device: TQ2440 SD/MMC

Manufacturer ID: 2

OEM: 544d

Name: SD01G

Tran Speed: 25000000

Rd Block Len: 512

SD version 1.10

High Capacity: No

Capacity: 982.5 MB

Bus Width: 4-bit

EmbedSky> mmc rescan

MMC CMD8 Timeout

MMC CMD13 Timeout

Status Error: 0x002D0032

EmbedSky> mmc part

Partition Map for UNKNOWN device 0
--
Partition Type: DOS

Partition
Start Sector
Num Sectors
Type


1
243

2011917
6

EmbedSky> mmc dev

mmc0 is current device

EmbedSky> mmc list

TQ2440 SD/MMC: 0

EmbedSky> fatls mmc 0

MMC CMD13 Timeout


512
nikon001.dsc


misc/


dcim/


3701
fisrttest.html

2 file(s), 2 dir(s)

评分

参与人数 1可用积分 +10 信誉积分 +2 收起 理由
bitmilong + 10 + 2 原创内容

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2011-08-29 14:11 |只看该作者
看了楼主好几篇的文章,真是替众多的同鞋感谢crifan 无私的share。
最后楼主六个两个疑惑的地方,我有一点个人的见解

在最后可以成功读数据之后,却也还是发现有两个命令会超时:
MMC CMD8 Timeout
MMC CMD13 Timeout


#define MMC_CMD_SEND_EXT_CSD                8
上面的cmd 的命令在SD 卡是不支持的。如果是用MMC卡测试的话,就不会报超时了。

#define MMC_CMD_SEND_STATUS                13
上面的cmd 是获取卡的状态,通过spec 可知,使用这条命令的时候,卡是要在transfer 状态。
我看了看楼主的源码,在楼主的源码中,发出该cmd时,卡没有处于 tranfsfer 状态,所以报超时也是符合协议的

论坛徽章:
0
3 [报告]
发表于 2012-08-15 17:33 |只看该作者
学习~~谢谢楼主~~

论坛徽章:
0
4 [报告]
发表于 2012-08-15 18:45 |只看该作者
牛人,也在研究uboot。
能帮小弟看看我的一个问题吗?
关于uboot中的cfi flash问题
见链接:http://bbs.chinaunix.net/thread-3765156-1-1.html

论坛徽章:
0
5 [报告]
发表于 2012-09-22 22:42 |只看该作者
好东西 收藏一下哈

论坛徽章:
0
6 [报告]
发表于 2013-06-24 21:54 |只看该作者
好东西,绝对的好东西。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP