Splash screen in USBloader

      Qc片子的启动是比较九曲十八湾的,从QCPBL,到QCSBL,再到OEMSBL,最后到启动android的USBloader。在这里我的版本是Android1.6 donut,Google在后面的版本中加入了LK,不过对于在bootloader中加入Splashscreen道理都是一样的。开始没有在OEMbootloader添加主要是因为OEMbootloader不方便打log,不好调试,所以先在USBloader中实现以后再移植到QCSBL中去。

      从道理上来说,要想实现开机画面在逻辑上是比较简单的,把MDP和LCDC跑起来,然后把panel初始化,最后往buffer上扔上你需要显示的数据就行了。不过在实现上还是需要下一番功夫的,主要是要对硬件功能需要一定了解,整理一下达到这个目标需要完成的工作:

     1)首先是要在bootlaoder中添加,所以对bootloader是需要一定了解的,在bootloader跑到哪部分的时候点屏是比较合适的。这里要考虑的时bootloader跑到哪了我们需要的一些API都可以使用了,说穿了就是那些东西初始化可以使用了我们就可以点屏了。

     2)然后就MDP和LCDC要跑起来,要了解让这两个芯片工作起来必须做什么操作。这个一般需要参考QC的代码,因为毕竟我们不是很了解芯片,除了时钟之外,那么一大堆寄存器哪些是需要初始化的,哪些是不需要的我们并不清楚。

     3)最然后就是panel的初始化。这里主要的区别是使用的异步屏还是同步屏的问题,这里我们使用的是SPI-RGB的同步屏,SPI的初始化我们使用GPIO模拟,这里一个最重要的问题就是我们如何在bootloader中操纵GPIO。

     4)最后就是我们需要显示的数据了,一般有两种方法,一个就是将需要显示的图片二进制数据写入数组,另外就是将要显示的图片放入nand分区里面。

      了解了需要完成的工作之后下面就是各个击破~~首先说说bootloader,主芯片上电以后,reset之后供上时钟,然后就会跳到rom上一段特定的地址开始执行代码,这里就是QCPBL了,QCSBL会掉用CONFIG_DATA的数据来初始化RAM和NAND,然后将QCSBL载入ram中执行,QCSBL会将OEMSBL当成动态链接库载入,然后OEMSBL会将USBloader载入内存,并reset ARM11,这样ARM11就开始执行USBLoader。再然后ARM9会将AMSS载入内存,载入以后会通知ARM11载入linux kernel,最后两个核上的系统就都跑起来了。

       我们来重点关注一下USBloader,基本上bootloader都是一个形式,首先一段init.s或者start.s之类的汇编用来设置ARM的一些寄存器,比如设置堆栈指针R13,PC指针R14,并使用R1-R3存储一些参数。汇编执行完以后会blx到bootloader的main或者start之类的函数开始执行。其实bootloader的代码还是比较好看的,毕竟是单线程一路跑下来,比起camera那动不动开3个线程交互的东西好看多了。main里面一般都是初始化RAM,NAND,设置一些时钟,并初始化一些必要的驱动,然后将kernel从NAND中读出来放入RAM,最后将控制权交给kernel。因为USBloader不需要进行RAM的初始化,主要是进行时钟,NAND分区表的一些设置,这里很简答的,我们的Splash screen就可以放在时钟设置以及板级初始化的后面。

       了解完启动过程之后我们再来看MDP和LCDC,要让这两个东西跑起来,一般就是power和时钟的enable,然后就是相关寄存器的初始化。在这里我参考了QC的MDP和LCDC driver的代码,但对于寄存器的设置还是必须要QC支持的,我们不了解芯片,不可能对每个寄存器都设一遍值。在这里稍微描述一下需要赋值的寄存器,图像处理器一般是相通的,一般了解以后对以后其他的芯片也有参考作用。

       比较重要的有DMA buffer的地址,buffer的RGB数据类型,buffer的大小,对齐等等和FB相关的寄存器,然后就是关于LCDC信号极性的一些寄存器,再然后就是LCDC  HSYNC VSYNC之类的一些寄存器,比如start,end之类的,还有一个重要的就是PCLK的rate。基本上enable MDP和LCDC的时钟以后,设置好这些寄存器,芯片就能正确发送数据了,如果有问题,那。。。那再慢慢DEBUG吧~~我开始的时候就是PCLK的rate没设,导致图像怎么都不对啊~~

       最后就是我们的PANEL的初始化了。panel的初始化最重要的一点就是GPIO的使用,因为我们现在使用的是双核,而对GPIO的设置实际上在ARM9上,要在ARM11上设置GPIO具体权限问题。在这里,USBloader通过写GPIO的shadow寄存器来控制GPIO,这里有一个特别注意的是必须将GPIO的权限赋给ARM11,不然写shadow寄存器是不管用的。知道怎么操作GPIO那么初始化的过程就简单了。

        在这里有个同步屏和异步屏的区别,同步屏本身内部不具备产生时序的电路,所有的时序都必须由MPU来提供,而且它不具备LCDC控制器,所以屏的data必须保证在一个刷新频率。而异步屏具有自己的LCDC控制器,不需要主芯片的LCDC,要让它显示图片只需要一个更新就可以了,不需要不停地提供信号。

        那么现在屏就开始正常工作了,我们最后看一看如何要显示我们的图片。要显示图片,只要将RGB数据放入buffer中,DMA就会将数据送给panel显示了。所以data的数据类型必须和寄存器的设置相匹配。在这里我是使用数组的方法来保存要显示的数据,当然也可以读取分区表里面的类容。一般来说Splash screen都是raw data数据经过游程编码产生的*。rle文件,下面介绍下如何获得我们需要的像素数组:

        首先使用imagemagic提供的covert命令将PNG图片转成rawdata,命令是:convert *.png -depth 8 rgb:*.raw  然后使用android提供的RGB2565命令将数据转成rle格式,rgb2565 -rle <*.raw>   *.rle    最后使用xxd -i  *.rle > initlogo.h将rle文件转化成数组。这里有一个要特别注意的是使用xxd获得的数组是unsigned char型,而rle文件都是short格式存储的,这样就需要将两个char合成一个short,因为x86上的linux是使用litte-edian来存储数据,所以合并的时候要注意高位实际上是在后的。这里要特别注意,我开始就因为没注意,结果图像出来总不对。


         基本上就是这些了~~ 以后再想到啥再补充~~

 

你可能感兴趣的:(android,工作,汇编,存储,buffer,图像处理)