1、概述

本文档以imx6实验平台为例,介绍SD设备驱动实现流程。

 

2、SylixOS中SD系统框架

SylixOSSD协议栈(以下称作SD Stack)结构如图 2.1所示。

2.1 SD 协议栈结构

1Host层:硬件控制器抽象层,SD控制器在不同的硬件平台上可能有不同的实现,因此需要实现具体的传输处理操作。所有的控制器驱动都向上(Core层)提供统一的操作接口。SD Stack已经提供了符合SD规范的标准控制器SDHCI驱动,在此情况下,控制器驱动的编写将更加简单。当然也可使用SPI传输。

2Core层:主要封装了SDSPI两种传输方式以及SD MemorySDIO相关协议操作库,让Client层只需要关心与具体设备相关的SD协议处理,而不必考虑底层的硬件情况,详细介绍如下:

(a) sdLib为基于Core Xfer 为传输对象封装的SD Memory相关协议操作库;

(b) sdioLib: sdLib一样,是针对sdio类设备特殊操作的相关工具库,sdio类设备驱动使用此库可以使驱动的编写更简单。

(c) SDM: SD DRV Manager, SD 驱动管理层,这里的SD驱动包括SD 设备驱动和SD控制器驱动,这样两者的信息都由SDM管理维护,以此达到两者完全隔离的目的。

3Client层:实现具体的设备类协议,主要包括SD MemorySDIO 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控制器驱动安装

图中相关实现解读如下:

  1. SD控制器参数初始化,主要填充HOST控制器相关参数,如卡状态、总线名、设备类型、时钟频率等;

  2. 端口初始化,即实现通道相关管脚的分配等;

  3. 通道扩展寄存器初始化,此函数可以暂时为空;

  4. 创建SD标准主控制器,主要实现寄存器访问驱动、解析主控制器的功能、创建传输事务、创建SDM层的HOST对象用来保存HOST信息等;

  5. 获取SDM层的HOST对象;

  6. SDM层通知当前设备事件(针对BOOT设备的特殊属性,直接创建设备,提高启动速度);

  7. 热插拔事件处理,主要针对SD卡等热插拔设备。

本文档主要针对eMMC,在实验平台上作为BOOT设备启动,所以,主要介绍上图⑥函数。

3.3 SDM设备创建

SD设备作为启动设备时,通知事件相关调用关系如图 3.3所示。

3.3 SDM设备创建

图中,首先根据通知事件类型,直接调用__sdmDevCreate函数创建一个SDM设备,该函数中相关实现解读如下:

  1. 遍历SD驱动链表,根据设备驱动类型找到对应的设备驱动,并得到设备名;

  2. 创建一个CORE设备,将设备名和挂接的适配器名关联起来;

  3. 调用设备驱动创建一个SD设备。

3.4 SD设备的创建及初始化

SD规范主要定义了3种传输速率:低速(400KHZ时钟,通常用于设备初始化阶段);全速(25MHZ时钟,用户设备正常工作阶段);高速(50MHZ时钟,可支持高速设备)。SD规范中明确定义了设备和控制器必须支持低速和全速,高速模式为非必要实现,需要控制器和设备双方均支持才能正常工作。

设备的创建最终调用到从SD驱动链表中查找到的设备驱动函数__sdmemDevCreate,该函数中首先就是调用API_SdMemDevCreate接口创建一个SD记忆卡设备,而对SD设备的初始化__sdMemInit就在该函数中被调用,关于__sdMemInit解读如下:

  1. 发送命令前设置,如图 3.4所示。

3.4 初始化前准备

  1. 重启电源;

  2. 初始化时将时钟设置为低速400KHZ状态;

  3. 设置总线为1位总线模式。

2进入idle状态,如图 3.5所示。

3.5 进入idle状态

3)       检查卡接口条件(cmd8),如图 3.6所示。

3.6 检查卡接口条件

  1. 获取HOST工作电压;

  2. 检查卡支持电压。

4获取卡支持信息,并激活卡初始化(acmd41),如图 3.7所示。

3.7 获取卡支持信息

5获取设备CIDcmd2),如图 3.8所示。

3.8 获取设备CID

6获取设备RCAcmd3),如图 3.9所示。

3.9 获取设备RCA

7)根据设备类型(sd/mmc设备)切换传输速率(即切换时钟频率),如图 3.10所示。

3.10 针对设备类型进行相应处理

  1. sd设备

    1. 设置当前时钟为全速传输状态(25mhz时钟);

    2. 获取当前设备可支持传输能力(即是否支持高速传输);

    3. 若设备支持高速传输,设置当前时钟为高速传输状态(50mhz时钟);

    4. 设置块传输长度(默认512);

    5. 设置总线宽度(4bit);

  2. mmc设备

    1. 设置块传输长度(默认512);

    2. 设置mmc卡的总线频率;

    3. 设置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