davince codec engine 内存分配记录 与引用

9 篇文章 0 订阅
9 篇文章 0 订阅

要想在codec engine 中用malloc free等函数,要修改如下:

dsp端可用的内存分配(实地址):malloc、free等函数。分配所用的heap在.tcf(.tci)中设置,如下可将动态分配的内存定位到DDRALGHEAP中

prog.module("MEM").MALLOCSEG  = bios.DDRALGHEAP;

下面更详细的描述下dsp端memory的分配脚本(.tci和.tcf)内容:

       1)、首先是定义几个memory段并定义其属性,如下面的DDRALGHEAP、DDR2

var mem_ext = [

{

    comment:    "DDRALGHEAP: off-chip memory for dynamic algmem allocation",

    name:       "DDRALGHEAP",

    base:       0x88000000,   // 128MB

    len:        0x03A00000,   //  MB

    space:      "code/data"

},

{

    comment:    "DDR2: off-chip memory for application code and data",

    name:       "DDR2",

    base:       0x8BA00000,   //  MB

    len:        0x04400000,   //   MB

    space:      "code/data"

},

{

    comment:    "DSPLINK: off-chip memory reserved for DSPLINK code and data",

    name:       "DSPLINKMEM",

    base:       0x8FE00000,   // 254MB

    len:        0x00100000,   //   1MB

    space:      "code/data"

},

{

    comment:    "RESET_VECTOR: off-chip memory for the reset vector table",

    name:       "RESET_VECTOR",

    base:       0x8FF00000,   // 255MB

    len:        0x00000080,   // 128 B

    space:      "code/data"

}

];

    2)、接着设置其中的哪些段可以有heap,其中heap大小待定。在后面的设置中DDR2还用于存放code、data,不能将其全设为heap。

bios.DDR2.createHeap = true;

bios.DDR2.heapSize   = 0xF00000; //

 

/* set for use in all.tcf */

var platformSeg = bios.DDR2;

 

bios.DDRALGHEAP.createHeap = true;

bios.DDRALGHEAP.heapSize   = bios.DDRALGHEAP.len;

       3)、最后就是对涉及memory的功能指定具体的段,其中MALLOCSEG涉及malloc()、free()等动态分配内存的函数

bios.setMemCodeSections (prog, platformSeg);

bios.setMemDataNoHeapSections (prog, platformSeg);

bios.setMemDataHeapSections (prog, platformSeg);

 

bios.MEM.BIOSOBJSEG = bios.DDRALGHEAP;

bios.MEM.MALLOCSEG  = platformSeg;

再 转载:----------------------------------------------------------------------------------------------------------

Davinci 开发中的灵异事件

在进行Codec Engine服务器端的开发时,有时会出现一些莫名其妙的现象,在模拟器上明明跑得好好地一段程序,移植到开发板上愣是出现一堆错误。这些错误,和GPP端不同:它们没有错误信息、不会自动退出、甚至连Trace信息也不打印。我把这些都称为灵异事件。当然,这些事件的产生还是归咎于代码本身的缺陷或不周全。以下问题是我在开发Davinci应用程序中遇见的,摘录下来,供大家参考。

链接时提示符号未定义

这个问题发生在Sever端集成时,无论Lib、还是Codec在各自的机器上都编译通过了,唯独集成在一起时,确出现了以下集成错误信息:

undefined                       first referenced

 symbol                              in file

---------                       ----------------

_LITTLE_B2D                     /prj/common/lib/libaes.a

_LITTLE_D2B                      /prj/common/lib/libaes.a

打开libaes项目,发现LITTLE_B2DLITTLE_D2B定义在头文件中:

#undef BIG_ENDIAN

#undef LITTLE_ENDIAN

 

#if defined(USER_BIG_ENDIAN)

    #define BIG_ENDIAN

#elif defined(USER_LITTLE_ENDIAN)

    #define LITTLE_ENDIAN

#else

    #if 0

