手机开机的整个过程

  • 格式:doc
  • 大小:53.50 KB
  • 文档页数:18

本文试图通过代码来深入剖析Qualcomm手机开机的整个过程,即从按下开机键一直到出现待机界面,Qualcomm的手机软件在整个流程中究竟完成了哪些工作。

本文的主要目标是理清手机的初始化流程,并为今后Amoi定做初始化工作提供一个参考。

关键字:开机、Rex、TMC、ui_task、CoreApp一、开机的简要流程分析Qualcomm的平台软件支持两种启动方式:一种是Nor Flash启动方式,另外一种就是Nand Flash启动方式。

Nor Flash启动方式就相当于硬件直接找到一个入口点开始执行代码,相比较而言会比较简单,且Amoi没有采用此种方式,所以本文对于这种方式不做详细分析。

另外一种就是Nand Flash启动方式,这种方式和PC的启动方式比较相像,也是Amoi采用的Boot方式,下面将详细分析在此方式下面的开机过程。

按下开机键之后,将产生一个时钟中断,从而通知AMSS 主芯片的Boot Load硬件去将放臵于Nand Flash上面的第一个Block(8K)里面的Boot代码Copy到内核内存(RAM,这个内存应该是CPU自带的内存,同后面提到的SDRAM 有一定区别,可以把它当作CPU的Cache)的0xFFFF0000地址,并开始执行Boot代码。

Boot的主要任务是完成整个系统的硬件初始化工作(类似于PC上面的BIOS所完成的硬件自检工作,至于Boot的详细工作机制,后文会有详细描述)。

Boot所完成的工作里面,最重要的一件事就是会将整个手机软件代码(AMSS软件包)拷贝到SDRAM中,并最后将控制权交给AMSS软件。

说白了,就是Boot执行完成之后,代码的执行点将由Boot跳转到AMSS软件的的入口点函数main().(此函数在mobile.c里实现)。

代码运行到了Main()之后,在这个函数里面将完成操作系统(rex)的初始化工作,其实现方法是调用rex_init()。

Rex_init()完成的工作很简单:1.完成操作系统必要的一些数据结构(timer链表、任务链表等))的初始化之外;2.接下来,它创建了三个任务,分别是:rex_idle_task、rex_dpc_task和tmc_task。

Idle任务没什么好解释的,目前这个任务为空,什么也没做,dpc_task目前不知道是做什么的,暂时可以不用管。

前面的这两个任务都属于操作系统层面的,由操作系统来维护,和手机软件关系不大。

哪一个和手机软件关系大呢?答案是:tmc_task。

大家可以把这个当作操作系统的入口(主)任务,也可以把它当作整个手机软件的入口任务。

即AMSS 软件里的所有其它任务的创建和维护就是由这个tmc_task 来完成的。

到此为止,整个AMSS软件还并没有跑起来,只是跑到了tmc_task里面了。

在tmc_task里面,会调用tmc_init()来完成整个AMSS软件包的初始化工作,其中最重要的一项工作就是调用tmc_define_tasks()将AMSS软件包所有需要的任务都创建起来了。

比如说slee_task、dog_task、cm_task、wms_task、ui_task等。

这些任务,一般不需要直接和AL层软件打交道,但请大家记住,手机上所有功能的实现最根本点就是由这些服务组件(Service Task)来完成的。

将来大家跟踪一个具体的功能模块时,比如说通话模块,如果需要,可以再去深入研究它的具体实现。

好了,到现在为止,所有的AMSS核心软件就全部跑起来了(手机的功能模块,在软件方面就体现为OS层面的一个任务)。

但现在大家还根本看不到Brew和AEE的影子。

呵呵,各位不要急。

到了这个层面之后,我想稍微多说几句。

最早的Qualcomm平台,比如说5xxx系列,是根本没有Brew的,那个时候的AL(Application Layer)层软件开发,是直接调用底层Service task所提供的API来完成相应的工作的。

从这种角度来看的话,显然那时的开发是比较郁闷和难度较高的。

不过,到了65xx之后,Qualcomm平台引入了Brew,手机开发商就没必要去从这么底层(Service API)的层面进行手机开发了,他们完全可以基于Brew来实现一台手机的所有功能(Qualcomm给我们的参考代码,就是全Brew平台的)。

Brew的运行环境AEE是如何跑起来的呢?关键在于ui_task(),由于ui_task和我们手机开发的关系非常密切,其地位也相当重要,所以,后文我将单独对它进行一个深入的研究与分析。

到目前为止,大家只需要知道ui_task将AEE 加载起来了,并且,它起到了一个中间层的作用,即所有AMSS底层服务组件的消息,都将经由ui_task而转到AEE,并最终转到具体的App(Applet)的执行代码里面(HandleEvent())。

注意:1.上述的开机过程,在每一次按开机键都需要走一遍,即关机之后,整个系统的所有功能都将消失,而不像有些手机,看起来是关了机,但实际上底层还是有一些软件模块在跑。

