uboot移植之uboot中的SD卡驱动解析

简介:

1:地址对硬件操作的影响

    (1)操作系统(指的是linux)下MMU肯定是开启的,也就是说linux驱动中肯定都使用的是虚拟地址。而纯裸机程序中根本不会开MMU,全部使用的是物理地址。这是裸机下和驱动中操控硬件的一个重要区别。

    (2)uboot早期也是纯物理地址工作的,但是现在的uboot开启了MMU做了虚拟地址映射,这个东西驱动也必须考虑。查uboot中的虚拟地址映射表,发现210开发板里面,除了0x30000000-0x3FFFFFFF映射到了0xC0000000-0xCFFFFFFF之外,其余的虚拟地址空间全是原样映射的。而我们驱动中主要是操控硬件寄存器,而S5PV210的SFR都在0xExxxxxx地址空间,因此驱动中不必考虑虚拟地址。

2:从start_armboot开始

这里的();就是SD卡的初始化函数,这个函数的作用就是初始化开发板上MMC系统。MMC系统的初始化应该包含这么几部分:SoC里的MMC控制器初始化

(MMC系统时钟的初始化、SFR初始化)、SoC里MMC相关的GPIO的初始化、SD卡/iNand芯片的初始化

3:mmc_initialize()函数分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int  mmc_initialize(bd_t *bis)
{
struct  mmc *mmc;
int  err;
INIT_LIST_HEAD(&mmc_devices);     //初始化内核链表,next指针和prev指针都指向自身
cur_dev_num = 0; // SD 卡的插槽,我们这里有4个插槽
if  (board_mmc_init(bis) < 0)
cpu_mmc_init(bis);    //时钟初始化  GPIO初始化,但是目前都是初始化SoC内部,并没有
               //涉及外部的SD卡的初始化
#if defined(DEBUG_S3C_HSMMC)
print_mmc_devices( ',' );
#endif
#ifdef CONFIG_CHECK_X210CV3
mmc = find_mmc_device(1); //lqm
#else
mmc = find_mmc_device(0);
#endif
if  (mmc) {
err = mmc_init(mmc);
if  (err)
err = mmc_init(mmc);
if  (err) {
printf ( "Card init fail!\n" );
return  err;
}
}
printf ( "%ldMB\n" , (mmc->capacity/(1024*1024/(1<<9))));
return  0;
}

    (1)INIT_LIST_HEAD(&mmc_devices);

内核链表的初始化函数,内核链表在初始化的时候,链表的next指针和prev指针都是指向其自身。mmc_devices链表全局变量,用来记录系统中所有已经注册的SD/iNand设备。所以向系统中插入一个SD卡/iNand设备,则系统驱动就会向mmc_devices链表中插入一个数据结构表示这个设备。

    (2)if (board_mmc_init(bis) < 0)

查看代码可知,board_mmc_init(),其实是__def_mmc_init()函数的别名,而__def_mmc_init()函数的返回值固定是-1,所以if判断成立,执行cpu_mmc_init()函数。

    (3)cpu_mmc_init()函数

cpu_mmc_init()函数在uboot/cpu/s5pc11x/cpu.c中,

int cpu_mmc_init(bd_t *bis)

{

#ifdef CONFIG_S3C_HSMMC

setup_hsmmc_clock();

setup_hsmmc_cfg_gpio();

return smdk_s3c_hsmmc_init();

#else

return 0;

#endif

}

setup_hsmmc_clock():在uboot/cpu/s5pc11x/setup_hsmmc.c中。hsmmc高速mmc,clock时钟,所以这个函数应该是用于mmc控制器的时钟初始化。里面是通过宏定义来选择配置哪些通道的时钟(通过MPLL分频得到)。x210选择的是通道0和通道2(SD卡)

setup_hsmmc_cfg_gpio():MMC控制器IO引脚的设置。在在uboot/cpu/s5pc11x/setup_hsmmc.c中中

smdk_s3c_hsmmc_init():uboot/drivers/mmc/s3c_hsmmc.c中。该函数里面主要调用s3c_hsmmc_initialize(int channel)函数,参数channel表示的是MMC的通道。

至此,cpu_mmc_init()函数分析结束,继续分析mmc_initialize()函数。

    (4) find_mmc_device(0)函数

find_mmc_device()uboot/drivers/mmc/mmc.c中,这个函数其实就是通过mmc设备编号来在系统中查找对应的mmc设备(struct mmc的对象,根据上面分析系统中有2个,编号分别是0和2)。函数工作原理就是通过遍历mmc_devices链表,去依次寻找系统中注册的mmc设备,然后对比其设备编号和我们当前要查找的设备编号,如果相同则就找到了要找的设备。找到了后调用mmc_init函数来初始化它。

    (5)mmc_init()函数

