如何构建达芬奇的DSP Server

时间:2021-06-25 00:34:56
德州仪器(TI)的达芬奇(DaVinci)数字媒体 技术 平台包括四大部分:芯片(处理器)、 开发 工具或开发套件、 软件及技术支持。其中软件开发涉及到操作 系统、音 视频编解码算法及ARM和 DSP之间的分工协作,让很多 工程师感到比较复杂。为此TI推出了一系列软件模块和工具来建立Davinci软件开发的框架,方便 工程师在此基础上快速的开发自己的产品。这些软件模块和工具包含在TI的基于达芬奇技术的数字视频评估板的软件开发包中。


一般的视频 应用系统中,Davinci的ARM负责操作系统应用, DSP负责 运行音视频codec算法处理,ARM通过TI的Codec Engine机制调用 DSP侧的codec。那么怎样把不同的codec算法集成到一个 DSP可执行 程序(称为 DSP Server)中,又保证它们占用的 资源不冲突?本文从Davinci软件结构入手,介绍如何构建 DSP Server,及如何通过 DSP Server的配置 文件配置FC(Framework Component),以便通过FC管理 DSP的资源。

达芬奇DMSoC软件概述

一般来讲,软件系统分为应用层、信号处理层和I/O层三部分,TI提供的达芬奇参考软件框架就是基于这样的结构,如图1所示。Davinci的应用工程师可以在系统的用户空间在系统 功能性上添加和发挥自己的特色。信号处理层通常都运行在 DSP一侧负责信号处理,包括音视频编解码算法、Codec Engine、 DSP的实时操作系统 DSP/BIOS及和ARM通信的模块。I/O层就是我们通常所说的驱动,是针对Davinci外设模块的驱动程序。

如何构建达芬奇的DSP Server

其中应用层通过Codec Engine的VISA(Video, Image, Speech, Audio)API来调用 DSP侧的算法,通过EPSI(Easy Peripheral Software Interface)API来访问和操作Davinci的外设。这三个部分通常对应三个Davinci软件开发小组。当然还需要一个系统集成工程师把这三个部分集成起来,不过VISA API和EPSI API的存在已经大大简化了集成工作的复杂程度。

如图2所示,DaVinci的软件开发通常需要四个步骤(本文以codec运行在 DSP为例):

如何构建达芬奇的DSP Server

第一步,工程师需要基于 DSP利用CCS开发自己的音视频编解码算法,编译生成一个编解码算法的库文件*.lib(等同于Linux环境下的*.a64P,直接在Linux环境下修改文件后缀名即可)。如果要通过Codec Engine调用这个库文件中的算法函数,那么这些算法实现需要符合xDM(xDAIS(eXpress DSP Algorithm Interface Standard) for Digital Media)标准;Codec Engine机制下不符合xDM标准的算法实现需要创建算法自己的Stub和Skeleton(具体请参考spraae7.pdf)。
第二步,生成一个在 DSP上运行的可执行程序*.x64P(即.out文件),也就是 DSP Server。本文将详细介绍这一步。
第三步,根据 DSP Server的名字及其中包含的具体的音视频编解码算法创建Codec Engine的配置文件*.cfg。这个文件定义Engine的不同配置,包括Engine的名字、每个Engine里包括的codecs及每个codec运行在ARM还是 DSP侧等等(具体说明,请参考sprue67.pdf的第5章Integrating an Engine)。
最后,应用工程师收到不同的codec包、 DSP Server和Engine配置文件*.cfg,把自己的应用程序通过编译、链接,最终生成ARM侧可执行文件。

Codec Engine概述
前面我们提到,应用工程师通过调用Codec Engine的API来调用和运行符合xDAIS的算法(关于API的具体信息,请参考sprue67.pdf第4章)。在Davinci软件中,符合 xDAIS的音视频编解码算法(即xDM算法)的调用是通过Codec Engine的VISA API完成的。Codec Engine通过这套API为算法的执行提供了一个标准的软件架构和接口,体现在以下几个方面:
1. 通过Codec Engine API调用的算法可以运行在本地(ARM侧)或者远端( DSP侧);
2. Codec Engine可以基于ARM+ DSPDSP或ARM上运行;
3. 无论Codec Engine运行在ARM还是 DSP上,对应的Codec Engine API都是完全一致的;
4. Codec Engine的API与操作系统无关。比如Linux、VxWorks和WinCE环境下的Codec Engine API都是完全一致的。

Codec Engine是介于应用程序和具体算法之间的软件模块,其中的VISA API通过stub和skeleton访问Engine SPI最终调用具体的算法。因此,Codec Engine的工作是通过完成VISA API的任务来体现的。VISA API分为四部分VISA create/control/process/delete,我们以codec算法运行在 DSP为例,通过VISA API的执行过程了解Codec Engine的工作原理。

