过完2015年春节回来了,利用上班前的几天时间,先把这篇文章写完,本来是先写《DAVINCI DM3730开发攻略——linux-2.6.32移植》,但是那篇文章涉及内核的东西太多,不太好写,而本人已经很长时间没写新文章了,先发布这篇文章。后来想了想,从应用程序使用的角度分析,再一步一步深入内核里边去,也许更好。

前面几篇DM3730开发攻略讲到:一个DAVINCI  DM3730板子程序由xload,uboot, linux-2.6.32或者(linux-2.6.37),文件系统rootfs和存放在文件系统里边的很多应用程序组成,这个顺序是从CPU运行的顺序排列的,或者从烧到NAND FLASH的角度讲:我们桐烨科技的命名是:dm3730_xload.bin,dm3730_uboot.bin,dm3730_kernel.bin,dm3730_ubifs.bin(里边包含很多应用程序,我们使用ubifs而不是jffs2),有些客户还加上自己的应用程序app等BIN文件。

 

1、文件系统移植:

在DVSDK4_03安装包里边(不清楚的网友可以先看看本人在51CTO博客一篇《DAVINCI DM3730开发攻略——DVSDK4_03和双核CODEC机制介绍》),本人开发目录dvsdk4_03\filesystem,人家TI(包括合作第3方)已经提供arago-base-tisdk-image-dm37x-evm.tar.gz和dvsdk-dm37x-evm-rootfs.tar.gz,其中arago-base-tisdk-image-dm37x-evm.tar.gz是经过第3方裁剪的文件系统,非常适合烧写NAND FLASH里边,也可以直接解压做为NFS文件系统(NFS环境设置见本人51CTO博客一篇《DAVINCI DM3730开发攻略——开发环境篇》);而dvsdk-dm37x-evm-rootfs.tar.gz是不经过裁剪的文件系统,里边的众多应用程序、很有价值的LIB文件、测试程序,包括测试DMAI例程的应用程序、encode应用程序、decode应用程序、wifi应用程序等等,特别关注usr/share/ti里边的例子,总之非常丰富,具体有什么价值,还需要有兴趣在这方面开发的网友自己打开文件夹看看。

wKioL1TtPjXBTqeyAAGgU7vwlxc721.jpg

图-1 dvsdk-dm37x-evm-rootfs有关TI测试应用程序

 

这个dvsdk-dm37x-evm-rootfs.tar.gz超级大,不适合烧写到NAND FLASH里边去。我们也是在arago-base-tisdk-image-dm37x-evm.tar.gz基础上面,把dvsdk-dm37x-evm-rootfs.tar.gz有用的东西COPY过来,然后加上自己开发的应用程序和修改的脚本,同时也对arago-base-tisdk-image-dm37x-evm.tar.gz进行裁剪,才得到自己产品的文件系统rootfs。这个rootfs可以做为NFS测试,也可以使用mkfs.ubifs,mkfs.jffs2或者mksquashfs等工具制作烧写到板子NAND FLASH的产品文件系统(xxx.bin或者xxx.img之类文件),至于这些文件系统如何制作,这里不再累赘,因为众多网友都写有很多博客文章进行介绍,特别是omap3530,dm3730的ubifs,本人就没必要多说了(题外话,我们碰到一些客户对NFS文件系统和烧写到NAND的文件系统都不知道怎么回事,就敢做DAVINCI嵌入式产品,只能说他们老总有钱养人和项目烧钱啊,这种客户我们现在不敢卖开发板了。现在网络这么发达,技术文章非常多,还有其他几百块钱的linux嵌入式开发板多如牛毛,在大学随便买回来学习学习,一点难事都没有。从各大门户网站论坛来看,各路大神都下了论断,从2015年开始国内企业倒闭潮模式开启,找工作更难了,如果家境不好的学生还和其他人醉生梦死去玩,苦果等出到社会慢慢品尝吧。以前在DM368开发攻略说过,危机有“危”也有“机”,技术过硬的人才还是很抢手的,毕竟现在是地球村模式,科技还是一直向前发展的,淘汰的都是些低效低技术门槛的企业)。

 

2、DVSDK视频应用程序介绍

介绍完文件系统的移植,现在可以介绍应用程序了,以前写DM6446开发攻略的时候,没有单独介绍,这里我们为了完善DAVINCI开发攻略,补充一下。我们拿TI DAVINCI最经典的音视频encode例子来说吧,这个encode 涉及到原始图像采集和dsp调用,多线程如何配合运行,非常有价值。TI DAVINCI双核芯片DM6446,DM6467T,DM3730这几个经典的芯片都是同样的应用架构。在dvsdk4_03\dvsdk-demos_4_02_00_01\omap3530目录里边,有encode,decode,edge_detection三个例子,其中edge_detection(边缘检测)用到c6accel的LIB,侧重DSP算法移植,不是很经典,我们不介绍,decode也比较简单,就是如何调用h264解码,mpeg4解码,jpeg解码,音频g711的解码。我们还是选择encode介绍,看看encode如何录制h264视频文件和g711音频文件(同时修改一下可以支持mpeg4或者jpeg压缩)。结合本人的《DAVINCI DM3730开发攻略——DVSDK4_03和双核CODEC机制介绍》,通过这个encode具体的例子,更加深入了解双核的是如何工作的。