为什么可以肯定地说上述开机过程每次都必须走一遍,原因很简单,因为我们的平台软件是基于Nand Flash 启动的,所有的代码都需要Copy到SDRAM才能运行,而关机断电之后,SDRAM里的东东会全部丢失,所以,毫无疑问,上述的过程必须每次开机都执行;2.关机的过程相对比较简单,系统检测到关机中断之后,将调用tmc_powerdown_handler()来完成关机动作,它将把所有AMSS的任务都Stop掉,并最后调用rex_exit()退出Rex,从而完成整个关机动作。

3.显然,关机动作前,如果有必要,每一个任务必须将它希望保存的信息保存到Flash上面,以便下次开机时可以得到这些信息;开机流程简图说明:1.Tmc是操作系统层面和AMSS软件关系最密切的一个任务,不过需要OEM商在此处修改的地方应该不多;2.ui_task是在操作系统层面,OEM商需要重点研究清楚的一个任务,它是连接底层Task和上层AL的一个中间层,有可能需要加入OEM商的操作流程;3.CoreApp是在Brew层面的一个AL层的入口Applet,它其着管理整个上层AL层软件的作用,根据产品需求,这个App需要定做;4.AEE是整个上层App的运行环境,目前Qualcomm没有公开它的源码,但它的运行机制,Amoi需要好好研究清楚,我将在另外一篇《Qualcomm平台AEE运行机制深入分析与研究》中探讨它的运行机理和调度机制,大家有兴趣可以参考此文;二、Boot代码深入分析Boot代码大部分是用汇编语言写的,也有小部分,可能需要由OEM商修改,所以用C语言来写。

另外,Boot代码属于Driver范围,所以大家可以在drivers/boot目录里面找到相应的代码。

Boot的代码组织得非常模块化,整个boot 的入口点是在Boot_function_table.s里面,这个汇编代码里面实际上是将Boot需要完成的任务封装成了不同的函数,由不同的函数来完成相应的工作,接下来,我将深入分析这些函数所完成的工作,如下所述。

a)mmu_enable_instruction_cache;这个只有在Nand启动模式时才需要,打开ARM的指令Cache.b)boot_hw_ctrl_init此函数主要是完成两条总线(EBI1、EBI2)控制器的初始化,这个函数执行完了之后,系统就可以知道两条总线上连接了哪些设备,同时也可以找得到这些设备,不过,至于单个设备自身的初始化,则不在这里。

[注]这个函数很重要,OEM商如果需要加新的设备到系统中(挂在两条总线上),则需要定做此模块,目前阶段主要是内存。

另外,如前文所述,这个函数是由C语言来写的,主要目的就是为了方便OEM商定做。

内存设备的修改,可以在这个模块里找到相应的数据结构,相对还是比较简单的。

c)boot_hw_tlmm_init1.晶振时钟的初始化;2.中断表的初始化;3.GPIO的初始化;4.Msm本身的驱动,除了EBI2;d)boot_rom_test这个函数非常简单,只是做一个很简单的Rom检查.(比对两个标志位来检查,并没有一块一块地去检查)。

e)boot_ram_testRam自检,具体算法其实也很简单,就是读、写内存以判断是否成功。

f)boot_ram_init1.拷贝手机代码从Nand Flash到SDRAM。

a.Image__BB_RAM__Base:Core Code;b.Image__APP_RAM__Base:App Code;[注]上述动作是分块进行的,原因是因为Qualcomm支持分块Boot Load.2.将Image__ZI_REGION__ZI区域初始化为0;3.初始化OEM要求的动态Heap;4.至于代码段里的数据初始化,直接在Image里就完成了(编译器完成);g)boot_stack_initializeARM栈初始化,主要是为分块代码加载而预留的.h)boot_cache_mmu_initARM Mmu初始化注意:到此为止,整个Boot的工作就告完结了,那么,它又是如何跳到AMSS的main入口点呢?原因很简单,ARM编译器在链接的时候会自动做出一个__rt_entry(),由此函数来完成ARM库函数的初始化,并最后将代码执行点跳转到main()。

而__rt_entry()会在boot_reset_handler.s里调用,具体细节,大家可以不用太过关心,只需要明白,Boot跑完之后,手机软件就跑到了main里就Ok了。

三.Ui_task的深入分析从大的方向来讲,ui_task只完成两件事,一件是必要的初始化工作(这个也是我们所关心的,即ui_task到底完成了哪些工作);另外一件事就是各种信号量的事件处理,这也是我们比较关心的,即ui_task到底将哪些事件转发给了上层App。

搞清楚了上述两点,我们也就能大致把ui_task 的承上启下的工作机理研究清楚。

1.ui_Init;初始化过程中,ui_task主要完成了如下几件事。

a)创建一个用于Kick Watchdog的定时器,这样WatchDog能够及时得到Kick,假如今后发现手机在ui_task 里面自动重启,很有可能就是这个定时器的Timeout设臵得过短而造成的;b)注册通话相关的回调,主要是和紧急呼叫相关;c)电话本初始化,之所以要进行这个工作,主要是加快开机之后AL层软件操作电话本的速度,但这样将有可能导致开机速度过慢,如果开机速度过慢,可以考虑进入待机界面之后,在后台开一个task去完成这项工作;d)初始化Sound设备;e)向底层服务任务wms_task注册wms回调,这个回调是在IWms组件里实现的。