DSP

Dsplink源码结构,内存管理

2019-07-13 19:39发布

DSPLINK几乎是DAVINCI平台最重要的一个底层系统,它是ARM+DSP平台上特有的。 DAVINCI之所以能成为现在的DAVINCI,有一大部分就是因为有DSPLINK把GPP(General Purpose Processor,  即DM6446中的ARM)和DSP给连起来了。 TI期望大家使用的是它的CODEC ENGINE,因为如果使用CODEC ENGINE,很多底层的细节对开发者就是透明 的了。而为了更深入地了解DAVINCI系统,为了不做“不明真相”的高层代码开发者,或者只是为了追求GEEK的 精神,我们应该去了解DSPLINK的结构和原理。BY THE WAY,这就是在学校里的好处,不用去关心产品的上 市时间,爱干什么干什么。 不过,这篇文章只是“占座”性质的文章。我还没有深入地去看DSPLINK的源码,在这里只是先把以前理解到的东 西总结一下先。以后认真看了再补上。我想,DSPLINK的结构对于以后对异构多核间的通信是有借鉴意义的。 要使用DSPLINK的话,有下面那么几步:
  1. OF COURSE, 把环境给搭起来,重新编译。
  2. OF COURSE, 把DEMO给跑起来。
  3. 理解DSPLINK的相关知识:内存分配及其他。
  4. 分析DEMO,修改DEMO为已所用。
  5. 修改DSPLINK,为已所用。最高境界也~
以下的内容主要是关于3,4两步的。

系统结构

先上图: 发现没有,位于上层的几个模块都有PROC, CHNL, MSGQ等几个小模块,所以DSPLINK的纵向(就是从上层到 下层)是用这几个线贯穿的。 下面这是dsplink的目录结构,可以看到和上图中的模块是大致对应的。每一个模块都放在一个文件夹下。 .
./pmgr
./gen
./osal
./probe
./api
./ldrv
API
api文件夹里是暴露给外部用户使用的接口,放在这里的接口才能被外界调用,所以说,要修改DSPLINK的源码 为已用,得把增加的接口放在这里。DSPLINK USER GUIDE(在DSPLINK的安装目录里的DOC文件夹下)给出 的接口都在这个api文件夹下定义。DSPLINK的每一个模块都会暴露一些接口给它的上一层,api这一层就把接口 暴露给用户使用。
Processor Manager
pmgr文件夹里就是Processor Manager的代码。Processor Manager,顾名思义,提供对处理器的控制。这是核 心的一个模块,其他模块对它进行支持。比如通过CHNL传送数据时,Processor Manager作为一个上层的“管理 者”,Linux Driver层对其进行底一层的驱动支持。Generic Source Modules(GEN)对其进行一些常规的模块的支 持,比如要加载COFF格式的镜像,就要使用GEN里对COFF的支持。
Link Driver
Link Driver的代码在ldrv文件夹下。如上图所示,主要完成的是通信的工作。 通信有两种: 一是CHNL,这种通信的DEMO是LOOP。这种通信是同步的,有ISSUE和RECLAIM两种操作。流程大致是这样 (摘自USER GUIDE(dsplink 1.40)的Appendix, Issue reclaim model): The steps for data transfer with issue reclaim model may be summarized below: 1.  Open a channel with defined buffer size & direction. 2.  Issue a buffer for IO on the specified channel Empty buffer for receiving data Filled buffer for sending data 3.  Attempt to reclaim the buffer. Reclaim will block until the IO operation completes or a timeout occurs. This wait can be postponed to a later point in time for asynchronous IO. 4.  A client must reclaim all the buffers issued to a channel. 二是MSGQ,也有个DEMO。这种通信是异步的。 反正这两种通信都要driver的支持。 Link Driver还要包括对ZCPYPCPY两种传输模式的支持。ZCPY就是Zero Copy,就是不COPY,只传指针。 PCPY好像是Processor Copy,反正是要COPY数据。CHNL和MSGQ都可以选是使用ZCPY还是PCPY。
Operating System Adaptation Layer (OSAL)
这是DSPLINK和OS的“国界”,DSPLINK和操作系统之间的协作通过OSAL来进行。OSAL模块使得DSPLINK具有 可移植性。
Probe
还有一个文件夹叫probe,是用来在实际使用DSPLINK里来评估其性能的。

内存管理