#define BIG_ENDIAN        //   Big-Endian machine with pointer casting

    #elif defined(_MSC_VER)

        #defineLITTLE_ENDIAN    //   Little-Endian machine with pointer casting

    #else

  //       #error

    #endif

#endif

 

#if defined(BIG_ENDIAN)           Big-Endian machine

    #define BIG_B2D(B,D)       D = *(XDAS_Int32 *)(B)

    #define BIG_D2B(D, B)        *(XDAS_Int32 *)(B) = (XDAS_Int32)(D)

    #define LITTLE_B2D(B, D)    D = ENDIAN_REVERSE_DWORD(*(XDAS_Int32*)(B))

    #define LITTLE_D2B(D, B)    *(XDAS_Int32 *)(B) =ENDIAN_REVERSE_DWORD(D)

#elif defined(LITTLE_ENDIAN)       Little-Endian machine

    #defineBIG_B2D(B,D)       D =ENDIAN_REVERSE_DWORD(*(XDAS_Int32*)(B))

    #defineBIG_D2B(D,B)       *(XDAS_Int32 *)(B)=ENDIAN_REVERSE_DWORD(D)

    #defineLITTLE_B2D(B,D)   D= *(XDAS_Int32*)(B)

    #defineLITTLE_D2B(D,B)   *(XDAS_Int32*)(B)= (XDAS_Int32)(D)

#else

    //ERROR()

#endif

原来这是因为我们在编译时,忘了添加 USER_BIG_ENDIAN USER_LITTLE_ENDIAN 等宏。在 CCS Build Option 选项中,加上即可:


 图省略


没有运行DSP端程序

错误描述

这个问题发生在GPPDSP程序联合测试时,当我试图在GPP端调用DSP端算法时,出现如下Trace信息:

ti.sdo.ce.image1.IMGENC1- IMGENC1_process> Enter (handle=0x3d9c8, inBufs=…)

ti.sdo.ce.image1.IMGENC1- IMGENC1_process> Exit (handle=0x3d9c8, retVal=0xFFFFFFFD)

错误分析

显然,在Trace信息中没有看到任何和DSP有关的消息,DSP端没有运行。IMGENC1_process方法直接返回错误:0xFFFFFFFD(实际上就是-3)。打开头文件xdm.h,发现有一个含糊的定义:

#define XDM_EUNSUPPORTED       -3          /**< Request isunsupported. */

参考一个正确处理过程的Trace信息:

ti.sdo.ce.image1.IMGENC1- IMGENC1_process> Enter (handle=0x3d9c8, inBufs=……)

CV -VISA_allocMsg> Allocating message for messageId=0x000600b2

OM- Memory_getBufferPhysicalAddress> Enter(virtAddr=0x41209000, size=16641)

OM- Memory__getPhysicalAddress> Enter(virtAddr=0x41209000, size=16641)

OM- Memory__getPhysicalAddress> found in cb(Sc=0x41209000, Ec=……)

OM- Memory__getPhysicalAddress> returning physAddr=0x837ac000

OM- Memory_getBufferPhysicalAddress> return (0x837ac000)

OM- Memory_getBufferPhysicalAddress> Enter(virtAddr=0x41229000, size=262144)

