嵌入式技术

  • Windows CE的历史 I

     

    艰难的起步

     

    Microsoft199611月发布了Windows 95的缩小版,Windows CE 1.0(有些评论指CE代表的是Compact Edition,也有人说是Consumer Electronics,不过Microsoft都否认)。他一开始的设计目标是简单易用以及用户熟悉的体验,特别是对于Windows 95的用户而言。

     

    然而,在讨论Windows CE发展之前,我们必须先回到1992年的夏天。其实微软在1990年就开始对现在许多Windows CE里面的技术展开了研究工作。当时这些研究的初衷是为了创造出一个移动型的Windows设备。在1992年,微软宣布了移动型Windows的计划。

    当时微软启动了WinPad项目,这个项目里面,微软希望能够可以转变用户和Windows交互的方式。当时的想法是想通过改变我们现在熟悉的平台到一个完全不一样的平台,从而激发更多的创新。微软的目标是通过改进Win16的代码,使之能够充分发挥新的x8632位)CPU的功能,从而促成刚才所提到的改变。到了1994年,微软已经得到了全球最大的OEM厂商里面的7家投入到WinPad的项目中,其中包括了当时的Compaq(现在已经被HP收购)、MotorolaNECSharp。这几家后来基本上占领了Handheld PC的市场。

     

    不幸的是,WinPad对于当时来说是太超前了,里面包含了一些太过于超前的技术,譬如手写识别。但是1994年的硬件水平并不足以支持运行这些代码。当时的32CPU才刚刚开始商业上的起步,无论是CPU还是内存的架构都不足以承受这些相对先进的技术所造成的负载。更糟糕的是,1994年的电池技术不便宜,并且功能也不够丰富,续航时间也不长。微软经过了OEM厂商几轮的讨论,最后不得不在1994年秋天放弃WinPad项目。

     

    然而,几乎是同时,另外一个代号为Pulsar的项目在Redmond悄悄地开始了。这个项目的目标是创建一个无线的,通用的消费者产品。这种产品的功能丰富,但是使用简单。人机界面只有少数的输入功能(譬如只有几个按钮),而机器本身则是和x86完全不一样的架构。对于Microsoft而言,这种想法有着美好的前景。因为如果有这种产品,就可以帮助Microsoft从复杂的PC软件市场中抽离出来,从而可以让Microsoft集中力量在简化技术的入门门槛。这一点,无论是Bill Gates本身还是微软内部的智囊团,都认为是有光明前景的。不幸的是,同样是因为硬件发展不足的原因,使得Microsoft被迫放弃了这个项目的研究。

     

    虽然放弃了,但是,微软意识到,上述的想法对于创造一个移动设备的梦想而言是正确的。这种意识,被后来ApplePsionMobile Device市场上面的成功不断的加强。不幸的是,90年代前期的消费者市场还是没有对这种技术准备好,特别是Microsoft所梦想的市场。面对这块新生的市场,规模比较小,玩家比较多,而客户的兴趣尚处于培育阶段,微软不得不实行等待政策,等待技术和市场成熟的时候再采取行动。

     

    随着199412月份WinPad项目组的解散,WinPad的团队和Pulsar的团队合二为一,成立了统一的一个产品组:Pegasus

  • XPE USB 2.0启动技术

    这片文章是我在MEDC 2007中国的演讲稿。PPT附在帖子里面。所有的演示的截图都在PPT里面。 

    首先我们会介绍USB 2.0 BOOT的原理,然后介绍一下USB BOOT的使用场景。

    在讲解USB启动的技术之前,我觉得很有必要和大家回顾一下PC启动技术的历史。微软公司从1975年成立开始至今已经有三十多年的历史了。而微软的成长也是和PC产业的发展有着密切的关系。启动的技术是PC技术一个非常重要的部分。x86的芯片加电启动的时候,会到0XFFFF:0000H的地址去第一条指令执行。通常这个地址上面放置的是一个ROM,这个ROM就是我们熟悉的BIOS系统。因为PC行业在开始的时候基本上都是基于软盘作为存储的,所以那时候BIOS执行完对硬件的初始化之后就会执行一个中断,从软盘的0磁头,0磁道,第一扇区(英文叫做Sector)取得指令集执行。一个扇区的大小是512个字节,所以今后也就约定俗成主引导区(也就是MBR)的大小就是512个字节。之后,随着存储技术的发展,PC的存储就渐渐开始转向硬盘了。而软盘在之后的十几年里面,就退化成仅仅用于安装操作系统或这系统恢复时候启动所需要的设备。而在上个世纪90年代出现的光盘技术,就成了软盘的最后杀手,把软盘的功能也完全替代掉了,所以到了新世纪的时候,基本上大家再也看不到软盘了。近几年来,随着移动存储的技术发展,特别是USB为接口的存储技术渐渐成为了主流。而存储介质NAND Flash(就是我们所说的闪存)的容量越来越大,速度越来越快,NAND Flash的主流厂商目前已经可以坐到百兆级的读取,这个和CD-ROM的兆级,DVD-ROM的十兆级有着明显速度上面的优势。并且,NAND的设备通常是固态的集成电路,不像光存储那么容易磨损。另外,基于闪存的存储体积比较小,非常容易携带。而目前对于许多嵌入式的设备来说,USB的接口基本上是标配,但是因为体积和成本的原因就未必带有DVD-ROMCD-ROM。因此在嵌入式领域,甚至是普通PC就对USB启动产生了大量的需求。在最近两年,许多的PC主板厂商顺应这种需求,在BIOSUSB控制器中加入了USB启动的支持,从而奠定了USB启动的硬件基础。然而,除了硬件的支持以外,作为操作系统的软件业需要加入USB的支持才能够让用户实现USB的启动。因为硬件的支持,只是解决了可以读取NAND里面的主引导区信息。但是主引导区的程序也需要支持USB才能够继续从NAND里面读取出后面更大量的程序,因为这么多年来,主引导扇区的技术还一直保留至今,也就是512个字节而已。并且在MBR里面除了引导程序以外,还包括硬盘的分区表等重要的信息。所以需要微软对启动程序进行改造。在之前的几年,USB启动之能够在一些特殊的USB设备,譬如M-System的存储里面实现,其原理是在控制器内放入了模拟硬盘的芯片,把USB设备模拟成硬盘。这种方法只是过渡的方法,所以在新版微软的操作系统Vista里面,我们已经加入了这个技术。而对于嵌入式的XP,我们则是在2007Feature Pack里面也加入了同样的新版启动程序,从而实现了对大多数USB 2.0存储的支持。今天我们多谈论的USB 2.0启动的技术,就是这样一个背景下面的实现方案。UFD的全称是USB FLASH DISK,我们今天最主要的议题就是用USB FLASH DISK来启动一个嵌入式的XP系统。其实对于FLASH技术,USB不是唯一的接口标准,我们在市面上经常会看到其他形态的接口,譬如SD卡,CF卡,这些都是基于Flash的存储,只是和PC的接口标准不一样。但是USB 2.0接口的速度是400M,远远比CF卡和SD卡的十兆级要快的多。另外,USB的接口在PC上面也要比SDCF等接口普遍的多,在价格上面,同样是Sandisk 1G的存储,U盘要比CF卡便宜。所以在嵌入式系统里面,用U盘作为启动要比CF卡更有优势。

     

    所以USB启动的技术可以用于以下的几个方面,首先可以作为主要的存储,把整个系统都运行在UFD的存储上面。第二,可以用U盘作为安装部署和售后服务,譬如可以把整个安装盘放在U盘里面,或者干脆给用户发一个新的U盘作为系统的更新。我在网络上面看过一些技术爱好者写的一些对比文章,他们发现如果把Vista的安装盘放在U盘里面进行安装要比传统的DVD安装方式要快不少。另外,通过USB启动的技术,还可以对设备进行检测分析和解决问题。我们可以通过嵌入式的XP工具定制出一个小型的系统(大约100M左右),然后再这个系统里面加入对设备的检测工具,这样售后维护的技术人员,只带一个U盘就可以对设备进行维护和更新了,并且还可以用U盘对设备的出错记录文件进行copy带回去分析,这样可以大大提高维护的工作效率。

     

    下面,我们具体讲述一下如何去实现这样的一些技术。首先,我们需要把UFD存储进行分区和初始化,然后把主引导程序写到主引导区内。然后我们通过嵌入式XP的技术定制一个操作系统镜像,copyU盘里面进行系统的启动和初始化。在这个过程中,我们会把一些定制时候的经验和大家分享。然后我们会演示U盘启动的过程,最后我们探讨一下一些常见的问题。

     

    首先是准备U盘的阶段。在这个阶段里面,我们会利用微软提供的工具对UFD存储进行分区和初始化。微软在XP SP2Vista里面提供了一个工具叫做DISKPART。如果大家曾经经历过DOS或者是WIN9X时代的话,应该知道那时候,微软作启动盘的工具是fdsikformat。在XP SP2之后的版本里面,我们用DISKPART替代掉了之前的这些工具。而在嵌入式XP里面,微软针对U盘作了一个更方便的工具:UFDPREP

     

    下面我们先做一下DISKPART的演示。然后我们再做一下UFDPREP的演示。在这个演示当中,我用的是一个1GU盘。这个U盘是我在电脑城里面随便选的一个最普通的U盘。

     

    DISKPART是一个命令行的工具,所以我们先进入命令行,然后输入DISKPART。在XP里面,立即就会进入DISKPART的命令行状态。不过在Vista里面,因为会涉及到安全问题,所以Vista会提醒你要有管理员的权限。进入DISKPART的命令行状态之后,我们可以通过list disk查看一下目前在PC上面所有的磁盘。(如果大家对DISKPART的命令不熟悉,可以通过输入HELP指令来获取帮助)。首先需要先选择对那个盘进行操作,我们看到U盘是DISK 1,所以我们select disk 1。然后我们通过“clean”指令清除这个盘的所有记录。这里大家要注意,clean指令可是把U盘的东西都擦掉了,所以如果U盘里面如果有数据的话,需要先备份出来。然后,我们创建一个分区,注意,分区必须是Primary的分区。我这里指定了分区大小是300M,因为我一会儿定义的操作系统也就1百多M,所以300M是足够了。另外,我发现如果把分区设的越大,copy的时间会比较长,所以不需要把整个U盘都用掉。另外,如果你希望能够全部用完U盘的话,我的建议最好保留32M左右的空间作为EWF的分区(EWF技术我下面会讲到)。分区完了之后,我们就可以通过select partition 1选定这个分区(大家也可以通过select partition的指令查看选定的盘上面的分区列表),然后通过Active指令激活这个分区。

     

    分区激活后,开始格式化。格式化需要一段时间。具体的时间长短,决定于你的分区大小。当然,在格式化的时候也可以通过参数的设定把格式化设定为快速格式化。DISKPART缺省的格式化是普通的格式化,而不是快速格式化。在格式化的时候,大家可以选择FAT32的格式还是NTFS的格式,这里我们选用NTFS。最后通过Assign的指令给一个盘符,以便我们copy操作系统镜像。到了这里,准备工作完成,所以我们可以退出了。

     

    下面,我们看看用嵌入式XP的技术对U盘的启动准备。嵌入式XP提供一个UFDPREP的工具,工具的位置在嵌入式XP安装目录下面的utilitites目录,大家可以通过UFDPREP /?来获取帮助。在这里,我们设定了U盘启动盘的大小为300M,(就是/siez=300的参数)。/y的参数是设定系统不必去提醒我“数据会全部丢失”。这个命令其实就是把MBR的数据写入,然后格式化分区。执行完后,U盘就准备好了。大家要注意一点是,有一些U盘如果不兼容的话(或者是USB 1.1U盘),执行的时候是不会出现Formatting的过程的。为了确认U盘的确准备好,可以通过UFDPREP /verify的命令去确认U盘的状态。

     

    U盘准备好后,我们可以开始定制操作系统了。通过嵌入式XPTarget Designer,我们可以选择我们所需要的组件。嵌入式的XP其实就是把XP专业版分为1万多个组件,其中有9000多个组件是驱动程序,其他的就是操作系统的软件。我们只要选择自己所需要的组件就可以了。嵌入式XP也提供硬件平台的分析工具(TAP),以便与大家比较方便的把硬件的驱动程序加入到平台的支持里面。对于一些不在XP9000多个驱动程序支持列表里面的一些特殊硬件设备或者用户自己的程序,譬如检测的软件,维护的软件等,可以通过Component Designer来进行打包,然后通过Component Database Manager把打包好的组件在Target Designer里面显示出来。对于如何定制嵌入式XP,请大家参加我们另外的课程EXP201 Windows Embedded XP技术探讨,或者去做一下HOL206 构建Windows XP Embedded操作系统映像。在这里,我只想说一下对于USB启动所需要的组件,最主要是USB BOOT 2.0的组件,大家必须把这个组件加入到你所定制的操作系统里面。这个组件最主要的功能是在NTLDR程序里面加入对USB 2.0总线和FLASH驱动的支持。完成操作系统定制之后,我们通过Dependency checkBuild Image创建一个定制的XP,最后镜像会输出到一个开发机的目录。然后我们把那个目录里面所有的文件和目录用XCOPY /S拷贝到U盘,这样就生成了一个我们定制的可启动的系统了。

     

    要注意的一点是,如果使用VISTADISKPART准备的U盘,最好是把NTLDR renamebootmgrNTLDR其实是MBR的启动程序调用的第一个程序。在XP里面,MBR的代码会在系统根目录下面寻找NTLDR这个文件,然后开始执行,所以NTLDR是在引导程序后执行的第一个程序。而在Vista里面,现在的版本的MBR代码会寻找NTLDR或者BOOTMGR这两个文件中的一个,但是在今后的版本里面,BOOTMGR会是标准,所以建议大家如果使用VISTADISKPART,最好用BOOTMGR的名字。

     

    在使用USB BOOT里面,有几点需要注意。因为U盘通常都使用闪存作为存储介质。但是闪存是有一定寿命的。一般擦写的次数是30万到100万次左右。超过了这个次数,闪存就会出现坏块,从而影响到系统的稳定性。所以如果我们所设计的设备是用U盘作为主要存储的时候,一定要尽量减少擦写的次数。在嵌入式的XP里面,微软提供了一个叫做EWF的技术,全称叫做Enhanced Write Filter。它可以把所有的擦写操作重定位到指定的Overlay里面,Overlay可以是一个硬盘,也可以是内存,只有管理员发出Commit的指令才把运行时候的更改信息写入到系统硬盘里面。这个技术最初的设计是为了保护系统盘用的。譬如通过EWF技术可以对系统C盘作保护,把所有的写操作都Redirect到内存里面,而数据则通过网络,蓝牙等方式传输到系统外。这样即使有病毒攻击,病毒也不能够存活,只要重起系统,一切恢复原来的状态。对于U盘启动的嵌入式XP系统,为了减少写的次数,我们可以利用EWF的技术把所有些操作都Redirect到内存里面,从而延长U盘使用的寿命,提高系统稳定性。以前的EWF技术是对整个系统盘进行保护,但是应用了一段时间之后,有许多的客户要求微软开放一些指定的目录以便系统可以写入用户的数据,因此在Feature Pack 2007里面,微软还加入了FBWFFile Based Write Filter)的技术,让用户可以封装系统盘,并且开放制定的目录进行写操作。因此大家可以利用这些技术来设计在U盘里面运行的系统。如果大家需要用到EWF或者FBEWF的技术,则在刚才所做的准备U盘的过程中,需要留有大约32M的空间,以便系统创建EWF的分区。

     

    在创建完操作系统后,我们需要在PC上面设置USB的启动。这是我机器上面USB启动设置,最主要的是要把USB设为最先启动的设备。另外,一般的BIOS都会把USB启动做成是模拟软盘或者模拟硬盘(其实就是中断号的不一样)。微软的USB BOOT 2.0的技术是需要大家把USB模拟成硬盘的,这一点需要注意。

     

     

    虽然USB启动能带来许多的方便的地方,但是他对系统会有一定的要求。并且,运行在U盘里面的嵌入式XP系统也不是万能的,使用这个技术会有一些限制。下面我们就探讨一下这方面的问题。

     

    首先是系统的要求,USB BOOT 2.0的技术要求BIOS必须支持USB 2.0通过0x13H中断启动,也就是硬盘模拟了。另外,要求启动的接口必须是USB 2.0U盘也必须是USB 2.0,因为USB 1.1的速度太慢,会严重影响系统的稳定性。最后一个要求是U盘里面的FLASH必须满足最低的写入速度是不低于9M/s,这样才能保证系统正常运行。(现在的USB2.0U盘大都满足这个要求)。

     

    在使用USB BOOT 2.0的嵌入式XP系统里面,会有一些限制。首先,在目前的版本里面,不支持Standby和休眠的模式,因此不可以使用HORM的技术。不过我们在下一个版本的Feature Pack里面会加入对Standby的支持。另外,因为系统运行在闪存里面,所以我们不支持DUMP,也不会支持换页操作,所以没有Pagefile。因此,如果是一些大型的消耗内存的程序,必须控制其内存使用,或者增加系统的内存。

     

    在嵌入式的XP里面,微软提供了一个Debug版本的NTDECT程序。NTDETEC.comNTLDR启动的时候调用的一个硬盘检测程序。普通的NTDETECT在检测不到可启动硬盘的时候只会报一个invalid的错误。利用Debug版本的检测程序可以把系统检测出来的所有硬盘设备都列出来,以方便大家查错。Debug版本的检测程序就在系统安装光盘的ValueAdd目录下面,名字叫做USBNTD.CHK。只要把这个程序改名为NTDETECT.COM,然后放在U盘根目录下面替代掉原来的NTDETECT.COM就可以了。现在我们把定制好的U盘插入到目标机器上面启动。

     

    下面是用Debug版本的NTDETECT输出结果。

     

    下面是第一次启动时候运行FBAFBA也是微软嵌入式XP的特性之一,最主要的作用是对定制化的操作系进行初始化。在初始化过程中,系统允许执行一些文件。这个特性最主要的目的是因为对于设备厂商而言,定植好的操作系统需要大量的复制到也许是成千上万台的目标机器上面。但是如果大家都是同样一个IMAGE,那么类似序列号,网卡地址等每台机器不一样的信息就不能够写到机器上面,需要人工更改。所以微软提供了一个FBA(全称叫做First Boot Agent)的程序,里面可以设定一些Script或者程序,从而产生序列号,MAC地址等每台机器特性化的信息。FBA的过程正如其名字一样,只会执行一次,因此在之后的启动就直接执行系统代码了。

  • Windows CE 6.0中断处理过程

    这里我们主要讨论的是CE的中断建立和中断相应的大概流程以及所涉及的代码位置。这里所讲述的,是针对ARM平台的。在CE的中断处理里面,有一部分工作是CE Kernel完成的,有一部分工作是要由OEM完成的。

    Kernel代码工作

    ExVector.s:中断向量定义,里面定义的是armtrap.s的函数地址

    Armtrap.s:中断处理定义,最重要是里面的IRQHandler函数,而其中最重要的是CALL OEMInterruptHandler

    Mdarm.c:中断向量加载

    Kdriver.cNKCallIntChain函数:把IRQ转换为SysIntr,值得留意的是pIntChainTable[],是IRQ所对应的ISR处理程序的入口,其中最主要的是其成员函数pfnHandlerpfnHandler的填充,是在HookIntChain里面,这个函数是ISR在初始化的时候调用的。在这个函数里面,如果pIntChainTable为空,则返回SYSINTR_CHAIN,如果pIntChainTable[]不为空,则调用pfnHandler得到一个sysintr值,然后返回之。

     

    OEM定义工作:Oalintr.cOEMInterruptHandler函数,通过查询硬件的中断寄存器,得到硬件IRQ号。对于EINT04-23的中断,通过EINTMASK寄存器,得到相对应的系统IRQ。注意,这里的IRQCE定义的IRQ,是系统硬件IRQ的扩展。然后调用NKCallIntChain看看这个IRQ是否是一个ChainInterrupt。如果函数返回SYSINTR_CHAIN或者返回一个不合法的sysintr,则通过OALIntrTranslateIrqIRQ转化为sysintr。如果是一个合法的sysintr,则返回该值。

     

    单一ISRDevice,主要通过OEMInterruptHandler处理,在OEMInterruptHandler没有定义的IRQ,可以在OAL里面或者驱动的加载里面,通过HookInterrupt函数进行关联。

    多个ISRDevice,通常这是总线设备的需求,因为总线设备上面通常串有几个设备。这些总线上的设备,需要有一个ISR判断究竟是哪个设备发出的中断。这个ISR,是一个DLL的程序,设备驱动必须在初始化的时候通过LoadIntChainHandler(文件名,函数名,irq)加载这个DLL程序。LoadIntChainHandler的定义在kdriver.cNKLoadIntChainHandler里面。对于大多数的总线设备,可以利用微软已经写好的giisr.dll来实现。giisr的实现代码在Public\common\oak\drivers下面。

     

    对于总线设备,如果利用GIISR的话,原理如下:

    总线设备驱动在初始化的时候,通过LoadIntChainHandler加载GIISR,而加载的时候,LoadIntChainHandler会调用GIISRCreateInstance创建一个实例,GIISR会返回一个index值给LoadIntChainHandler,以标示实例,LoadIntChainHandler则会返回一个Handle给驱动,驱动则根据这个Handle存取GIISR。得到这个handle之后,初始化还需要包括从reg表里面读出相关的初始化参数,对GIISR进行赋值,譬如Port AddressMask AddressSysIntr等。

     

    驱动程序在初始化的时候:

    1、创建一个EventCreateEvent

    2、然后用InterruptInitialize函数把sysintr和这个Event相关联

    3Kick-off一个ThreadIST

    4、这个Thread最终是WaitForSingleObjectEventID

    具体的例子,可以参阅USBFN的例子:sc2410pdd.cpp里面,UfnPdd_Start函数;

This Blog

Syndication

Tags

No tags have been created or used yet.

© 2008 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker