DM8148从DSP侧发送Frames流到A8侧程序配置
最近在调试DM8148,根据需求需要将摄像头获取的数据送入DSP进行图像处理后再送入A8进行其他处理(网络发送等),在调试的过程中一直遇到数据从DSP侧发送到A8时,程序只能成功执行几次,然后A8侧的FramesInLink就获取不到数据,仔细阅读官方的例程后,总算是调通了,现在把过程记录下来。
第一次写,有不当或者错误的地方欢迎指出。
将Frames或者Bits数据流从BIOS侧发送到Linux侧时,除了正常的配置之外,还需要额外编写Linux侧中Frames/BitsIn的回调函数,并在回调函数中调用release释放被占用的ListMP资源,否则程序正常运行几次后便会因为队列/链表资源耗尽导致处理器之间的通信失败,现象是Linux能收到NEW_DATA_CMD命令,但是FramesTskMain/BitsTskMain程序中能够获得的有效帧是0(打开SYSTEM_DEBUG_IPC_RT宏后会在串口打印如下信息)
这里以DSPFramesOut->HostFramesIn为例说明(注意如果是Vpss中只有一路Frames流或者Video中只有一路Bits流发送到Host,则只需要配置gVcamModuleContext.ipcFramesOutVpssToHostId和gVencModuleContext.ipcBitsOutRTOSId这两个参数就可以在配置Prm参数的时候直接使用MCFW库中提供的回调函(这两个可以参考multich_capturedisplay.c和multich_encode_decode.c中相关的参数配置),而不用手动编写回调函数)
由于MCFW库中并没有提供从DSP发送Frames/Bits时Linux侧的配置,因此如果需要完成从DSP发送Frames/Bits到A8侧,需要手动添加回调函数,并在回调函数中读取传过来的Frames/Bits数据。这里以Frames流从DSP发送到A8实例。
首先定义一个全局变量用于记录A8侧用来接收DSP发送来的数据的LinkID。
UInt32 gFramesDsp2HostId;
然后是两个Link的创建参数配置
ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkId = ipcFramesInDspId
ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkQueId = 0
ipcFramesOutDspPrm.baseCreateParams.numOutQue = 1
ipcFramesOutDspPrm.baseCreateParams.outQueParams[0].nextLink = ipcFramesInHostId0
ipcFramesOutDspPrm.baseCreateParams.noNotifyMode = TRUE
ipcFramesOutDspPrm.baseCreateParams.notifyPrevLink = TRUE
ipcFramesOutDspPrm.baseCreateParams.notifyNextLink = FALSE
ipcFramesOutDspPrm.baseCreateParams.inputFrameRate = 30
ipcFramesOutDspPrm.baseCreateParams.outputFrameRate = 30
ipcFramesInHostPrm0.baseCreateParams.inputFrameRate = 30
ipcFramesInHostPrm0.baseCreateParams.inQueParams.prevLinkId = ipcFramesOutDspId
ipcFramesInHostPrm0.baseCreateParams.inQueParams.prevLinkQueId = 0
ipcFramesInHostPrm0.baseCreateParams.outQueParams[0].nextLink = SYSTEM_LINK_ID_INVALID
ipcFramesInHostPrm0.baseCreateParams.notifyNextLink = FALSE
ipcFramesInHostPrm0.baseCreateParams.notifyPrevLink = FALSE
ipcFramesInHostPrm0.baseCreateParams.noNotifyMode = TRUE
ipcFramesInHostPrm0.exportOnlyPhyAddr = TRUE
ipcFramesInHostPrm0.cbCtx = NULL
ipcFramesInHostPrm0.cbFxn = i_ipcFramesHostCb
ipcFramesInHostPrm0.cbFxn表示A8侧收到数据后调用的回调函数指针,ipcFramesInHostPrm0.cbCtx为传入ipcFramesInHostPrm0.cbFxn的形参,这里使用gFrames2HostID来记录linkID,没有参数需要传向ipcFramesInHostPrm0.cbFxn,所以这里设置为NULL。
然后是回调函数Void i_ipcFramesHostCb(Ptr cbCtx)。
/*DSP 帧到host的回调函数,其中cbCtx为NULL*/
Void i_ipcFramesHostCb(Ptr cbCtx)
{
UInt32 status = 0;
VIDEO_FRAMEBUF_LIST_S bufList;
OSA_printf("----------ipc Frames get from DSP Host link ID is %X-------------
", gFramesDsp2HostId);
VDsp_getFullVideoFrames(gFramesDsp2HostId, &bufList, 0);
OSA_printf("----------host get frames in ListMP-------------
");
if (bufList.numFrames){
status = VDsp_putEmptyVideoFrames(gFramesDsp2HostId, &bufList);
OSA_assert(0 == status);
OSA_printf("----------Host release frames to MCFW-------------
");
}
}
关于这个函数的实现可以参考ti_vcap.c中static Void * App_ipcFramesSendRecvFxn(Void * prm)函数,这里实现与官方的稍有差异,官方库中App_ipcFramesSendRecvFxn为一个在初始化时候创建的线程,该线程创建完成后,便进入等待状态,回调函数仅向App_ipcFramesSendRecvFxn发送一个信号量,用来启动线程,线程启动后,进行处理相关操作。
接下来是VDsp_putEmptyVideoFrames和VDsp_getFullVideoFrames的实现。这两个函数的实现同样是参考ti_vcap.c中Vcam_getFullVideoFrames和Vcam_getFullVideoFrames的实现。
/*释放帧*/
Int32 VDsp_putEmptyVideoFrames(UInt32 linkID, VIDEO_FRAMEBUF_LIST_S *pFrameBufList)
{
VIDEO_FRAMEBUF_S *pSrcBuf;
VIDFrame_Buf *pDstBuf;
VIDFrame_BufList vidBufList;
UInt32 i;
Int status = 0;
vidBufList.numFrames = pFrameBufList->numFrames;
for (i = 0; i < vidBufList.numFrames; i++)
{
pSrcBuf = &pFrameBufList->frames[i];
pDstBuf = &vidBufList.frames[i];
Vcam_copyVidFrameInfoMcFw2Link(pDstBuf,pSrcBuf);
}
if (vidBufList.numFrames)
{
status =
IpcFramesInLink_putEmptyVideoFrames(linkID,
&vidBufList);
}
return 0;
}
/*Host 获取从DSP传过来的帧*/
Int32 VDsp_getFullVideoFrames(UInt32 linkID,
VIDEO_FRAMEBUF_LIST_S *pFrameBufList, UInt32 timeout)
{
VIDFrame_BufList vidBufList;
VIDFrame_Buf *pInBuf;
VIDEO_FRAMEBUF_S *pOutBuf;
UInt32 i;
pFrameBufList->numFrames = 0;
vidBufList.numFrames = 0;
IpcFramesInLink_getFullVideoFrames(linkID, &vidBufList);
pFrameBufList->numFrames = vidBufList.numFrames;
for (i = 0; i < vidBufList.numFrames; i++)
{
pOutBuf = &pFrameBufList->frames[i];
pInBuf = &vidBufList.frames[i];
Vcam_copyVidFrameInfoLink2McFw(pOutBuf,pInBuf);
}
return 0;
}
配置完成后,上电通过串口可以看到如下连续的打印信息,表示配置成功,A8侧读取到DSP发送的Frames流