在调用VISA API之前需要在应用程序中通过Engine_open()这个Engine API把 DSP的可执行程序加载到 DSP的memory,同时把 DSP从复位状态释放,这时 DSP开始运行 DSP Server的初始化程序在 DSP侧创建一个优先级最低的任务RMS(Remote Management Server),RMS负责管理和维护对应到具体codec算法的Instances。如图3所示,应用程序调用VISA create API,相应的VISA create函数到Engine SPI中的Codec table中查到这个codec运行在远端 DSP 侧。接着Engine SPI通过OSAL(Operating System Abstraction Layer)、 DSP Link把VISA create的命令传到 DSP侧的RMS。RMS通过 DSP侧Engine SPI的codec table找到要调用的codec算法后,就会在RMS中创建一个相应的Instance(即一个 DSP/BIOS 系统中的任务)。VISA create会返回一个Instance的Handle,以便于给这个Instance做后续的VISA control/process/delete提供信息。VISA delete和VISA create原理类似,只是RMS删除掉相应的codec算法的Instance和执行codec算法的任务。

如何构建达芬奇的DSP Server

概括来说,VISA control用来动态的修改codec instance的属性,VISA process用来对算法的输入数据流做处理并返回一个输出数据流。如图4所示,应用程序在调用VISA process/control时会通过xDM Stub把传递给codec算法的参数收集起来,并且转换成 DSP可以识别的物理地址。Stub把这些参数和相关的命令通过Engine SPI、OSAL和 DSP Link传递到 DSP侧的Instance。Instance再通过Skeleton把传递过来的参数和命令解析出来,通过 DSP侧VISA control/process对codec算法执行control/process。

对Codec Engine有了基本工作原理的了解之后,我们就会更清楚的理解 DSP的软件怎样配合应用程序工作及 DSP Server中除算法之外还应该包括哪些内容。

创建 DSP Server

对达芬奇的软件来说, DSP Server也叫Codec Server。其中“codec”是一组算法。从图3和4可以看到,除算法之外, DSP Server还集成了其他的软件模块(如 DSP/BIOS、 DSP Link、Codec Engine等)。

如何构建达芬奇的DSP Server

1. xDC简介

达芬奇的软件开发环境中,有一个 DSP工程师比较陌生的工具xDC(Express DSP Component)。和gmake类似,xDC根据一套build指令build生成可执行文件。xDC同时也会build依赖文件,并且可以一次build多个目标对象的可执行文件(如图5中的hello.x64P是 DSP的可执行文件,hello.x470MV是ARM的可执行文件)。xDC的源文件可以是C程序、C++程序、汇编程序和库文件等。

如图5所示,xDC按照build指令,对 DSP Server的源文件进行build(类似于make)生成 DSP Server .x64P文件。这个过程可以分为三部分:创建 DSP Server的源文件;设置xDC的配置文件;执行“make”生成可执行文件。

如何构建达芬奇的DSP Server

2. DSP Server的源文件
以Codec Engine_1_02中的video_copy为例,如图6我们可以看到video_copy的 DSP Server中包括和图5对应的源文件main.c、video_copy.tcf和link.cmd。图5中的packages是指图3和图4中的 codecs、RMS、Engine SPI和OSAL。接下来,我们可以通过xDC的配置文件看到如何把packages添加到Server中。

要构建 DSP Server首先就需要创建main.c和server的 DSP BIOS配置文件.tcf及link.cmd。我们提到engine_open会把 DSP从复位状态释放, DSP Server程序开始运行初始化等等。这个初始化就是 DSP Server main.c(见图7)中的CERuntime_init()。除此之外在main.c中还可以打开Codec Engine的trace功能,读取或更改main函数的参数等。

如何构建达芬奇的DSP Server
如何构建达芬奇的DSP Server
DSP BIOS的配置文件.tcf中定义 DSP的memory map、设置 DSP的复位/中断向量表并且创建和初始化BIOS程序需要的各种数据对象(如图8的.tcf)。在.tcf中我们只能定义编译器默认的 sections(如.text和.bss等)。但是,我们可以在link.cmd中定义自己的sections(如图8 link.cmd中.tables和.csl_vect等)。

如何构建达芬奇的DSP Server

3. xDC文件

在Linux中我们用make命令根据makefile来生成可执行文件,xDC也有类似的生成脚本文件(我们统称为xDC文件)。如图6所示,其中package.bld、package.xdc和video_copy.cfg三个文件就是提供给xDC build DSP Server的xDC文件。

在package.xdc中声明 DSP Server的名字、它的路径及Server的依赖文件。Package.bld文件的功能类似于Linux中的makefile,它会告诉xDC怎么样build DSP Server的源文件。如图9所示在package.bld中定义target是C64P DSP、要生成针对target的可执行程序,其中配置脚本文件是video_copy.tcf(与图8中的.tcf类似)、链接选项是链接link.cmd(与图8中的link.cmd类似)文件,同时还要生成main.c的目标代码。

如何构建达芬奇的DSP Server

