1、概述
本文档以imx6实验平台为例,介绍SD设备驱动实现流程。
2、SylixOS中SD系统框架
SylixOS中SD协议栈(以下称作SD Stack)结构如图 2.1所示。
图 2.1 SD 协议栈结构
1)Host层:硬件控制器抽象层,SD控制器在不同的硬件平台上可能有不同的实现,因此需要实现具体的传输处理操作。所有的控制器驱动都向上(Core层)提供统一的操作接口。SD Stack已经提供了符合SD规范的标准控制器SDHCI驱动,在此情况下,控制器驱动的编写将更加简单。当然也可使用SPI传输。
2)Core层:主要封装了SD和SPI两种传输方式以及SD Memory和SDIO相关协议操作库,让Client层只需要关心与具体设备相关的SD协议处理,而不必考虑底层的硬件情况,详细介绍如下:
(a) sdLib为基于Core Xfer 为传输对象封装的SD Memory相关协议操作库;
(b) sdioLib: 与sdLib一样,是针对sdio类设备特殊操作的相关工具库,sdio类设备驱动使用此库可以使驱动的编写更简单。
(c) SDM: SD DRV Manager, 即SD 驱动管理层,这里的SD驱动包括SD 设备驱动和SD控制器驱动,这样两者的信息都由SDM管理维护,以此达到两者完全隔离的目的。
3)Client层:实现具体的设备类协议,主要包括SD Memory和SDIO BASE两个库,分别对应SD存储卡类设备和SDIO类设备,详细介绍如下:
(a) SD Memory 负责SD Memory 相关的协议处理(如初始化,块读写等),它同时完成与SylixOS块设备相关的接口创建(BLK_DEV)。
(b) SDIO BASE: sdio类基础驱动,它和SD Memory处于同一级别,它不会直接去创建实际的sdio类设备,主要是在完成sdio的基础初始化后,使用特定的sdio子类驱动来创建对应的设备。之所以设计sdio类基础驱动,是为了让驱动的管理更加统一,同时将原设计中的一些缺点(比如设备驱动要关心Host的一些信息)掩藏起来, 让sdio类设备驱动开发更简洁。
3、SD驱动实现
3.1 SD设备驱动安装
在安装控制器驱动前,需要先安装SD设备驱动,树要实现如图 3.1所示。
图 3.1 安装SD设备驱动
该函数中主要就是实现了SD memory设备的创建和删除方法,并将其链入设备驱动链表,以便于在有设备事件通知时,创建设备时根据设备类型调用。
3.2 SD控制器驱动安装
在imx6实验平台的bsp中,需要创建HOST控制器用来保存HOST相关信息,安装控制器驱动实现如图 3.2所示。
图 3.2 SD控制器驱动安装
图中相关实现解读如下:
- SD控制器参数初始化,主要填充HOST控制器相关参数,如卡状态、总线名、设备类型、时钟频率等;
- 端口初始化,即实现通道相关管脚的分配等;
- 通道扩展寄存器初始化,此函数可以暂时为空;
- 创建SD标准主控制器,主要实现寄存器访问驱动、解析主控制器的功能、创建传输事务、创建SDM层的HOST对象用来保存HOST信息等;
- 获取SDM层的HOST对象;
- 向SDM层通知当前设备事件(针对BOOT设备的特殊属性,直接创建设备,提高启动速度);
- 热插拔事件处理,主要针对SD卡等热插拔设备。
本文档主要针对eMMC,在实验平台上作为BOOT设备启动,所以,主要介绍上图⑥函数。
3.3 SDM设备创建
当SD设备作为启动设备时,通知事件相关调用关系如图 3.3所示。
图 3.3 SDM设备创建
图中,首先根据通知事件类型,直接调用__sdmDevCreate函数创建一个SDM设备,该函数中相关实现解读如下:
- 遍历SD驱动链表,根据设备驱动类型找到对应的设备驱动,并得到设备名;
- 创建一个CORE设备,将设备名和挂接的适配器名关联起来;
- 调用设备驱动创建一个SD设备。
3.4 SD设备的创建及初始化
SD规范主要定义了3种传输速率:低速(400KHZ时钟,通常用于设备初始化阶段);全速(25MHZ时钟,用户设备正常工作阶段);高速(50MHZ时钟,可支持高速设备)。SD规范中明确定义了设备和控制器必须支持低速和全速,高速模式为非必要实现,需要控制器和设备双方均支持才能正常工作。
设备的创建最终调用到从SD驱动链表中查找到的设备驱动函数__sdmemDevCreate,该函数中首先就是调用API_SdMemDevCreate接口创建一个SD记忆卡设备,而对SD设备的初始化__sdMemInit就在该函数中被调用,关于__sdMemInit解读如下:
- 发送命令前设置,如图 3.4所示。
图 3.4 初始化前准备
- 重启电源;
- 初始化时将时钟设置为低速400KHZ状态;
- 设置总线为1位总线模式。
2)进入idle状态,如图 3.5所示。
图 3.5 进入idle状态
3) 检查卡接口条件(cmd8),如图 3.6所示。
图 3.6 检查卡接口条件
- 获取HOST工作电压;
- 检查卡支持电压。
4)获取卡支持信息,并激活卡初始化(acmd41),如图 3.7所示。
图 3.7 获取卡支持信息
5)获取设备CID(cmd2),如图 3.8所示。
图 3.8 获取设备CID
6)获取设备RCA(cmd3),如图 3.9所示。
图 3.9 获取设备RCA
7)根据设备类型(sd/mmc设备)切换传输速率(即切换时钟频率),如图 3.10所示。
图 3.10 针对设备类型进行相应处理
- sd设备
- 设置当前时钟为全速传输状态(25mhz时钟);
- 获取当前设备可支持传输能力(即是否支持高速传输);
- 若设备支持高速传输,设置当前时钟为高速传输状态(50mhz时钟);
- 设置块传输长度(默认512);
- 设置总线宽度(4bit);
- mmc设备
- 设置块传输长度(默认512);
- 设置mmc卡的总线频率;
- 设置mmc卡的总线位宽。
3.5 挂载磁盘分区并打印磁盘信息
设备创建并初始化完成后即可进行分区挂载,如图 3.11所示。
图 3.11 挂载磁盘分区
至此SD驱动已基本实现。
4、参考资料
1. SD Memory Card Specifications Part1 Physical Layer Specification
2. SD Specifications Part 1 Physical Layer Simplified Specification
3. SD Specifications Part E1 SDIO Simplified Specification
4. SD Specifications Part A2 SD Host Controller Simplified Specification
5. http://blog.chinaunix.net/uid-30296321-id-5094936.html