摘要:本文结合实际项目(一款以WINCE为操作系统内核的GSM/PHS双模智能手机)对嵌入式系统Windows CE5.0的底层驱动(SD卡)的架构进行了分析和研究,以MARVELL公司提供的基于INTEL Zylonite硬件平台的BSP为基础,利用Windows CE5.0的Platform Builder集成开发环境(IDE)开发适合实际项目的SD卡驱动代码,分别以轮询和中断方式实现该驱动的动态加载,并深入分析SD卡驱动(流驱动)的详细的加载过程。 
关键词:Zylonite  Platform Builder   BSP  SD卡驱动

0、引言

随着通信领域新业务需求的不断增长及计算机技术,半导体技术和电子技术的术的迅速发展,嵌入式系统异军突起,已经渗透到社会生活的方方面面了。它是集软件,硬件于一体的高可靠性系统。其最大特点即为可以通过裁减装卸系统模块来配置整个平台所要求的功能。

Windows CE是由微软公司所开发的一个嵌入式操作系统,它与Windows平台的编程接口有很强的兼容性。其平台开发工具Platform Builder是一个完全集成的开发环境(IDE)。本项目所涉及的硬件开发套件Intel Zylonite Development System装配有Intel的Xscale芯片处理器Monahans L(PXA300),并配有相关外设电路接口(USB2.0,SD/MMC,音频,以太网口等)及外设(触摸屏,KEYPAD,扬声器,听筒,话筒等)。其独特的结构优化能力保证了操作环境和通用应用设备可以在高频率和的情况下快速处理任务。

 

1、 WINCE 下的SD卡驱动架构

Wince 下SD卡驱动协议栈组成 :

u       HOST硬件底层部分 (主控制端驱动)       SDHC_XXX.DLL

u       BUS 中间逻辑命令层 (总线驱动)                     SDBUS.DLL

u       CLIENT上层(客户端驱动)                              SDMEMORY.DLL

1.1、主控制端驱动

     主控制端驱动控制包含主控制器硬件,遵循主控制端驱动接口,它被用于总线驱动通信和设置操作参数。主控制器驱动接口提供一个硬件提取层,在总线和主控制端执行之间。即:SDHC_XXX.DLL是最底层,因为这层是硬件关联层,因此取名XXX便是为了对应的具体的硬件BSP包(如本项目的硬件平台是ZYLONITE,其硬件供应商给的BSP包名即为ZYLONITE,在实际项目中我们便将SDHC_XXX.DLL取代为SDHC_ZYLONITE.DLL),它负责具体的发命令,大多数情况下都需要修改。

1.2、总线驱动

总线驱动作为提取和管理层处于主控制驱动和客户端驱动之间。它包括在SDbus.dll文件。为客户端驱动提供了标准的API,允许运行在任何的基于windows ce设备。总线驱动将是独立于应用程序和主控制端驱动,在不同的处理器之间移植,并不需要改动。SDBus.dll是中间层,负责整合命令和管理。

1.3、客户端驱动

客户端驱动和SD客户端驱动通信接口允许客户端驱动去和SD设备通信。客户端驱动接口是有计划地抽象SD总线物理设备的执行,提供了客户端驱动最大的弹性。客户端驱动接口允许客户端驱动去衡量一个单一的,同步的访问存储卡驱动使用一个线程,异步通信设备驱动。SDMemory.dll是最高层,类似于应用层。

2.立足微软SD卡协议栈开发Zylonite 的BSP包的SD卡驱动

当我们开发SD卡驱动时,并详细分析比较了Microsoft的SD驱动架构和Intel所提供的BSP内的参考SD卡驱动以后,可以得出如下结论:

l         针对主控制端驱动(SDHC_XXX.DLL):因为这一层是直接操作硬件的一层,所以大多数情况下都需要修改。修改的内容基本为收发命令部分以及数据传输和硬件初始化部分.

l         针对总线驱动(SDBUS.DLL):因为这一层处于主控制驱动和客户端驱动之间,用于他们之间的通信,SD卡总线请求都放在它里面,微软提供了非常完备的样例代码,所以我们一般都不需要改动,直接调用它的接口就可以了。

