DSP

DM8148从DSP侧发送Frames流到A8侧程序配置

2019-07-13 11:06发布

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的创建参数配置 /*DSP Frames out to host*/ ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkId = ipcFramesInDspId;//helloWorldID; 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; /*host Frames in from DSP*/ 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); #if 1 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------------- "); } #endif } 关于这个函数的实现可以参考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流
配置成功后串口打印