要正确编译encode例子,必须编译内核linux-2.6.32和其他相关的元素,最后才能编译encode的例子,见本人那篇51CTO博客《DAVINCI DM3730开发攻略——DVSDK4_03和双核CODEC机制介绍》,这篇文章非常重要,顺便提一下,其他元素编译完后,都产生对应的临时文件和输出文件,这些都是下一级要编译元素的所依赖的文件,你对其中一个make clean等清除命令,后面的元素模块肯定编译不过去。Encode例子直接调用的是DMAI元素(dvsdk4_03\dmai_2_20_00_15\packages\ti\sdo\dmai),而不是直接去和内核打交道,也不是直接去跟DSP打交道。DMAI就是一个封装好的中间件,DMAI可以直接通过open设备节点和内核驱动打交道,但是它也不能直接去调用DSP SERVER,而是去调用codec-engine里边的VISA接口,只有codec-engine配合dsplink等元素才能调用DSP SERVER。这里提到DSP SERVER就是C64+ DSP程序了,一个DSP核只有一个DSP SERVER(就是编译出来的cs.x64P),而一个SERVER可以有N个DSP 算法CODECS,就是那一大堆的h264,jpeg,mpeg4编码解码,g711、aac音频编码解码,以及客户自己的算法(例如我们桐烨科技的ty_video_copy算法)。

我们打开dvsdk4_03\dvsdk-demos_4_02_00_01\omap3530\encode文件夹,先打开Makefile,修改第79行,

#SOURCES = $(wildcard *.c) $(wildcard ../*.c)注释掉

#HEADERS = $(wildcard *.h) $(wildcard ../*.h)注释掉

改成:

SOURCES = $(wildcard *.c)

HEADERS = $(wildcard *.h)

