摘要:
本文主要阐述了基于linux操作系统的数字电视机顶盒的常用几种升级方式:OTA,USB,网络,结合常用的bootloader:cfe,u-boot实现升级做了简述,并综合对比其各自的优劣。
关键词:
数字电视机顶盒,升级方式,linux,u-boot, cfe ,OTA ,bootloader
随着技术的日新月异,以及为了满足用户对功能和使用的要求,需要对机顶盒进行升级来满足需求,升级不仅能解决程序的BUG,还能增加新功能,但是升级考虑不全面将会造成很多问题,本文就机顶盒的常见几种升级方式的设计与实现来进行探讨,目前常用的升级方式有,OTA升级,USB升级,网络升级,以及串口升级,由于目前程序越来越大,电脑对串口的支持,尤其是笔记本电脑一般没有串行接口,虽然有USB转串口之类的设备,串口的传输速度也是很慢的,所以串口对整个程序的的升级已经越来越少。这里的OTA升级是讨论针对数字电视的有线数据传输来进行的升级。后面两种升级方式基本上是嵌入式终端设备的通用升级方式,不限制于具体的设备。
目前的升级,一种方案是直接在bootloader中实现,另外一种是bootloader+应用层实现。前者实现难度相对较大,人机界面不是很友好,但能节省部分空间,代码相对独立。后者实现难度较低,人际界面也友好,扩展性强,但需要额外的空间,仍然依赖bootloader。
摘自《嵌入式系统BootLoader技术内幕》
对于目前大多数嵌入式操作系统的机顶盒,需要升级的部分大致可以分为bootloader,kernel,rootfs+app,有的可能划分更细。升级程序和bootloader息息相关,一般bootloader起到引导和升级,就需要在机顶盒出厂前已经固化并保证数据安全,为后续的升级做准备和铺垫。针对目前常用的linux机顶盒环境,bootloader一般有u-boot,cfe,redboot以及其他一些bootloader。U-boot作为一种通用的bootloader已经成熟的应用到各种嵌入式设备中,CFE是broadcom公司针对其芯片做的一个通用固件环境,基于MIPS架构。我们公司拥有目前主流的架构arm架构,super-h架构,mips架构和powerpc,主要用到u-boot和cfe,我主要也就以上两种bootloader做一些升级方面的讨论。
USB升级:
优点:实现难度小,依赖性小,适合单个升级。
缺点:大批量升级效率较低,需要额外U盘设备。
USB升级针对不同的平台可以有不同的方法,主要的实现方法有底层实现和应用层实现两种方法。因为现在不同平台的bootloader都提供了对usb存储设备的支持。有通用bootloader如u-boot,以及某些公司的私有bootloader如broadcom的cfe。
一般情况下,可以将升级直接做到bootloader里面,这样的好处就是可以保证安全以及数据依赖性小,缺点就是实现难度相对来说要大一点。USB升级以及tftp升级方式完全可以在bootloader里面来实现,因为其依赖性小,以上的bootloader已经做了这方面的相关驱动,实现起来难度较小,对bootloader环境命令的依赖性较大,有的可能需要修改bootloader的源代码,添加部分适合升级的命令和程序。后面将提到的OTA升级,由于其依赖调制解调器,在bootloader中移植难度较大,一般不在bootloader中做。对于大多数NANDFlash,为了保证数据的安全性,许多厂商都是将bootloader裁剪到128K之内,以满足对bootloader数据的安全性,这就需要从其他方面来实现以上所说的升级。针对U-boot的USB升级,U-boot已经对USB设备以及fat分区有了良好的支持,u-boot启动后,进入到芯片代码主函数:start_XXXboot,以上XXX可以是sh4,arm等,根据实际的架构找到相对应的函数。通常我们可以在u-boot的引导kernel的之前做相关升级处理。
void start_XXXboot
(void)
{
……………
//在这里添加我们的USB升级判断程序。
Usb_init()
Usb_stor_san(1)
//判断是否需要升级
If(1 ==
need_update)
{
//置位升级标志
……………
}
for (;;) {
main_loop ();
}
}
在main_loop函数中添加具体的升级程序
voidmain_loop (void)
{
…………省略前面代码……………….
//添加USB升级的具体函数
usb_update_file();
s= getenv ("bootcmd");
debug("### main_loop: bootcmd=\"%s\"\n",
s ? s :"");
if(bootdelay >= 0 && s
&& !abortboot (bootdelay))
……………….
}
这样就在U-boot下面完成了一个USB升级方案。需要开启相应的宏开关,如USB,FAT。编译后可以将U-boot裁剪到128K之内。这种方式主要先从usb读取升级文件到内存,再调用u-boot本身的nandwrite的相应烧写命令来实现的,支持范围广,由于其开源和通用性,所以支持很高,可以对各种文件系统直接进行烧写,甚至有些网友移植了在u-boot下直接烧写ubifs文件系统的命令。是一个很好的扩展,目前U-BOOT支持主流程序的烧写。
Cfe相对于u-boot来说具有很强的针对性,只针对broadcom的mips架构,cfe对usb进行了封装,使用各种烧写都是用统一的flash命令,在CFE中使用USB比u-boot还要方便方便,默认就可以直接支持tftp,usb烧写程序,还可以直接通过网络或者USB存储设备直接从内存中启动,这也为我们在CFE下做升级提供了很好的基础。Cfe封装了以分区的形式来烧写程序,但不支持ubifs的直接烧写。所以在使用CFE烧写不支持直接文件系统时,可以有两种思路:
在CFE中添加对相应文件系统的烧写支持,此方案的优点是节省了总的升级时间,缺点是实现难道太大,不同的文件系统需要添加不同的代码来适应,增加了CFE代码量。
在CFE中从内存启动带busybox的内核,这块broadcom有实现,然后通过linux的命令来实现文件系统的烧写,此方案的优点是对文件系统支持较大,扩展性很强,缺点是需要用到临时系统,总的升级时间较第一种长60秒左右。
实现伪代码如下:
void cfe_main(int a,int
b)
{
…………………..//省略CFE初始化代码
If(TRUE ==
check_usb_update())
{
exe_usb_update();
}
//下面就是引导内核还是进入CFE命令行,在这之前添加。
if( !(sflags &
NO_STARTUP) )
cfe_auto_sysinit(sflags
&FORCE_SYSINIT);
if( !(sflags &
NO_STARTUP) )
cfe_autostart();
cfe_command_loop();
}
以上代码在CFE的两种方案的USB升级都需要添加,只是具体实现在exe_usb_update中不同。Check_usb_update()主要是检测U盘是否有升级文件和是否需要升级,exe_usb_update()是从U盘中读写升级文件并烧写,完成升级功能。
以上是USB升级的常用两种举例,通用性较强,只需要根据自己厂商适合的方式来实现代码即可,也可以稍微修改作为工厂批量生产方式,实现完全自动化。
OTA升级
优点:用户参与少,直接由前端控制,适合大批量升级
缺点:依赖前端码流,依赖机顶盒tuner。
OTA升级(OnTheAir),又称空中升级,是指用户终端直接通过信号通道接收下载方式来升级软件。是厂家最重要的一种升级方式,用于大批量用户升级。在手机,以及其他一些移动终端也有用到,它们主要是通过3G或者Gprs等无线升级方式,也可以总体概括到网络升级中。只是具体区别于通常所说的电信网络以及这里的无线网络和我们将讨论的数字电视网络。机顶盒的OTA升级数据可以根据不同厂商自己的方式封装,打包成TS流,然后播放,机顶盒终端接收到流,通过解析NIT等相关表来获取升级信息。NIT表中主要包括升级频点的参数信息,如频率,符号率,调制方式等。在OTA数据的处理上,采用DSM-CC规范。ISO-IEC13818-6里有对DSM-CC规范的详细说明。DSM-CC是为在异构网络环境下传送多媒体宽带业务开发的ISO/IEC标准,特别适合广播电视网络。DSM-CC是与传输层无关的协议。这样任何编写好的使用DSM-CC的应用程序不需要关心其下面的服务器和客户机之间使用的传输层,从纯MPEG-2传输流网络到核心ATM网和各种ATM或非ATM的接入网,甚至包括高速局域网,到端到端的ATM网络的多数宽带网络,都可以传递使用同一个应用程序。码流机播出码流,机顶盒通过解析NIT表获取到相应的升级信息,传递给tuner来进行锁定,如果锁定好,则通过dmx来获取数据,这样我们新建一个线程来处理接收到的数据,根据接收数据的起始地址,我们判断是DSI还是DII或者是DDB,我们必须首要要获取到DII的信息,因为这里有DDB数据的整体说明,这有获取了DII的信息后,我们才能对所接收的数据是否完整进行判断。对于不同厂家的OTA升级有可能不需要完全实现DSI,DII,DDB三种,但至少需要实现DII和DDB。这里面我们涉及到数据校验,来保证数据的完整性,如果是对数据进行了加密或者封装,还需要做相应的解析。我们通常是将所有升级的所有部分合并成为一个bin文件,最后再一次性获取整个bin文件保存到内存中,再分解出各个部分,烧写到每个文件制定的地址上去,完成整个升级过程。整个过程只有烧写程序的时候如果断电无法恢复,但由于烧写程序的时间很短,几率几乎为0,所以安全性还是可以保证的。
不同平台的OTA实现也不尽相同,但思路都是需要针对具体平台对锁频,接收和解析码流,最后烧写到flash中。
TFTP升级
优点:简单。
缺点:依赖于网络,需要服务端支持。
相信做开发的人都或多或少用过TFTP,NFS,我们在开发中使用TFTP来做烧写处理,被认为是最简单的方式,同样只要用户终端有网络,并被获知需要升级,和已知TFTP服务端及文件名,便能很容易的实现升级,在TFTP升级中,我们不需要额外修改tftp的代码,只需要为自动参数传递升级的命令即可。
在uboot中需要先设置serverip参数,然后使用
tftp内存地址服务端的文件名如:tftp80000000 vmlinux.ub
在CFE中可以直接使用
flash–noheader服务器IP:文件路径分区
如:flsah–noheader 192.168.1.100:/vmlinuz
flash0.kernel
考虑到网络的连通的不确定性以及丢包的问题,一般我们在内网中使用或者可以在工厂批量升级使用。
当然升级方式还有多种多样,可以硬盘升级,http,ftp,串口升级等等,串口升级由于其传输速率问题已经不考虑在做整个升级文件的烧写,目前常用串口升级来更新序列号,MAC地址,厂家ID以及版本信息等,其他的方式不外乎就是通过USB接口或者网口,万变不离其中,都几乎可以从以上三类来进行变种。
参考文献:
1.《嵌入式系统BootLoader技术内幕》http://www.ibm.com/developerworks/cn/linux/l-btloader/
2.《数字电视系统数据广播规范》
3.《ISO-IEC13818-6 Mpeg-2 Digital Storage
Media Command & Control》