@13,515,611us: [+0T:0x42ac9b60 S:0x42a88eac] CV - VISA_call(visa=0x3d9c8, msg=……

说明,这个错误时在stub中返回的。

修改IIMGENC1

到这一步,不禁想,要是TI提供的imgenc库能打印Trace信息就好了。幸好Codec Engine里,为我们提供了IMGENC的源代码,因此我需要修改源文件,加入Trace模块,重新编译,替换掉TI原有的库就可以。 IMGENC源文件存放在目录:($codecengine安装目录)\packages\ti\sdo\ce\image1文件夹中,这里我需要修改imgenc1_stubs.c。在Visual Studio中打开文件,加入Trace的代码:

GT_Maskti_sdo_ce_image1_IMGENC1_curTrace;

BOOLti_sdo_ce_image1_IMGENC1_curTrace_init=FALSE;

以及初始化函数:

if(!ti_sdo_ce_image1_IMGENC1_curTrace_init)

{

    GT_create(&ti_sdo_ce_image1_IMGENC1_curTrace,"ti.sdo.ce.imgenc1.IMGENC1_STUBS");

    GT_set("ti.sdo.ce.imgenc1.IMGENC1_STUBS=01234567");

    ti_sdo_ce_image1_IMGENC1_curTrace_init=TRUE;

}

接下来就可以在需要加入Trace的地方添加命令了。

GT_Trace使用方法可以参考我的文章:使用GenericTrace Support打印调试信息

编译

由于源文件目录下没有makefilepackage.bld文件,我们需要手动添加:

makefile文件,主要是载入xdcpaths.makxdcrules.mak等文件

PROJECT_ROOTDIR :=$(CURDIR)/../../../..

 

include$(PROJECT_ROOTDIR)/xdcpaths.mak

 

XDC_PATH :=$(PROJECT_ROOTDIR);$(XDC_PATH)

 

include$(PROJECT_ROOTDIR)/buildutils/xdcrules.mak

package.bld文件,主要是指定哪些文件需要被编译:

Pkg.attrs.exportAll =true;

 

var SRCS =["imgenc1.c", "imgenc1_skel.c","imgenc1_stubs.c"];

 

Pkg.otherFiles = [

    "imgenc1.h"

];

 

for (var i = 0; i< Build.targets.length; i++) {

    var targ = Build.targets[i];

 

    Pkg.addLibrary("lib/imgenc1",targ, {

    }).addObjects(SRCS);

 

   Pkg.addLibrary("lib/imgenc1_debug", targ, {

        profile : "debug"

    }).addObjects(SRCS);

}

发现错误

最后,我发现,原来错误来自于:

if ((sizeof(VISA_MsgHeader)+sizeof(*inBufs)+sizeof(*outBufs)+

        inArgs->size+outArgs->size)>sizeof(_IMGENC1_Msg)){

    return(IIMGENC1_EUNSUPPORTED);

}

原来,我忘记在GPP端为outArgs指定size的值了:

outArgs.size=sizeof(outArgs);

加上后,错误解决。

莫名奇妙死机

问题描述

这下程序应该能完美运行了吧,我兴冲冲地传入测试参数,泡杯茶(第一次运行,不知道需要多久),开始等待……

五分钟过去了……怎么还没有结果?应该是计算量大的问题,因为我的程序里用了大量的递归,先去打会儿网球吧

不是吧,都过去了两小时,怎么还是停留在这里?

VISA_call(visa=0x3d9c8,msg=0x4115ec80): ……

Comm_put>Enter(queue=0x6, msg=0x4115ec80)

Comm_put> return(0)

Comm_get>Enter(queue=0x10005, msg=0x42a88f14, timeout=-1)

Comm_get> return(0)

Comm_put>Enter(queue=0x0, msg=0x41159c80)

强制退出后,DSP居然死机了……

问题分析

我们知道,DM6446是双核的,GPPDSP。一个算法接口,在GPPDSP端分别对应StubSkeltonGPP端在Stub中通过调用VISA_call方法来执行DSP端的代码。DSP端完成操作后,在返回。整个过程,是基于一种消息传递机制的。

从上面的Trace信息中可以看出:代码已经执行到VISA_call,但是,却没有等到DSP端返回结果,因此处于一种死机状态。只是这种状态,也太令人困混了:由于DSP端没有返回任何信息,因此,我们根本看不到DSP端的Trace信息,无法判断到底是哪里出了问题。

我编写代码有个习惯,现在VC上将代码调试通过,然后移植到DSP上。既然代码在VC上能调试成功,说明不是程序的问题。最大的可能是:内存分配错误导致DSP端代码崩溃!基于这点,我检查了代码,发现最有可能的问题是:递归太多。

接下来,我减少了递归的数量,重新编译后,程序通过。

修改栈大小

CC++编程中,堆(Heap)和栈(Stack)是分配内存空间,存放数据的两个重要地点。一般的,使用mallocnew关键字分配的内存空间保存在堆中,而局部变量、或者函数的参数,都是保存在栈中。因此,当一个程序中递归的数量很多时,栈空间往往不够,最终造成内存溢出。

打开项目中的xs文件,修改getStackSize方法,增大栈空间(我这里将原来的1024增加为4096):

functiongetStackSize(prog)

{

    if(verbose) {

        print("getting stack size for" + this.$name

            + " built for the target" + prog.build.target.$name

            + ", running on platform" +  prog.platformName);

    }

 

    return (4096);

}

或者也可以修改server端的cfg文件:

Server.algs= [

    {   name:"enctriangle",

        mod:ENCTRIANGLE,

        groupId:0,

        threadAttrs:{

            stackSize:4096,

            stackMemId:0,

            priority:Server.MINPRI+1

        }

    },

];

无法分配内存

又出问题了

解决完上述问题,似乎可以松口气,运行程序,编码,一切正常!

怀着期盼的心情,我点击了解码按钮,结果……怎么我的图片少了一大块?经过检查,确定不是解码的问题,看来编码这块儿还是不能让人放心啊!

继续分析问题

这次比较简单,在编码的关键点加入Trace后,清楚地发现,当系统运行到某个阶段时,

pPerson person=(pTFlat)malloc(sizeof(Person));

返回NULL指针!

想必是堆空间不够了!

堆不够?那就弄大点吧!

打开server工程的.cfg文件,睁大眼睛,仔细检查空间分配问题:

var mem_ext= [

{

    comment:"DDRALGHEAP: off-chip memory for dynamic algmemallocation",

    name:"DDRALGHEAP",

    base:0x82E00000,  //46MB

    len:0x00a00000,   //10MB

    space:"code/data"

},

{

    comment:"DDR2: off-chip memory for application code and data",

    name:"DDR2",

    base:0x83800000,  //56MB

    len:0x00600000,   //6MB

    space:"code/data"

},

{

    comment:"DSPLINK: off-chip memory reserved for DSPLINK code anddata",

    name:"DSPLINKMEM",

    base:0x83E00000,  //62MB

    len:0x00100000,   //1MB

    space:"code/data"

},

{

    comment:"RESET_VECTOR: off-chip memory for the reset vectortable",

    name:"RESET_VECTOR",

    base:0x83F00000,  //63MB

    len:0x00000080,

    space:"code/data"

},

];

怎么可能,我们明明分配了10MB的空间给DDRALGHEAP。继续往下看吧:

bios.DDR2.createHeap=true;

bios.DDR2.heapSize= 0x20000;// 128K

 

bios.DDRALGHEAP.createHeap=true;

bios.DDRALGHEAP.heapSize=bios.DDRALGHEAP.len;

试着修改bios.DDR2.heapSize的值,改成0×40000。运行程序,错误解决了。

为什么是DDR2

根据上面的内存分配表,DDR2区域应该是存放算法代码、数据的,不应该具备的功能,为什么这里修改了bios.DDR2.heapSize却可以回避异常呢?按理来说,应该是DDRALGHEAP才对。再说,当前程序中将bios.DDR2.heapSize设置成0×40000可以,如果将来运算量多,区区256K的堆空间,不一定能用。

继续查看代码,发现cfg中设置如下:

bios.setMemCodeSections(prog,bios.DDR2);

bios.setMemDataNoHeapSections(prog,bios.DDR2);

bios.setMemDataHeapSections(prog,bios.DDR2);

修改如下:

bios.setMemCodeSections(prog,bios.DDR2);

bios.setMemDataNoHeapSections(prog,bios.DDR2);

bios.setMemDataHeapSections(prog,bios.DDRALGHEAP);

OK了!

无法更新outbuf

问题描述

这个问题出现在当对第二幅图像编码完成后,从DSP端传出的数值仍然是第一幅图像的编码结果。

分析

DM6446是双核处理器,GPP端和DSP端通过CMEM共享内存来传递数据。GPP端是相对地址,DSP端是绝对地址。二者实际上是对应不同的内存块,通过Codec Engine API中的Memory_cacheInvMemory_cacheWb等函数来转换数据(相当于memcpy)。

因此,如果出现上述问题,肯定是由于在skel层没有执行相应的操作。打开imgenc1_skel.c。找到以下代码:

if ((pStatus->data.buf!=NULL) &&

    XDM_ISACCESSMODE_WRITE(pStatus->data.accessMask)){

 

    Memory_cacheWb(pStatus->data.buf,pStatus->data.bufSize);

 

    /*

     * Since we've cacheWb this buffer, wearguably should

     * reflect this cache state and clear theWRITE bit in

     * the .accessMask field.  However, we know the stub

     * doesn't propogate this field to thecalling app, so

     * this extra buffer management detailisn't necessary:

     *

     *XDM_CLEARACCESSMODE_WRITE(pStatus->data.accessMask);

     */

}

不难判断,问题出现在XDM_ISACCESSMODE_WRITE(data.accessMask)这里。

解决问题

原来,在DSP端的Skel中,Memory API通过查看data.accessMask来判断该段内存是否被写过,如果写过,才将它转化成GPP端的内存,否则,跳过。

打开Codec实现文件,在更新完outBufs数据后,修改outBufsaccessMask

/* report _how_ weaccessed the 2 data buffers */

XDM_CLEARACCESSMODE_WRITE(inBufs->descs[0].accessMask);

XDM_SETACCESSMODE_READ(inBufs->descs[0].accessMask);

 

XDM_CLEARACCESSMODE_READ(outBufs->descs[0].accessMask);

XDM_SETACCESSMODE_WRITE(outBufs->descs[0].accessMask);

http://newinfo.sysu.edu.cn/Snowwaft/?p=272


再附:--------------------------------------------------------------------------------------------------------------------------------

转自:http://processors.wiki.ti.com/index.php/Changing_DSPLink_Memory_Map


Introduction

DSPLink can be used by itself, or as part of Codec Engine (CE). This page gives details of changing the DSPLink memory map when used 'raw'. The instructions are applicable when using DSPLink version 1.4x onwards, where the dynamic configuration feature was added.

IMPORTANT: The details of changing DSPLink memory map when used within Codec Engine are available at this article.
Overview

The default DSPLink memory map for any platform usually assumes the following:
1 MB shared memory between ARM & DSP
1 MB DSP memory for DSP code and data

If the system integrator wishes to change the memory map, the following steps need to be taken:
Update $(DSPLINK)/config/all/CFG_[PLATFORM].c to modify the memory map as per the ARM-DSP split requirements.
Ensure that RESETVECTOR field in DSP config object is correctly modified.
Modify $(DSPLINK)/dsp/inc/DspBios/$(DSPOSVERSION)/$(PLATFORM)/dsplink-[PLATFORM]-base.tci file to modify the memory map as per the configuration update.
Ensure that the MAR configuration in the TCF file for cache matches the new memory map.
On Linux, ensure that the mem=254M value passed to bootargs is updated to reserve the new amount of memory from Linux kernel for shared memory + DSP memory.
Example

Assume that you have 256 MB on your board. You want to split this as:
ARM: 64MB (0x4000000)
DSP: 192MB (0xC000000)

For this memory map, perform the following steps to modify default DSPLink configuration:
Specify mem=64M on your Linux bootargs. This means you are saying that Linux (ARM) will use only the first 64MB. The last 196MB will be used by DSP & shared memory.
The last address is 0x8FFFFFFF. So if the last 192MB is for DSP, you need to start DSP & shared memory space at:
84000000 = 0x90000000 - C000000

So your configuration will be:
{
0, /* ENTRY : Entry number */
"DSPLINKMEM", /* NAME : Name of the memory region */
0x84000000, /* ADDRPHYS : Physical address */
0x84000000, /* ADDRDSPVIRT : DSP virtual address */
(Uint32) -1, /* ADDRGPPVIRT : GPP virtual address (if known) */
0x5000, /* SIZE : Size of the memory region */
TRUE /* SHARED : Shared access memory? */
},
{
1, /* ENTRY : Entry number */
"DSPLINKMEM1", /* NAME : Name of the memory region */
0x84005000, /* ADDRPHYS : Physical address */
0x84005000, /* ADDRDSPVIRT : DSP virtual address */
(Uint32) -1, /* ADDRGPPVIRT : GPP virtual address (if known) */
0xFB000, /* SIZE : Size of the memory region */
TRUE /* SHARED : Shared access memory? */
},
{
2, /* ENTRY : Entry number */
"RESETCTRL", /* NAME : Name of the memory region */
0x84100000, /* ADDRPHYS : Physical address */
0x84100000, /* ADDRDSPVIRT : DSP virtual address */
(Uint32) -1, /* ADDRGPPVIRT : GPP virtual address (if known) */
0x00000080, /* SIZE : Size of the memory region */
FALSE /* SHARED : Shared access memory? */
},
{
3, /* ENTRY : Entry number */
"DDR", /* NAME : Name of the memory region */
0x84100080, /* ADDRPHYS : Physical address */
0x84100080, /* ADDRDSPVIRT : DSP virtual address */
(Uint32) -1, /* ADDRGPPVIRT : GPP virtual address (if known) */
0xBEFFF80, /* SIZE : Size of the memory region */
FALSE /* SHARED : Shared access memory? */
},

By doing this, you have reserved almost 191MB for DSP-side and 1MB for (DSPLINKMEM & DSPLINKMEM1) shared memory.
Ensure that the RESETVECTOR field in LINKCFG_dspObjects structure is also changed to point to the right place.
STATIC CONST LINKCFG_Dsp LINKCFG_dspObjects [] =
{
{
...
0x84100000, /* RESETVECTOR : Reset Vector for the DSP */
...
}
}
Correspondingly, DSP-side TCF file would have:
/* ============================================================================
* MEM : DSPLINKMEM
* ============================================================================
*/
var DSPLINKMEM = prog.module("MEM").create("DSPLINKMEM");
DSPLINKMEM.base = 0x84000000;
DSPLINKMEM.len = 0x100000;
DSPLINKMEM.createHeap = false;
DSPLINKMEM.comment = "DSPLINKMEM";

/* ============================================================================
* MEM : RESET_VECTOR
* ============================================================================
*/
var RESET_VECTOR = prog.module("MEM").create("RESET_VECTOR");
RESET_VECTOR.base = 0x84100000;
RESET_VECTOR.len = 0x00000080;
RESET_VECTOR.space = "code/data";
RESET_VECTOR.createHeap = false;
RESET_VECTOR.comment = "RESET_VECTOR";

/* ============================================================================
* MEM : DDR
* ============================================================================
*/
var DDR = prog.module("MEM").create("DDR");
DDR.base = 0x84100080;
DDR.len = 0x0BEFFF80;
DDR.space = "code/data";
DDR.createHeap = true;
DDR.heapSize = 0x10000;
DDR.comment = "DDR";
You can even split up DDR into two or more memory segments on DSP-side if it makes more sense.
You can now increase your heap size to whatever you need (keep in mind DSP/BIOS restrictions on heap size, if any).
Ensure that you also change the MAR settings for DSP cache to match the new DSP memory map.

For default memory map of 0x8FE00000 to 0x8FFFFFFF, MAR 143 needs to be enabled:
prog.module("GBL").C64PLUSMAR128to159 = 0x00008000;

For the new memory map of 0x84000000 to 0x8FFFFFFF, MAR 132 to MAR 143 need to be enabled:
prog.module("GBL").C64PLUSMAR128to159 = 0x0000FFF0;

For this, refer to SPRU871 for MAR address ranges and DSP/BIOS documentation for syntax for the settings.

For technical support please post your questions at http://e2e.ti.com. Please post only comments about the article Changing DSPLink Memory Map here.





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听海拉拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值