解永亮,任洪伟,付国楷,房利国
(1.中国电子科技集团公司第三十研究所,四川 成都 610041;2.中国石油西南油气田分公司 重庆气矿,重庆 400021)
多通道SDIO驱动框架设计与实现*
解永亮1,任洪伟2,付国楷1,房利国1
(1.中国电子科技集团公司第三十研究所,四川 成都 610041;2.中国石油西南油气田分公司 重庆气矿,重庆 400021)
为了满足移动互联设备对功耗、性能以及成本的需求,通过对SDIO协议规范以及ARM、PowerPC等多核CPU异步多处理器模式下负载均衡技术进行研究,提出了在linux系统下灵活性和通用性较好的多通道SDIO设备驱动程序构架,并详细描述了通信机制的原理、设备端枚举和初始化过程、驱动构架的实现要点和技术优势。最后,在实际硬件环境中对驱动程序的性能进行了测试和分析,并对如何进一步提高传输速率提出了一些建议。
SDIO;Linux驱动程序;NAPI
在实际的系统设计和实现中,USB、PCI/PCIE等都是比较常见的高速互联总线,一般情况下,CPU只会实现USB的MAC层,还需要外接物理层PHY芯片才能提供完整的支持,而PCI/PCIE总线只会出现在高端的CPU中。FPGA芯片的USB和PCI/PCIE等总线接口,一般都是通过购买其他公司专门的IP CORE来实现,这对FPGA芯片的规模提出了较高的要求。随着移动互联的兴起,移动终端类设备大量产生,这些设备使用电池供电,对功耗也有了更加严格的要求,因此传统的高速总线不能很好地满足需要。
安全数字卡联盟(SD Card Association)制定了一套安全数字输入/输出卡(SDIO,Secure Digital Input/Output)规范,其主要目的是为低功耗移动电子设备提供一种高速的数据传输方式。SDIO卡除了具有SD卡所具备的信息存储功能以外还包含数据输入输出功能,因此在商用存储领域以及设备互联领域都得到了广泛应用。
在SDIO规范中针对每一种类型的设备都定义了一个子规范 ,比如:蓝牙接口规范、GPS接口规范、WLAN接口规范等。本文在此基础上抽象出一个更加通用的构架,并且以以太网驱动为例详细描述了在这种构架下驱动程序的实现要点。
每个SDIO设备可以有1到7个Function外加一个Memory Function。Function是一个自包含的IO设备,彼此之间可以完全相同也可以各不相同。所有Function被组织成寄存器的集合[1]。SDIO设备必须实现“通用I/O区”(CIA, The Common I/O Area),CIA由3部分组成:CCCR(Card Common Control Registers)、FBR(Function Basic Registers)、CIS(Card Information Structure)[2]。CCCR和FBR中分别保存有Function 0和Function 1-7的CIS指针,指向CIS区域。Function 1-7可以有最大128K的寄存器空间。
多通道SDIO设备利用多个Function来实现。每个Function的128K空间规划为寄存器区和IO数据区(实际实现可以用RAM方式或者FIFO方式)。SDIO设备端实现多套逻辑独立运行在不同的Function上。SDIO主机端为每个Function创建不同的数据收发线程,每个收发线程有各自的发送以及接收队列,同时把每个线程关联在不同的CPU核心上[3]。因为数据交互过程中涉及的空间是不重叠的,所以多个通道可以同时工作。SDIO设备内部空间见图1。
图1 SDIO设备内部空间
驱动开发和测试所使用的硬件平台主体构架如图2所示。CPU是Freescale公司的ARM处理器imx6s,主频800MHz。FPGA采用Xilinx公司的xc6slx45t芯片,作为SDIO设备端,不使用专门的SDIO IP CORE,通过采样时钟、数据、命令线分析主机端发送的内容。
图2 SDIO设备内部空间
由于CPU内部SDIO控制器或者外部SDIO控制存在一定差异,因此在操作系统中所对应的控制器驱动也各不相同。本文所描述的驱动框架运行在CPU端,软件层次是在Linux的SDIO控制器驱动之上,目的是为支持多通道功能的设备在Linux上的驱动开发提供一种设计思路以及实现方法。
整个SDIO设备驱动分为上下两层,上层为linux以太网接口模块(业务层),与内核协议栈交互;下层为SDIO接口模块(数据传输层),与CPU中SDIO控制器交互。下层模块为上层模块提供一个统一、一致的接口调用,包括:数据传输、配置管理、寄存器访问等,当上层业务层需要修改或者更换时,下层数据传输层可以无需修改继续使用。整体构架如图3所示。
以太网接口模块符合标准的linux以太网驱动构架,使用接收数据包效率更高的NAPI模式进行接收处理。提供ethtool管理接口,用户可以通过标准的ethtool命令对网络适配器的参数以及状态进行查询和修改。
图3 SDIO设备驱动构架
3.1 设备初始化过程
当CPU的SDIO控制器发现SDIO设备已经连接后它会通知操作系统,由操作系统完成设备的初始化。整个过程如图4所示。
图4 SDIO设备枚举过程
下面对每一步骤涉及的命令、访问的寄存器以及设备状态的变化进行说明,详细的寄存器定义请参见对应参考文档。
SDIO设备复位:发送CMD52命令写Function0的寄存器6对设备进行复位操作。此时设备由“初始化状态”切换为“Standby状态”。
设备进入IDLE状态:发送CMD0命令。
获取设备支持的Function数:发送CMD5命令且参数值设置为0,该命令除了可以获取Function数以外还能得到SDIO设备是否具有存储单元,能支持的电压范围。
协商电压范围:发送CMD5命令,参数设置值为通信双方能支持的电压范围的交集[4]。
设置设备地址:发送CMD3命令获取设备自动产生的设备地址(Relative Card Address,RCA),如果产生的地址和其他SDIO设备的地址冲突,会重新发送该命令,通知设备重新产生新的地址[4]。
选中设备:发送命令CMD7,参数为之前产生的设备地址,接收到该命令后设备进入“命令接收状态”[4]。
读取设备参数:发送CMD52命令访问Function0的寄存器0、8、12h、13h等,设备需要返回是否支持4比特数据模式、是否支持多块传输以及支持的总线速率等信息。
读取每个Function的CIS(Card Information Structure)信息:通过CMD52命令读取每个Function的CIS信息,CIS信息中包含最重要的数据是厂商ID以及设备ID,上一小节说的SDIO接口模块就是通过这两个ID来关联实际设备的。
3.2 驱动初始化过程
SDIO设备驱动与实际设备的关联与PCIE和USB类似,使用ID进行匹配。在驱动模块初始化函数中调用sdio_register_driver函数,并传递struct sdio_driver结构体,该结构体包含了驱动能支持的设备ID以及通道初始化函数(Probe)等信息。
对于具备多个通道的设备,操作系统会为每一个通道调用一次驱动中的通道初始化函数。在该函数中先使用CMD52命令访问Function0的寄存器2,使能对应的Function,并读取Function0的寄存器3,等待设备端Function进入“就绪”状态。再使用CMD52命令向对应FBR的寄存器10h和11h配置数据传输阶段使用的块大小参数。然后调用内核提供的kthread_create函数为当前Function创建发送内核线程,并通过sdio_claim_irq函数建立该Function与接收函数的关联。通过以上两个步骤,一个Function的数据发送以及数据接收逻辑通道已经建立完成。之后依次对设备能支持的每个通道完成以上的初始化过程以实现多通道构架,创建的多个通道逻辑上可以同时工作,每个通道可以在接收以及发送函数中实现具体业务逻辑,并使用不同应用层协议,比如一个通道传输以太网协议数据,另一个通道传输Bulkonly存储协议数据。驱动核心初始化处理流程如图5所示。
图5 驱动初始化流程
完成以上核心的初始化过程后,驱动再为每个使用该驱动的应用层进程/线程维护独立的事务队列,实现多个线程同时访问SDIO设备不会出现冲突,并且一个线程发起的传输事务响应结果只会返回给发起者线程,而不会被其他线程访问等功能。
3.3 数据收发过程
大块数据的发送和接收使用CMD53命令来完成,内核为该命令提供mmc_io_rw_extended函数,以及该函数的一些高级接口,包括数据发送接口:sdio_memcpy_toio和sdio_writesb;数据接收接口:sdio_memcpy_fromio和sdio_readsb。
SDIO接口模块与SDIO设备之间数据传输使用自定义的数据帧格式。根据分层思想,实际传输的数据也可以包含更上层的协议头,这样可以保证上层实现的修改不会影响其他各个层次的处理逻辑。
实际的数据接收使用linux内核中为提高网络数据包效率而设计的NAPI机制,它是一种介于中断接收和查询接收之间的一种机制,根据“配额”来决定本次处理的数据包的数量,如果“配额”不足,则在下一次系统空闲的软中断中继续处理。如果“配额”够了,则在下次数据接收的硬件中断中再次调度[5]。整个SDIO接口模块的数据处理流程如图6所示。
图6的接收处理流程中有几点需要说明:
(1)每个通道的上下文数据中都包含一个struct napi_struct结构体,当接收到数据时,各个通道独立调度自己的NAPI进行接收处理[6]。
(2)图6中的虚线框表示其内部的处理逻辑在专门的NAPI调度中执行,其他的处理逻辑在SDIO中断处理函数中执行。
图6 数据接收处理流程
实际测试平台使用双线程分别对两个通道进行压力和性能测试。经过一系列的测试,得到的测试结果如表1所示。
表1 SDIO接口吞吐量测试结果
从表1中的测试结果可以得出以下几个结论:
(1)小包的传输效率远远低于大包的传输效率,这是因为启动一次SDIO总线传输开销较大,所以在实际使用中对于小数据包可以考虑在CPU端和FPGA端分别进行分片以及合片处理,把若干小数据包组成一个大数据包,这样才能充分利用SDIO总线。
(2)从FPGA端进行性能分析可以发现FPGA大多数时候处于空闲状态,它并非数据传输的瓶颈,在当前情况下性能受限于CPU端。这里提出几点原因以及优化方式:①SDIO总线时钟为50 MHz,在4比特数据模式下理论上只有200 Mb/s的吞吐率,可以根据CPU情况提高时钟;②实验时FPGA只能支持单包传输不能支持多包传输,所以一次不能写入多包数据。
3)当前SDIO的吞吐率能够满足低功耗移动设备对性能的要求,能有有效降低FPGA规模和成本以及CPU外围芯片的数量和整机功耗。
本文设计了一种不局限于某种特定处理器的多通道SDIO通信机制,并对其原理、软硬件架构、数据收发处理与驱动程序设计做了详细介绍。本设计中的多个通道可以根据实际情况增加或者减少,每个通道的具体使用方式以及业务逻辑也可以灵活搭配,具有较强的适应性和扩展性。通过性能测试可以看出,目前该通信机制具有不错的性能并能满足对功耗和成本要求较高的需求。
[1] SD Group and SD Card Association. SD Specifications Part E1 SDIO Simplified Specification Version 3.00 (2011-02-25) [2015-03-20]. http://www.sdcard.org.
[2] 黄晓曦,黄世震. 基于ARM的SDIO驱动设计[J]. 计算机与数字工程, 2010(01):160-161. HUANG Xiao-xi, HUANG Shi-zhen. ARM-based Driver Design for SDIO [J]. Computer & Digital Engineering, 2010 (01): 160-161.
[3] 秦培斌,肖志辉,杨大川等. 基于多核处理器的加密卡异步并行驱动设计[J]. 通信技术,2014,47(07):833-834. QIN Pei-bin, XIAO Zhi-hui, YANG Da-chuan,et al. Asynchronous Parallel Driver Design of Encryption Card based on Multi-core Processing Unit[J]. Communications Technology, 2014,47(07):833-834.
[4] SD Group and SD Card Association. SD Specifications Part 1 Physical Layer Simplified Specification Version 4.10 (2013-1-22) [2015-03-20]. http://www.sdcard.org.
[5] 许里,冯国仕,李璞. 光纤通道接口通用驱动程序设计与实现[J].通信技术, 2014,47(11):1344-1345. XU Li, FENG Guo-shi, LI Pu.Design and Implementation of Fabric Channel Interface Driver[J]. Communications Technology, 2014,47 (11): 1344-1345.
[6] Jonathan Corbet,Alessandro Rubini, GregKroab-Hartman. Linux设备驱动程序[M]. 第3版. 北京:中国电力出版社,2012:518-520. Jonathan Corbet, Alessandro Rubini,GregKroab-Hartman.Linux Device Dnvers[M].The Third Edition.Beijing:China Elatrn Power Press,2012:518-520.
Design and Implementation of Multi-channels SDIO Driver Framework
XIE Yong-liang1, REN Hong-wei2, FU Guo-kai1, Fang Li-guo1
(1.NO.30 Institute of CETC, Chengdu Sichuan 610041, China;2.Chongqing Gas Field, Southwest Oil and Gas Company of CNPC, Chongqing 400021, China)
For meeting the requirements by power dissipation, performance and costs of mobile interconnection devices, and based on the study of SDIO protocol specifications and load balancing technique in asynchronous multi-CPU mode of multi-core CPU like ARM and PowerPC and so on, a flexible and adaptable program framework of multi-channels SDIO device driver in linux system is proposed, and the theory of communications mechanism, enumeration and initiation process in device end, including implementation outlines and technical advantages of this driver framework,are described in detail. Finally, tests and analysis are also done on driver’s performance in practical hardware environments, and some advices on how to enhance transmission efficiency are also given.
SDIO; Linux driver program; NAPI
10.3969/j.issn.1002-0802.2015.05.022
2014-12-11;
2015-03-18 Received date:2014-12-11;Revised date:2015-03-18
TP309.7
A
1002-0802(2015)05-0616-05
解永亮(1979—),男,学士,工程师,主要研究方向为嵌入式系统、通信安全技术、计算机应用;
任洪伟(1978—),男,学士,工程师,主要研究方向为信息网络、信息安全、通信安全技术;
付国楷(1980—),男,学士,工程师,主要研究方向为嵌入式系统、通信安全技术、计算机应用;
房利国(1977—),男,硕士,高级工程师,主要研究方向为信息安全、通信安全技术、计算机应用。