mmc_init()函数在drivers/mmc/mmc.c中。这个函数的主要作用是进行mmc卡的初始化。mmc_init函数内部就是依次通过向mmc卡发送命令码(CMD0、CMD2那些)来初始化SD卡/iNand内部的控制器,以达到初始化SD卡的目的。


4:总结

    (1)整个MMC系统初始化分为2大部分:SoC这一端的MMC控制器的初始化,SD卡这一端卡本身的初始化。前一步主要是在cpu_mmc_init函数中完成,后一部分主要是在mmc_init函数中完成。

    (2)整个初始化完成后去使用sd卡/iNand时,操作方法和mmc_init函数中初始化SD卡的操作一样的方式。读写sd卡时也是通过总线向SD卡发送命令、读取/写入数据来完成的。

    (3)struct mmc结构体是关键。两部分初始化之间用mmc结构体来链接的,初始化完了后对mmc卡的常规读写操作也是通过mmc结构体来链接的。



本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1927550
相关文章
|
1月前
|
消息中间件 Cloud Native Java
【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合
【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合
|
6月前
|
存储 边缘计算 数据管理
Docker 存储驱动解析:选择最适合你的存储方案,优化容器化部署性能和数据管理
Docker 存储驱动解析:选择最适合你的存储方案,优化容器化部署性能和数据管理
142 0
|
2月前
|
人工智能 安全 大数据
开源软件全景解析:驱动技术创新与行业革新的力量
开源软件全景解析:驱动技术创新与行业革新的力量
394 0
开源软件全景解析:驱动技术创新与行业革新的力量
|
3月前
|
存储 机器学习/深度学习 数据挖掘
数据仓库与数据湖:解析数据驱动的未来
在数字化时代,数据成为企业决策的核心资源。本文将深入探讨数据仓库和数据湖的概念、特点以及应用场景,分析其在实现数据驱动决策过程中的重要性和优势,并展望数据驱动的未来发展趋势。
52 5
|
4月前
|
C语言 Windows
9.3 Windows驱动开发:内核解析PE结构节表
在笔者上一篇文章`《内核解析PE结构导出表》`介绍了如何解析内存导出表结构,本章将继续延申实现解析PE结构的PE头,PE节表等数据,总体而言内核中解析PE结构与应用层没什么不同,在上一篇文章中`LyShark`封装实现了`KernelMapFile()`内存映射函数,在之后的章节中这个函数会被多次用到,为了减少代码冗余,后期文章只列出重要部分,读者可以自行去前面的文章中寻找特定的片段。
26 0
9.3 Windows驱动开发:内核解析PE结构节表
|
4月前
|
存储 Windows
9.2 Windows驱动开发:内核解析PE结构导出表
在笔者的上一篇文章`《内核特征码扫描PE代码段》`中`LyShark`带大家通过封装好的`LySharkToolsUtilKernelBase`函数实现了动态获取内核模块基址,并通过`ntimage.h`头文件中提供的系列函数解析了指定内核模块的`PE节表`参数,本章将继续延申这个话题,实现对PE文件导出表的解析任务,导出表无法动态获取,解析导出表则必须读入内核模块到内存才可继续解析,所以我们需要分两步走,首先读入内核磁盘文件到内存,然后再通过`ntimage.h`中的系列函数解析即可。
35 0
9.2 Windows驱动开发:内核解析PE结构导出表
|
6月前
|
存储 Linux Go
Docker 存储驱动解析:选择最适合你的存储方案
Docker 存储驱动解析:选择最适合你的存储方案
89 0
|
7月前
|
存储 传感器 物联网
基于小熊派SD卡+Fatfs+移植开源iniparse解析库并使用
基于小熊派SD卡+Fatfs+移植开源iniparse解析库并使用
42 0
|
10月前
|
C语言 Windows
驱动开发:内核解析PE结构节表
在笔者上一篇文章`《驱动开发:内核解析PE结构导出表》`介绍了如何解析内存导出表结构,本章将继续延申实现解析PE结构的PE头,PE节表等数据,总体而言内核中解析PE结构与应用层没什么不同,在上一篇文章中`LyShark`封装实现了`KernelMapFile()`内存映射函数,在之后的章节中这个函数会被多次用到,为了减少代码冗余,后期文章只列出重要部分,读者可以自行去前面的文章中寻找特定的片段。
171 0
|
11月前
|
存储 Windows
驱动开发:内核解析PE结构导出表
在笔者的上一篇文章`《驱动开发:内核特征码扫描PE代码段》`中`LyShark`带大家通过封装好的`LySharkToolsUtilKernelBase`函数实现了动态获取内核模块基址,并通过`ntimage.h`头文件中提供的系列函数解析了指定内核模块的`PE节表`参数,本章将继续延申这个话题,实现对PE文件导出表的解析任务,导出表无法动态获取,解析导出表则必须读入内核模块到内存才可继续解析,所以我们需要分两步走,首先读入内核磁盘文件到内存,然后再通过`ntimage.h`中的系列函数解析即可。
214 0

推荐镜像

更多