然后把dvsdk4_03\dvsdk-demos_4_02_00_01\omap3530\ctrl.c,ctrl.h,demo.h,ui.c,ui.h  5个文件COPY进encode文件夹,我们这样做是因为这几个文件和decode文件夹共享文件,如果对5个文件修改,会同时影响encode和decode,为了保持工程的独立性,我们还是COPY到每个文件里边,这时就需要对encode里边的差不多每个源码文件,凡是使用demo.h等头文件include的路径改一下代码(#include "../demo.h"改成#include "demo.h")。以后参考encode建立自己的工程,比如我们的tvp5158_d1,完全参考encode例子,几乎一模一样,encode里边的是encode.cfg,不需要修改,下面就拿这里边的文件介绍。

wKiom1TtPUexTKpzAAGZlemaUJU370.jpg

图-2 encode例子里边的源码

 

Capture.c就是专门负责视频采集的源码了,这个会去调用到DMAI目录下的dvsdk4_03\dmai_2_20_00_15\packages\ti\sdo\dmai\linux源码函数和dvsdk4_03\dmai_2_20_00_15\packages\ti\sdo\dmai\linux\omap3530源码函数,里边也有对应的Capture.c,只不过这个DMAI里边的Captue.c是和li nux内核里边V4L2驱动对接,把这源码打开,好好看看,分析Capture_create()等等函数,一切都明白了,以前写过的V4L2的文章,都可以对接得到,DM6446、DM6467T、DM3730一个样,当然DM8148、DM8168、DM8127就不是这种软件架构了。同样encode目录下的标清视频CVBS输出display.c也和Capture.c一样,跟DMAI目录下的对应display.c和display_v4l2.c对接。Video.c就是如何调用DSP H264等算法去压缩采集线程放过来的数据,特别看看Venc1_create()函数和Venc1_process()的调用,通过这两个函数,可以在ARM应用程序去访问DSP算法,而我们客户的算法可以参数这个Venc1的东西,可以使用Venc_create()函数和Venc_process()去实现,对应的DMAI接口源码在dvsdk4_03\dmai_2_20_00_15\packages\ti\sdo\dmai\ce目录下。至于如何实现,需要大家回去自己慢慢摸索,我这里点到为止。去分析DMAI和codec-engine里边的VISA接口不是一天两天就搞明白的。Write.c是专门把video.c压缩好的H264 BUFFER数据进行文件方式保存(录制结束后可以从开发服务器把xxx.264 COPY出来,使用VLC或者暴风影院播放录制的文件)。Ctrl.c里边的线程就是处理类似按键和IR这些应用。每个线程里边都是一个while的大循环, 线程间图像数据BUFFER的管理使用FIFO。TI 提供的这几个线程间的BUFFER管理比较乱,特别是加上display线程后,录制的图像不是很连续,拿来学习是没问题的,做产品就不行了。

 

3、编译和运行encode的例子

我们在《DAVINCI DM3730开发攻略——DVSDK4_03和双核CODEC机制介绍》介绍如何编译cmem,sdma,dsplink,lpm,codecs等模块,特别是总的dvsdk4_03\Makefile和总的路径环境参数Rules.make,根据总Makefile编译方法,编译出来的模块全部自动COPY到NFS文件系统:

/home/davinci/dm3730/dvsdk4_03/filesystem/dm3730rootfs/opt/dvsdk/dsp目录下,

本人那篇文章特别写了个脚本,如何编译这些元素,比如在总的Makefile有个cmem的编译和install:

cmem_install:

    install -d $(EXEC_DIR)/dsp

    install $(CMEM_INSTALL_DIR)/packages/ti/sdo/linuxutils/cmem/src/module/cmemk.ko $(EXEC_DIR)/dsp

我们在总Rules.make最后面一句定义EXEC_DIR,

# Where to copy the resulting executables

EXEC_DIR=/home/davinci/dm3730/dvsdk4_03/filesystem/dm3730rootfs/opt/dvsdk

 

编译完相关的模块,最后才去编译demos,也就是我们的encode或者本人的tvp5158_d1,直接进到dvsdk4_03\dvsdk-demos_4_02_00_01\omap3530\encode目录下使用make clean和make,就会得到encode这个可执行的linux应用程序,你可以把这个应用程序COPY到NFS文件系统指定的目录/home/davinci/dm3730/dvsdk4_03/filesystem/dm3730rootfs/opt/dvsdk。

 

好了,编译如果一切OK,而且板子模拟视频接好,或者麦克风接好,可以给板子上电,进到NFS模式就行调试,执行以下命令:

在当前目录下(filesystem/dm3730rootfs/opt/dvsdk)录制H264视频文件:

./loadmodule.sh

./encode –v xxxxx.264

录制G711音频文件

./loadmodule.sh

./encode –s xxxxx.g711

 

录制视频的使用-v参数,录制音频使用-s参数,这些都在main.c里边有,可以去分析源码。

运行10秒~10分钟,使用Ctrl+C终止运行,那么在linux服务器对应的NFS文件系统/home/davinci/dm3730/dvsdk4_03/filesystem/dm3730rootfs/opt/dvsdk下面得到刚才录制xxx.264文件。

 

这个loadmodule.sh基本内容见下面(桐烨科技DM3730开发板使用的):

 

# TONGYE Tech. Memory Map for DM3730 EVM without Android

# Start Addr    Size    Description

# -------------------------------------------

# 0x80000000     120 MB  Linux

# 0x87800000     32 MB  CMEM for ARM and DSP

# 0x89800000     104 MB  CODEC SERVER for DSP (20M for DDR2)

insmod /opt/dvsdk/dsp/cmemk.ko phys_start=0x87800000 phys_end=0x89800000 allowOverlap=1 useHeapIfPoolUnavailable=1

insmod /opt/dvsdk/dsp/dsplinkk.ko

insmod /opt/dvsdk/dsp/lpm_omap3530.ko

insmod /opt/dvsdk/dsp/sdmak.ko

 

在另外一篇51CTO博文《DAVINCI DM3730开发攻略-U-BOOT-2010.06的移植》提到UBOOT参数bootargs,里边有个mem=120M@0x80000000的参数:

这个参数和loadmodule.sh、dvsdk4_03\codecs-omap3530_4_02_00_00\packages\ti\sdo\server\cs目录下的memmap.tci分配的地址一一对应,mem=120M@0x80000000的意思是从0x80000000这段内存分配给linux,后面紧跟的从0x87800000开始分配的32M专门给CMEM(所有双核DAVINCI芯片)重要的共享内存段,最后面104M是分配给DSP使用的,ARM和DSP都可以对32M的共享内存进行访问,上面提到的Capture.c和Video.c使用BufTab_create()函数产生的BUFFER都是指向这个内存,所以客户自己的算法可以对从ARM采集到原始的YUV4:2:2数据在DSP端进行图像分析。上面那些insmod 动态加载几个重要元素驱动,是必须的,否则无法去运行DSP SERVER。

 

以上是从encode应用程序角度进一步分析DVSDK软件架构,对开发DM3730的网友应该有点帮助。这个2014年公司过得比较艰难,公司运营成本越来越高,而卖给客户的产品利润越来越薄(本人认为中国大部分公司也碰到同样的问题,企业负担越来越重,大环境越来越差),同时也碰到一些合作不愉快的公司,发觉做TI DAVINCI方案,越是高级的CPU开发周期越长,所以大半年没怎么写文章了。做产品和做样机不是一回事,和大客户做好一个大批量生产的产品非常耗本人精力,但是为了公司的生存,也没办法。也由于太累了,公司也调整业务,不太想做开发板了。我们在DAVINCI方案能够坚持做下去,是由于TI 的带DSP的CPU生命周期长,以及几个合作愉快的老客户支持。DM3730采集1/4寸COMS 200万还是可以的,功耗低是摆在那里,一个高清720P智能视频分析相机功耗竟然不到4瓦。非常适合低成本人脸识别,低成本高清IVS产品设计,4CIF双目分析产品等。当然,要做1080P  60帧高清产品只能使用DM81XX了,不过这个DM81XX方案成本相当贵,功耗一般超过10瓦。

写了这么多,希望对在这方面开发的网友有帮助,有错误的地方可以指出更正,谢谢。