内存管理是使用DSPLINK时一定要理解的一个东西。这些内存是怎么分配,怎么用的,在哪些地方管理它的属性 。要了解了这些才能看懂DEMO的代码,才能修改代码为已所用 BUFPOOL/SMAPOOL的结构如图所示。有一个BUFPOOL的结构体,在其中可以设定有多少个MPBUF,每一个 MPBUF对应一个Buffer POOL,每一个Buffer POOL有一些BUFFER,这些BUFFER的大小是相同的。 DSPLINK中有一个结构体是SmaPoolAttrs,这个结构体用于指定上图中结构的属性。其中numBufPools指的是 number of buffer pools,即Buffer POOL的个数,上图中可以看到的个数是3。bufSizes是一个数组,每一个元素 存储的是上图中浅 {MOD}部分BUFFER的大小,如{2,3}指的是第一个Buffer POOL中的buffer的大小为2,第二个 Buffer POOL中的buffer大小为3。numBuffers是指number of buffers,即一个Buffer POOL中所含的buffer的个数 ,如numBuffers的值为{6,8},那么第一个Buffer POOL中有6个buffer,第二个buffer POOL中有8个buffer。还有 一个属性是exactMatchReq,如果此值为true的话,则实际分配内存时,请求的内存大小一定要和buffer的大小一 样,即为bufSizes,不然的话不会分配;如果此值为false,那么系统就会去找大于所请求的大小的内存。这里有 个规则的,我忘了…好像DSPLINK的安装文件夹里的POOL或者SMA POOL文档中有写。 了解了结构之后,Demo中的关于内存配置的宏就能看懂并修改了。 这里有TI给的pool的overview. 下面给出几个使用POOL时的注意事项和troubleshooting。

Troubleshooting

1
在Demo Loop里,传输的大小只能是128的倍数,但64, 129就不能传,这是因为数据对齐的关系。具体我也记不 得是怎么样了,可以看看源码里DSPLINK_ALIGN这个宏的说明。
2
Demo Loop的debug版本在内存分配时会有问题,不要使用make出来的debug版本的loop。
3
错误现象 Encodedecode Debug: POOL0: Buffer Size of each Buffer = 691200. Encodedecode Debug: POOL0: Number of Buffers in a buffer Pool = 1 POOL_Open () failed. Status = [0x80008013] 解决方案: 主要是buffer开得不够大的问题 http://wiki.davincidsp.com/index.php/DSPLink_POOL_FAQs http://wiki.davincidsp.com/index.php/Changing_DSPLink_POOL_size 解决这个问题要修改一个配置文件,上面的网页指示的文件可能是新一点的版本里的,在我所使用的dsplink 1.30 中,实际应该修改的是$(DSPLINK)/config/all/CFG_Davinci.TXT
4
错误现象 DEMO LOOP 中DSP端无法接收GPP端发送来的数据 原因 loop.c中将 /** ============================================= *  @name   NUMBUFS * *  @desc   Number of buffers in pool. *  ====================================== */ #define NUMBUFS        4 改成了1。 Debug过程及解决 loop.absClean将传691200的数据后,将NUMBUFS改成1,出现下面的错误。 =============== Sample Application : LOOP ========== Entered LOOP_Create () Leaving LOOP_Create () Entered LOOP_Execute () Before CHNL_Issue() out Before CHNL_Reclaim() out 即在CHNL_Reclaim里停了下来 将其改回4后,可正常传送。
5
错误现象 root@192.168.100.3:/opt/ttroot# ./loopgpp loop.out 691200 1 =============== Sample Application : LOOP ========== Entered LOOP_Create () POOL_Open () failed. Status = [0x80008013] Leaving LOOP_Create () Entered LOOP_Delete () CHNL_FreeBuffer () failed (output). Status = [0x80008000] CHNL_Delete () failed (input). Status = [0x80008000] CHNL_Delete () failed (output). Status = [0x80008000] POOL_Close () failed. Status = [0x8000800b] Leaving LOOP_Delete () ==================================================== 原因与解决 这也是因为dsplink的sma pool不够大,但是只是把pool设为691200*4(*4是因为loop中的num of buffers的值是4 )是不够的,因为还有其他的结构体什么的东西要用内存。当我把sma pool size的值设为691200*8时,运行成功。 以上内容多为回忆或潦草的笔记转化而来,一定得用批判的眼光看… TI达芬奇专题-说明及文章索引