l         针对客户端驱动( SDMEMORY.DLL):因为SDMemory就是所谓的Client层,类似于应用层,它还可用来识别卡的,不同种类的卡,比如sd memory card等,鉴于我们只需开发SD卡部分的驱动,所以也不需要怎么修改了(如果我要开发SD接口的SDIO设备,那么就得在这层做比较大的改动了)。

Intel所提供的BSP内的参考SD卡驱动自己实现了主控制端驱动(SDHC_ZYLONITE.DLL),而调用并保留了总线驱动(SDBUS.DLL)和客户端驱动( SDMEMORY.DLL)。因此结合具体的硬件设计(SD卡的CONNECTOR等),我们的主要任务便是利用BSP内的SD卡主控制端驱动代码,开发(配置并改进)我们实际项目内的SD卡驱动。

2.1、Zylonite BSP内的SD卡主控制端驱动概述

SD卡的驱动程序是以流的形式提供的,而该SD卡主控制端驱动以sdhc_zylonite.dll 的形式提供,入口在:\WINCE500\PLATFORM\Zylonite\public\csp\monahans\sdhc

有如下两个文件:

l         sdcontrol.c:内含一个非常重要的线程---SDControllerISTHandler,

主要负责卡与控制器的交互,处理控制器接收的消息等,具体的控制和处理函数均在此文件中。

l         main.c:      SDH(主控制端驱动)的导出流接口在该文件中实现,并

包含有主控制端驱动的(sdhc_zylonite.dll)的入口点。

SD卡硬件初始化及其主控制端驱动的注册表信息设置路径为:

\WINCE500\PLATFORM\Zylonite\Platform\ZYLONITE\SRC\DRIVERS\SDHC

主要文件为:

l         impl.c: 主要是在加载SD卡主控制端驱动时初始化硬件。内含一个非

常重要的线程---- SDCardDetectIstThread,专门处理SD卡的插拔操作。但是具体的插拔操作也是在Sdcontrol.c文件实现的。

2.2、结合实际项目的开发流程

2.2.1 SD卡的外部引脚及功能配置

在实际项目(一款以WINCE为操作系统内核的GSM/PHS双模智能手机)中,SD卡的外部引脚与Monahans_L的GPIO连接图及连接控制器的电路图如下所示:


    由上可得,先要配置SD卡的外部引脚及功能。而SD卡的引脚配置在其下的 \source 文件夹的xllp_mmc_board.c文件XllpMMCConfigure函数内修改。(特别注意:GPIO34要配成检测SD卡插入的中断源。)

2.2.2、分析修改并改进主控制端驱动重要线程及硬件初始化部分代码

l         SD卡主控制端驱动加载及架构解析

需要声明的是SD卡驱动加载顺序是:

加载SDBus.dll→加载sdhc_zylonite.dll→加载sdmemory.dll

我们在这里只详细讨论第2步(sdhc_zylonite.dll的加载),此时SDBus.dll已经加载成功。WINCE系统初始化后,会载入DEVICE.EXE, 对应代码devload.C中的WINMAIN函数会被调用起来,从而启动InitDevice函数,此函数会搜寻(\WINCE500\PLATFORM\Zylonite\Platform\ZYLONITE\SRC\DRIVERS\SDHC下的sdhc_zylonite.reg)注册表根键,准备参数调用WIN32 API接口-----Activedevice,接着利用Dllmaincrtstartup函数找到sdhc_zylonite.dll的入口,执行该文件的入口函数DllMain()然后继续返回到DEVICE.EXE(devload.C),调用launchdevice()函数,再调用sdhc_zylonite.dll的入口main.c文件内的SDH_Init(),自此将开始将开始SD卡主控制端驱动的初始化过程:

1. 调用SDH_Init()

2. 调用 SDHCDAllocateContext() 来分配一段主控制器的上下文

a)Context 是总线驱动和主控制端驱动共享的

3. 主控制端驱动使用SDHCDSetXxx宏来填充这个上下文结构

a)这个步骤是把主控制器向总线驱动描述一下

b)包括函数指针,支持的电流,最大时钟,槽数目,SDIO的支持等等。