xDC的强大之处还在于它提供给系统集成工程师一个强大的工具,这个工具可以用来把各种各样的代码模块组合成自己的最终产品。其中xDC的配置文件就是 DSP Server中的.cfg(例如图5中的video_copy.cfg)负责系统级的管理。请注意这里的.cfg文件不同于第一章提到的Codec Engine的.cfg文件(例如CE_INSTALL_DIR/examples/apps/video_copy/dualcpu /ceapp.cfg),下文中提到的.cfg都是指 DSP Server的.cfg文件。
xDC会根据以上提到的配置文件生成package.mak(类似于makefile),并最终运行它来生成图5所示的包括可执行文件的package。我们可以打开查看package.mak,但不能修改。因为重新运行xDC之后会生成新的package.mak。
4. 设置xDC的配置文件
既然.cfg文件负责系统级的管理,我们需要先了解什么需要管理?当然是 DSP的资源,无非就是CPU cycles、memory及DMA。针对Davinci上 DSP的软件开发,TI提供了Framework Components来方便 DSP软件工程师使用 DSP的 memory和DMA资源。xDM和xDAIS算法的Instance都向FC提出自己的资源请求,比如请求1KByte的memory或一个DMA通道。FC中的DSKT2和DMAN3就通过标准的、可以配置的方法给算法的instances分配资源(包括instances之间可以共享的资源)。举例来说,有了DSKT2负责不同算法开发的工程师就不必担心自己要用的某一段memory是否已经被别的算法占用等一系列问题,因为每一个算法的 memory都是由DSKT2分配的。
a. DSKT2 Framework
DSKT2负责管理系统中所有xDAIS算法的memory需求,它和应用层的接口非常简单“Create, Execute, Delete”。系统集成工程师需要用所有可以利用的memory初始化DSKT2模块。DSKT2模块包括两种类型的memory,永久性的 memory(只要这个算法存在,它就会占用的memory)和scratch memory(算法之间可以共享的memory)。当一个算法被创建的时候,永久性memory才会被DSKT2分配给这个算法,在算法被删除的时候,这段memory被返回到heap。当一个算法申请scratch memory时,会被分配一个memory 'pool',这个pool被拥有同一个scratch pool ID的其它算法共享。也就是说,共享scratch memory的算法属于同一个优先级,不能中断对方。
b. 配置 DSP Server的.cfg文件
在.cfg文件中可以做以下三个部分的配置。
(1) Codec配置:每一个codec都被包含在各自的线程中; 配置每一个codec线程的属性(线程优先级、堆栈大小和堆栈的memory资源)。具体请参考CE_INSTALL_DIR/xdoc/index.html。
(2) DSKT2配置: 把所有的IALG memory类型结合到可用的 DSP memory;定义缺省的scratch组的memory大小。
(3) DMAN3配置:定义DMAN3可以管理的DMA通道号;定义DMAN3可以提供给算法的TCC号。
以video_copy.cfg为例,对应到图4所示的 DSP Server部分,.cfg文件中对OSAL和codecs模块做了声明和定义。我们可以看到video_copy的server中包括VIDDEC_COPY和VIDENC_COPY两个codec。
如何构建达芬奇的DSP Server

接着对server进行配置,包括各个线程的属性配置。Codec engine将自动匹配算法的scratch memory ID和算法线程的优先级,保证安全操作。

如何构建达芬奇的DSP Server

对DSKT2的配置,参看下面的例子。需要注意的是这里的每一个scratch memory pool的大小通过数组的形式定义,数组的第一个元素对应scratch pool ID0,第二个元素对应scratch pool ID2,依次类推。

如何构建达芬奇的DSP Server

以下是DMAN3的配置例子。因为DMA需要memory存放PARAM和其他的通道配置,所以在DMAN3分配有heap(分为internal heap和external heap)。DMAN3的PARAM是通过它自己的base index和数量分配的,本例分配给DMAN3 48个PARAM。从这个例子中我们还可以看到DMAN3有8个可用的QDMA通道,tcc是通过bit mask来分配的。

如何构建达芬奇的DSP Server

5. xDC的build 过程
xDC的调用是通过执行命令 XDC完成的。在此之前,我们需要做以下几步:
a. 在config.bld中定义平台(ARM或 DSP),config.bld所在路径由xdcbuildcfg定义;
b. 在package.xdc中定义package,package.xdc在当前路径下(如图6的video_copy示例);
c. 在package.bld中定义要build的可执行文件和库文件,package.bld在当前路径下(如图6的video_copy示例);
d. 按照前面的介绍根据自己的应用修改server的.cfg文件。
执行XDC后先产生package.mak,XDC再运行package.mak生成包含可执行文件的package。

本文小结

以上的介绍基于工程师在实际开发过程中遇到的一些问题。我们希望通过这篇文章可以先理清思路,然后工程师可以有针对性的进一步研究和学习。要想了解更多的构建 DSP Server的细节还请大家参考sprued5.pdf及文中提到的用户手册和应用文档

原帖地址http://www.devdiv.net/viewthread.php?tid=3912&highlight=DSP%2Bvincent