Davinci 开发中的灵异事件.docx

上传人:b****8 文档编号:10625639 上传时间:2023-02-21 格式:DOCX 页数:12 大小:68.27KB
下载 相关 举报
Davinci 开发中的灵异事件.docx_第1页
第1页 / 共12页
Davinci 开发中的灵异事件.docx_第2页
第2页 / 共12页
Davinci 开发中的灵异事件.docx_第3页
第3页 / 共12页
Davinci 开发中的灵异事件.docx_第4页
第4页 / 共12页
Davinci 开发中的灵异事件.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Davinci 开发中的灵异事件.docx

《Davinci 开发中的灵异事件.docx》由会员分享,可在线阅读,更多相关《Davinci 开发中的灵异事件.docx(12页珍藏版)》请在冰豆网上搜索。

Davinci 开发中的灵异事件.docx

Davinci开发中的灵异事件

Davinci开发中的“灵异事件”

在进行CodecEngine服务器端的开发时,有时会出现一些莫名其妙的现象,在模拟器上明明跑得好好地一段程序,移植到开发板上愣是出现一堆错误。

这些错误,和GPP端不同:

它们没有错误信息、不会自动退出、甚至连Trace信息也不打印。

我把这些都称为“灵异事件”。

当然,这些事件的产生还是归咎于代码本身的缺陷或不周全。

以下问题是我在开发Davinci应用程序中遇见的,摘录下来,供大家参考。

链接时提示符号未定义

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

undefinedfirstreferenced

symbolinfile

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

_LITTLE_B2D/prj/common/lib/libaes.a

_LITTLE_D2B/prj/common/lib/libaes.a

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

#undefBIG_ENDIAN

#undefLITTLE_ENDIAN

#ifdefined(USER_BIG_ENDIAN)

#defineBIG_ENDIAN

#elifdefined(USER_LITTLE_ENDIAN)

#defineLITTLE_ENDIAN

#else

#if0

#defineBIG_ENDIAN//Big-Endianmachinewithpointercasting

#elifdefined(_MSC_VER)

#defineLITTLE_ENDIAN//Little-Endianmachinewithpointercasting

#else

//#error

#endif

#endif

#ifdefined(BIG_ENDIAN)////Big-Endianmachine

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

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

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

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

#elifdefined(LITTLE_ENDIAN)////Little-Endianmachine

#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的BuildOption选项中,加上即可:

没有运行DSP端程序

错误描述

这个问题发生在GPP和DSP程序联合测试时,当我试图在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,发现有一个含糊的定义:

#defineXDM_EUNSUPPORTED-3/**

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

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

CV-VISA_allocMsg>AllocatingmessageformessageId=0x000600b2

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

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

OM-Memory__getPhysicalAddress>foundincb(Sc=0x41209000,Ec=……)

OM-Memory__getPhysicalAddress>returningphysAddr=0x837ac000

OM-Memory_getBufferPhysicalAddress>return(0x837ac000)

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

@13,515,611us:

[+0T:

0x42ac9b60S:

0x42a88eac]CV-VISA_call(visa=0x3d9c8,msg=……

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

修改IIMGENC1

到这一步,不禁想,要是TI提供的imgenc库能打印Trace信息就好了。

幸好CodecEngine里,为我们提供了IMGENC的源代码,因此我需要修改源文件,加入Trace模块,重新编译,替换掉TI原有的库就可以。

IMGENC源文件存放在目录:

($codecengine安装目录)\packages\ti\sdo\ce\image1文件夹中,这里我需要修改imgenc1_stubs.c。

在VisualStudio中打开文件,加入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使用方法可以参考我的文章:

使用GenericTraceSupport打印调试信息

编译

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

makefile文件,主要是载入xdcpaths.mak、xdcrules.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;

varSRCS=["imgenc1.c","imgenc1_skel.c","imgenc1_stubs.c"];

Pkg.otherFiles=[

"imgenc1.h"

];

for(vari=0;i

vartarg=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是双核的,GPP和DSP。

一个算法接口,在GPP和DSP端分别对应Stub和Skelton。

GPP端在Stub中通过调用VISA_call方法来执行DSP端的代码。

DSP端完成操作后,在返回。

整个过程,是基于一种“消息”传递机制的。

从上面的Trace信息中可以看出:

代码已经执行到VISA_call,但是,却没有等到DSP端返回结果,因此处于一种“死机”状态。

只是这种状态,也太令人困混了:

由于DSP端没有返回任何信息,因此,我们根本看不到DSP端的Trace信息,无法判断到底是哪里出了问题。

我编写代码有个习惯,现在VC上将代码调试通过,然后移植到DSP上。

既然代码在VC上能调试成功,说明不是程序的问题。

最大的可能是:

内存分配错误导致DSP端代码崩溃!

基于这点,我检查了代码,发现最有可能的问题是:

递归太多。

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

修改栈大小

在C、C++编程中,堆(Heap)和栈(Stack)是分配内存空间,存放数据的两个重要地点。

一般的,使用malloc或new关键字分配的内存空间保存在堆中,而局部变量、或者函数的参数,都是保存在栈中。

因此,当一个程序中递归的数量很多时,栈空间往往不够,最终造成内存溢出。

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

functiongetStackSize(prog)

{

if(verbose){

print("gettingstacksizefor"+this.$name

+"builtforthetarget"+prog.build.target.$name

+",runningonplatform"+prog.platformName);

}

return(4096);

}

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

Server.algs=[

{name:

"enctriangle",

mod:

ENCTRIANGLE,

groupId:

0,

threadAttrs:

{

stackSize:

4096,

stackMemId:

0,

priority:

Server.MINPRI+1

}

},

];

无法分配内存

又出问题了

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

怀着期盼的心情,我点击了解码按钮,结果……怎么我的图片少了一大块?

经过检查,确定不是解码的问题,看来编码这块儿还是不能让人放心啊!

继续分析问题

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

pPersonperson=(pTFlat)malloc(sizeof(Person));

返回NULL指针!

想必是堆空间不够了!

堆不够?

那就弄大点吧!

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

varmem_ext=[

{

comment:

"DDRALGHEAP:

off-chipmemoryfordynamicalgmemallocation",

name:

"DDRALGHEAP",

base:

0x82E00000,//46MB

len:

0x00a00000,//10MB

space:

"code/data"

},

{

comment:

"DDR2:

off-chipmemoryforapplicationcodeanddata",

name:

"DDR2",

base:

0x83800000,//56MB

len:

0x00600000,//6MB

space:

"code/data"

},

{

comment:

"DSPLINK:

off-chipmemoryreservedforDSPLINKcodeanddata",

name:

"DSPLINKMEM",

base:

0x83E00000,//62MB

len:

0x00100000,//1MB

space:

"code/data"

},

{

comment:

"RESET_VECTOR:

off-chipmemoryfortheresetvectortable",

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端是绝对地址。

二者实际上是对应不同的内存块,通过CodecEngineAPI中的Memory_cacheInv、Memory_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);

/*

*Sincewe'vecacheWbthisbuffer,wearguablyshould

*reflectthiscachestateandcleartheWRITEbitin

*the.accessMaskfield.However,weknowthestub

*doesn'tpropogatethisfieldtothecallingapp,so

*thisextrabuffermanagementdetailisn'tnecessary:

*

*XDM_CLEARACCESSMODE_WRITE(pStatus->data.accessMask);

*/

}

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

解决问题

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

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

/*report_how_weaccessedthe2databuffers*/

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);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 职高对口

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1