最近在用CH565开发实时传输(isochronous)USB3.0 UVC相机。发现必须允许DVP中断被USBSS中断打断,才能保证相机的帧率(640*480 166 FPS @RAW8)正常。
//设置DVP中断,0x80表示可以被打断,
?//注意:USB3.0 ISO传输成功的关键所在
PFIC_SetPriority(DVP_IRQn, 0x80 | 13);
但是这也产生另外一个后果, 就是USBSS中断和DVP中断可能同时写DMA内存。例如:DVP接收完Image Sensor送来的一行图像数据,我把行首和行尾在DMA内存中用字符串标记,以方便USB抓包分析。
void DVP_Handler_USB30(void)
{....
???? uint8_t* pRecvBuff=pRecvSlot->ptrImageBegin + pRecvSlot->dataLength;
????//行首标记:RW<行号>
????pRecvBuff[0]='R';
???? pRecvBuff[1]='W';
???? int rowCount = g_Usb30SSDvpDmaInfo.rowCount;
????//char digits[4];
????nt divisor = 1000;
????for(int i=0; i < 4; i++)
????{
????????g_dbgDigits[i] = 0x30 + rowCount/divisor;
????????owCount = rowCount % divisor;
????????divisor? = divisor / 10;
??????}
???????? pRecvBuff[2] = digits[0];
???????? pRecvBuff[3] = digits[1];
????? ? ?pRecvBuff[4] = digits[2];
???????? pRecvBuff[5] = digits[3];
????????int width = g_Usb30SSDvpDmaInfo.nImageWidth;
????????//行尾标记:<行号>end
????pRecvBuff[width - 1]='d';
????pRecvBuff[width - 2]='n';
????pRecvBuff[width - 3]='e';
????pRecvBuff[width - 4] = digits[3];
????pRecvBuff[width - 5] = digits[2];
????pRecvBuff[width - 6] = digits[1];
????pRecvBuff[width - 7] = digits[0];
...
}
USBSS IN中断抢了DVP中断,在USBSS IN中断中准备UVC ISO PayloadHeader
void EP3_IN_Callback()
{...
????if(bHasPayloadeHeader)
????{
????PayloadHeader* PH = (PayloadHeader*)g_USB30DMAInfo.dvpData;
????//PH->bHeaderLength = sizeof(PayloadHeader);
????PH->bmHeaderInfo = g_Usb30SSDvpDmaInfo.bmHeaderInfo;
????PH->scrSourceClock.dwSourceClock = g_ClkCount;
????PH->scrSourceClock.wSOFTokenCounter = (USBSS->USB_ITP >> 3) & 0x3FF;
????//PH->alignPadByte = 0x00524448 | ((USBSS->USB_ITP%26 + 0x41) << 24);//"HDR#"
????PH->dwPresentationTime = g_ClkCount;//帧开始采集时刻
????}
...
}
通过USBCap抓包分析,发现一般正常的包如下
08a0? ?6b 7c 7d 67 6f 5d 64 6c 7c 70 75 66 65 6c 75 79? ?k|}go]dl|pufeluy
08b0? ?30 30 30 30 65 6e 64 52 57 30 30 30 31 aa 8f aa? ?0000endRW0001...
08c0? ?98 bb 92 b1 92 af 8d 98 98 c3 8a c3 9c bb 91 b8? ?................
但是也出现了如下诡异的现象
5da0? ?94 71 8c 78 aa 74 9f 6f 89 71 8e 81 99 6b 87 7a? ?.q.x.t.o.q...k.z
5db0? ?88 82 84 61 7a 76 7b 6a 78 6a 6d 6c 89 60 76 66? ?...azv{jxjml.`vf
5dc0? ?30 30 33 34 65 6e 64 c5 89 30 30 33 35 b7 92 c0? ?0034end..0035...
5dd0? ?90 bf 87 b5 8c bf a0 ad a6 cb 99 cd 93 b9 9d bf? ?................
6030? ?79 83 73 79 62 7d 75 7c 7f 7c 6f 78 61 74 68 6d? ?y.syb}u|.|oxathm
6040? ?6a 7d 71 76 6f 66 5f 84 ab 30 30 33 36 85 bd 76? ?j}qvof_..0036..v
6050? ?ba 7a b2 8f c3 93 de 8b c6 97 bb 93 c6 8f c9 7f? ?.z..............
发现标记内容与程序意图不一致,刚开始怀疑是程序Bug, 将相机设置于曝光状态即像素值都为0xFF方便查看,做了各种实验发现关了中断嵌套后问题消失。怀疑问题的根本原因是不是DMA内存访问出现了冲突。
请教一下: 1)USB3.0对DMA内存读的带宽是5GBPS,DVP对DMA内存写的带宽是60MB/s, 那么USB3.0和DVP对DMA内存的读写时钟显然不一样。RISC-V内部DVP和USB3.0,是不是共用数据总线和地址总线的?如果是,如何解决时钟频率冲突的。
2)如果在中断嵌套情形下, 中断A在写DMA然后中断B打断中断A的写入,中断B也写入一些东西到DMA内存,然后中断B退出,中断A继续写入,这样会不会导致DMA内存的数据总线和地址总线时序紊乱呢?