4. 调用 SDHCDRegisterHostController() 来把自己向总线驱动注册一下

5.  当总线驱动准备处理SD事件时,它会调用主控制端驱动的init 函数(pContext->pInitHandler)

接着便是sdbus.dll驱动部分的代码和SD卡主控制端驱动部分的交互设置:比如设置电源、时钟和总线宽度等。一般都是sdbus.dll发起请求,再去调用主控制端驱动部分的API,这里最后详细分析插槽状态交互确认,因为这是成功加载sdhc_zylonite.dll的关键。当有SD卡在插槽,sdbus.dll的slotstatuschange()调用并建立一个重要线程SDcardDetectIstThread(),当探测到有卡,即返回给sdbus.dll, 总线驱动即可调用HandleAddDevice()函数,自此初始化结束,sdhc_zylonite.dll加载成功。

l         对主控制端驱动重要线程SDcardDetectIstThread()代码的改进

在前面的叙述中,可以看出线程SDcardDetectIstThread()在sdhc_zylonite.dll最后的加载起决定性作用。然而我们发现在INTEL所给的BSP中,在检测卡的过程里,其采用了轮询的方式----即每隔一定的时间,CPU都会去读一次GPIO34的电平,以确定SD卡是否被插入或拔出,以此来判定是否去加载或卸载SD卡的客户端和主控制端驱动。很显然,这种方式的弊端是占用了过多的CPU资源,效率很低,严重影响了整个系统的实时性。因此,最能解决这个问题的办法无外乎是使用中断检测的方式。以下特别叙述采用2种不同的中断机制的方式实现:

1中断绑定静态配置:

1.在Bsp_cfg.h文件内定义一个系统中断号SYSINTR_SDMMC_DETECT

#define SYSINTR_SDMMC_DETECT (SYSINTR_FIRMWARE+N) N为当前已定义的最大值(以保证此中断未使用过)。

2.在Xllp_gpio_plat.h文件中找出GPIO34的定义:#define XLLP_GPIO_MMC_CD_0 34

3.在intr.c文件里将系统中断号和IRQ关联:

OALIntrStaticTranslate(SYSINTR_SDMMC_DETECT, IRQ_GPIO_SHARE(XLLP_GPIO_MMC_CD_0));

4.在主控制端驱动的硬件初始化代码Impl.c中的InitializeHardware()加入 EnablesdcardInterrupt()函数。

5.在Impl.c中完善EnablesdcardInterrupt(),加入GPIO上升沿或下降沿的检测和SET EVENT。

6.在Impl.c文件中定义hCardInsertInterruptEvent并在SetupCardDetectIST()内创建hCardInsertInterruptEvent

7.Impl.c文件中初始化dwSysintrCD= SYSINTR_SDMMC_DETECT,并绑定相应的EVENT:InterruptInitialize    (dwSysintrCD,hCardInsertInterruptEvent,NULL,0)

8.     改进线程SDcardDetectIstThread()的While部分代码,加入WaitForSingleObject( hCardInsertInterruptEvent, dwTimeout );只有当hCardInsertInterruptEvent被置上,才会往下走,否则一直在此处等待。

9.同上原理改写CardremoveInterrupt用于动态卸载SD卡主控制端驱动。

2中断绑定动态配置:

1.               在Impl.c文件的SetupCardDetectIST()函数内动态配置系统中断号和硬件中断源:KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwSDCDIrq, sizeof(DWORD), &(dwSysintrCD), sizeof(DWORD), NULL))。此处的&dwSDCDIrq可在SD卡主控制端驱动的注册表内更改后,用LoadPlatformRegistrySettings函数加载进来。可在sdhc_zylonite.reg 文件内将"CardDetectIRQ" 的值改为“IRQ_GPIO_SHARE_BASE+x-2” 在本平台内,IRQ_GPIO_SHARE_BASE=52,X=34。

2.               接上5-6-7-8-9。

CE下基于Zylonite硬件平台的SD卡驱动开发相关推荐

  1. 【SD卡】关于DJYOS下SD卡驱动开发详解

    关于DJYOS下SD卡驱动开发详解 王建忠 2011/6/21 1      开发环境及说明 硬件平台:tq2440(CPU: s3c2440) 操作系统:DJYOS1.0.0 1.1    说明 T ...

  2. Linux SD卡驱动开发(五) —— SD 卡驱动分析Core补充篇

    Core层中有两个重要函数 mmc_alloc_host 用于构造host,前面已经学习过,这里不再阐述:另一个就是 mmc_add_host,用于注册host 前面探测函数s3cmci_probe, ...

  3. wince下SD卡驱动开发

    WinCE 5.0下面SD卡驱动的开发.这是我做的第一个项目,当时做这个项目花费了相当的时间和精力,搞的我精疲力尽.几乎可以说当时对WinCE一点都不懂.也不知道从何处下手,就东看西看.东改西改,改的 ...

  4. SD卡驱动开发随笔(1)

    前不久刚写完SD卡驱动,最后的运行和读写文件效果自己也比较满意以下是性能测试结果 ----------------------------------------------------------- ...

  5. Linux SD卡驱动开发(二) —— SD 卡驱动分析HOST篇

    回顾一下前面的知识,MMC 子系统范围三个部分: HOST 部分是针对不同主机的驱动程序,这一部是驱动程序工程师需要根据自己的特点平台来完成的. CORE 部分: 这是整个MMC 的核心存,这部分完成 ...

  6. Linux SD卡驱动开发(六) —— SD卡启动过程总体分析

    一.工作流程 mmc驱动主要文件包括 drivers/mmc/card/block.c drivers/mmc/card/queue.c drivers/mmc/core/core.c drivers ...

  7. Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作

    前面对SD卡控制器有了一个基本的介绍.其实SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法,当然不同的控制器对硬件控制的方法不尽相同,但是他们最终都能像core层提交一个统一的封装 ...

  8. linux sd卡驱动教程,Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作

    前面对SD卡控制器有了一个基本的介绍.其实SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法,当然不同的控制器对硬件控制的方法不尽相同,但是他们最终都能像core层提交一个统一的封装 ...

  9. sd 卡驱动--基于高通平台

    点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...

最新文章

  1. 为python安装numpy和scipy(federo)
  2. 华为H3C ER3100由器限速方法合集
  3. qint64转为qstring qt_Qt项目中TCP通信的实现方式经验总结(服务端部分)
  4. mysql 慢查询过多_MySQL 慢查询优化
  5. python 爬虫框架_Python实战:爬虫框架(6)
  6. ionic3 html调用摄像头,Ionic3项目实战
  7. windows app html5,使用 HTML5 來偵測位置 (HTML)
  8. java: 无法将类 com.duo_tai.Cow中的构造器 Cow应用到给定类型;
  9. 使用C#: 自动切换鼠标的左右手习惯
  10. 安装不上vc++环境,导致部分游戏和qq不能用的解决方案
  11. [WPF系列]Adorner应用-自定义控件ImageHotSpot
  12. Java注解实现权限管理
  13. python人脸识别代码_一行Python代码搞定人脸识别
  14. erphpdown最新版下载v11.12,WordPress内容付费插件
  15. Can‘t connect to any repository: http://gitee.com/user.rame/java.git
  16. 码码在线考勤系统笔记(三)
  17. RMAN维护:RMAN中的交叉校验crosscheck
  18. Javascript的最大回文字符串
  19. 明明加了唯一索引,为什么还是产生重复数据?
  20. 极客时间-左耳听风-程序员攻略-机器学习和人工智能

热门文章

  1. java kafka 集群消费_kafka集群简单生产者消费者实例
  2. vue 怎么清空依赖_vuejs如何在把对象所有属性清空?
  3. android webview 长按菜单拦截,javascript-在Android上长按时禁用上下文菜单
  4. php zip下载损坏,php – 从zip中提取时损坏图像
  5. 计算机键盘标注,你所不知道的 Windows 10 小诀窍:万能计算器、虚拟键盘、屏幕截图标注...
  6. 利用旧手机自建anki服务器,废旧手机变身服务器,打造私人云盘
  7. Anaconda 安装
  8. cookie和session 以及Django中应用
  9. Java中 break continue return 的区别
  10. 水平+垂直布局-css (借鉴)