本帖最后由 tn28 于 2019-7-29 13:58 编辑
此文主要针对利用DS09UB933/34/62/64-Q1等FPD-Link器件搭建的流媒体后视镜/全景泊车等应用中,由于链路设计、应用环境干扰、ESD等情况,导致概率性出现屏幕显示闪屏或者滚动的现象。利用解串器中的诊断/中断功能,再配合上有帧buffer及视频处理能力的SOC,就可以有效地应对此类问题。
TI在ADAS应用中的FPD-LINK器件均带有丰富的诊断功能,包括奇偶校验/反向通道CRC校验/LOCK状态/帧水平宽度检测/帧垂直宽度检测等,利用这些诊断功能我们可以十分便利的知道解串器接收到的数据是否有问题。同时,我们可以将以上的诊断结果映射到中断管脚上,并将中断脚连接到SOC,如果解串器接收的数据检测出来有问题的话,可以通过中断脚通知SOC去读取相关的寄存器,从而知道具体是出现什么故障了。
而对于接收端带有帧buffer或者视频处理能力的SOC的系统,在我们知道当前帧的数据有问题的话,可以通过清除帧buffer将这些有问题的视频数据清除,重新接收下一帧画面,并冻结当前的显示画面,那这些问题就不会在屏幕上显示出来了。
1. 中断指示脚INTB pin
964/962的中断指示脚是Pin 6,它为开漏输出脚,所以需要4.7Kohm上拉到VDDIO电平。当这个脚为低电平时,表明有中断请求。
Figure.1 962/964的中断指示脚
而934的中断指示脚是Pin 25,其与GPIO_3复用,同样也是开漏输出脚,建议4.7Kohm上拉到VDDIO电平。 Figure.2 934的中断指示脚
2. 962/964中断功能的使能与配置
2.1 964/962 INTB中断指示脚的使能
使用INTB中断指示脚的输出,需要先将INTERRUPT_CTL 0x23 bit_7的全局中断使能打开,然后再打开0x23 bit5:0 的中断源开关,中断源来自于4个独立的RX,以及两个独立的TX(962/964可以理解为FPD-Link III接收器即RX,以及MIPI CSI发送器即TX的组合)的各种中断。 但是如果全局中断没有使能,符合条件的中断还是会在相应的中断状态指示寄存器上置位的。例如,要在检测到IS_RX0中断的时候,INTB输出中断,需要使能IE_RX0以及INT_EN。如果只是使能了IE_RX0,但是没有使能INT_EN的话,中断来了只会在INTERRUPT_STS 0x24中断状态指示寄存器进行指示,而不会在INTB脚有指示。 而当INTB中断指示脚由于TX或者RX的某种故障状态而拉低之后,需要通过读取相应中断源的中断状态指示寄存器,来清除中断指示脚的中断状态。具体的中断状态寄存器会在稍后的篇幅中详细介绍。
Figure.3 964/962全局中断控制寄存器
Figure.4 964/962 0x24中断状态指示寄存器
示例代码: #0x30为964的7bit I2C地址 #使能964的全局中断,以及TX0_1/RX0_1_2_3中断源 Write( 0x30, 0x23, 0xBF) #使能964的全局中断,以及RX0中断源 Write( 0x30, 0x23, 0x81)
2.2 964/962 各个RX Port的独立中断源
964/962的每一个RX Port都有多个独立中断源,而这些独立中断源都可以通过PORT_ICR_HI 0xD8和PORT_ICR_LO 0xD9寄存器进行使能。同时,在PORT_ISR_HI 0xDA和PORT_ISR_LO 0xDB中断状态指示寄存器,可以提供相应的只读中断状态指示。
而清除中断指示脚,以及中断状态指示寄存器的中断状态,可以通过读RX_PORT_STS1 0x4D和RX_PORT_STS2 0x4E,以及 CSI_RX_STS 0x7A中断状态指示寄存器进行清除。因为PORT_ISR_HI/LO的中断状态位是copy 0x4D/0x4E/0x7A中断状态寄存器的,
所以只要清除了 0x4D/0x4E/0x7A这三个寄存器的中断状态指示,PORT_ISR_HI/LO的中断状态指示位也会相应的清除,同时0x24的相应中断状态也会清除。
使能某一个RX Port的独立中断源,并使能INTB中断指示脚,可以遵循以下步骤:
a) 通过设置PORT_ICR_HI 0xD8和PORT_ICR_LO 0xD9,设定所需要的独立中断源
b) 在INTERRUPT_CTL 0x23 中,将相应RX Port的中断源使能打开
c) 在INTERRUPT_CTL 0x23 中,将全局中断使能打开 清除某一个RX Port以及INTB脚的中断状态指示,可以遵循以下步骤:
a) (可选)通过INTERRUPT_STS 0x24判断,是哪个TX port或者某一个RX Port出现中断
b) (可选)通过PORT_ISR_HI 0xDA和PORT_ISR_LO 0xDB寄存器可以确定具体的中断源
c) 通过读取RX_PORT_STS1 0x4D和RX_PORT_STS2 0x4E状态寄存器CSI_RX_STS 0x7A状态寄存器,即可以清除中断标志位。
Figure.5 964/962 各RX Port独立中断源
Figure.6 964/962 各RX Port独立中断状态指示寄存器
示例代码:
#0x30为964的7bit I2C地址 #使能RX_0的独立中断源 Write( 0x30, 0x4C, 0x01) Write( 0x30, 0xD8, 0x07) Write( 0x30, 0xD9, 0x77) #使能964的全局中断,以及RX0的中断源 Write( 0x30, 0x23, 0x81) INTERRUPT_STS = ReadI2C(0x30, 0x24) //读取0x24,判断中断源 if ((INTERRUPT_STS & 0x80) >> 7): print "# GLOBAL INTERRUPT DETECTED " //如果bit 7为1,则为全局中断 if ((INTERRUPT_STS & 0x20) >> 5): print "# IS_CSI_TX1 DETECTED " //如果bit 5为1,则为TX1中断 if ((INTERRUPT_STS & 0x10) >> 4): print "# IS_CSI_TX0 DETECTED " //如果bit 4为1,则为TX0中断 if ((INTERRUPT_STS & 0x08) >> 3): print "# IS_RX3 DETECTED " //如果bit 3为1,则为RX3中断 if ((INTERRUPT_STS & 0x04) >> 2): print "# IS_RX2 DETECTED " //如果bit 2为1,则为RX2中断 if ((INTERRUPT_STS & 0x02) >> 1): print "# IS_RX1 DETECTED " //如果bit 1为1,则为RX1中断 if ((INTERRUPT_STS & 0x01) ): print "# IS_RX0 DETECTED " //如果bit 0为1,则为RX0中断 #假如RX0中断,通过0xDB/0xDA寄存器来判断具体的中断类型 Write(0x30, 0x4C,0x01) //选通RX0 PORT_ISR_LO = ReadI2C(0x30, 0xDB) //读取0xDB状态 PORT_ISR_HI = ReadI2C(0x30, 0xDA) //读取0xDA状态 if ((PORT_ISR_LO & 0x40) >> 6): print "# IS_LINE_LEN_CHG INTERRUPT DETECTED " //如果bit 6为1,则为水平宽度变化故障 if ((PORT_ISR_LO & 0x20) >> 5): print "# IS_LINE_CNT_CHG DETECTED " //如果bit 5为1,则为垂直宽度变化故障 if ((PORT_ISR_LO & 0x10) >> 4): print "# IS_BUFFER_ERR DETECTED " //如果bit 4为1,则为RX buffer 溢出故障 if ((PORT_ISR_LO & 0x04) >> 2): print "# IS_FPD3_PAR_ERR DETECTED "//如果bit 2为1,则为RX 奇偶校验错误故障 if ((PORT_ISR_LO & 0x02) >> 1): print "# IS_PORT_PASS DETECTED " //如果bit 1为1,则为RX Pass Fail 故障 if ((PORT_ISR_LO & 0x01) ) : print "# IS_LOCK_STS DETECTED " //如果bit 0为1,则为LOCK状态变更故障 if ((PORT_ISR_HI & 0x04) >> 2): print "# IS_FPD3_ENC_ERR DETECTED "//如果bit 2为1,则为RX Port 编码失败故障 if ((PORT_ISR_HI & 0x02) >> 1): print "# IS_BCC_SEQ_ERR DETECTED "//如果bit 1为1,则为BCC时序错误故障 if ((PORT_ISR_HI & 0x01) ) : print "# IS_BCC_CRC_ERR DETECTED " //如果bit 0为1,则为BC CRC校验错误故障 #通过读取0x4D/0x4E/0x7A中断状态指示寄存器,清除中断状态 Write(0x30, 0x4C,0x01) //选通RX0 ReadI2C(0x30, 0x4D) ReadI2C(0x30, 0x4E) ReadI2C(0x30, 0x7A)
2.3 964/962 TX Port的独立中断源
964/962的MIPI CSI TX端的独立中断源有五个, 可以在CSI_TX_ICR 0x36中断源控制寄存器使能,然后在CSI_TX_ISR 0x37中断状态指示寄存器读取中断状态,同时清除0x36以及INTB相应的中断状态。 中断状态寄存器的配置以及清除中断状态的操作,与RX Port类似,这里不做赘述。
3. 934中断功能的使能与配置
3.1. 934 INTB中断指示脚的使能
与964/962类似,使用934的INTB中断指示脚的输出,需要先将INTERRUPT_CTL 0x23 bit_7的全局中断使能打开,然后再打开0x23 bit 1:0 的中断源开关,中断源来自于2个独立的RX Port。 相应RX Port的中断状态也可以通过INTERRUPT_STS 0x24中断状态指示寄存器进行指示。而当INTB中断指示脚由于RX的某种故障状态而拉低之后,需要通过读取相应中断源的中断状态指示寄存器,来清除中断指示脚的中断状态。
示例代码:
#0x30 为934 的7bit I2C 地址 #使能934 的全局中断,以及RX0_1 中断源 Write( 0x30, 0x23, 0x83)
3.2. 934 各个RX Port 的独立中断源
934 的每一个RX Port 都有多个独立中断源,而这些独立中断源都可以通过PORT_ICR_HI 0xD8 和PORT_ICR_LO 0xD9 寄存器进行使能。同时,在PORT_ISR_HI 0xDA 和PORT_ISR_LO 0xDB 中断状态指示寄存器,可以提供相应的只读中断状态指示。 而清除中断指示脚,以及中断状态指示寄存器的中断状态,可以通过读RX_PORT_STS1 0x4D 和RX_PORT_STS2 0x4E 中断状态指示寄存器进行清除。因为PORT_ISR_HI/LO 的中断状态位是copy 0x4D/0x4E 中断状态寄存器的,所以只要清除了 0x4D/0x4E 这三个寄存器的中断状态指示,PORT_ISR_HI/LO 的中断状态指示位也会相应的清除,同时0x24 的相应中断状态也会清除。 示例代码请参考2.2 章节中对964/962 的操作。
4. 实际应用配置
如本文开关所述,对于流媒体后视镜/全景泊车等ADAS 应用中,由于各种各样设计及外在干扰等因素,有可能会导致实际显示效果因为闪屏问题的出现而不及预期。为解决此类问题,我们可以利用解串器中的诊断/中断功能,再配合上有帧buffer 及视频处理能力的SOC,将有问题的视频数据过滤掉。 下文以964/962 为解串器举例,着重阐述解串器端应该是如何进行中断功能的使能及配置,SOC 端的处理方式请咨询相应SOC 的支持团队,此处不做赘述。而934 的配置方式与964/962 十分类似,因为964/962 的独立中断源是比934 多的,并且有TX 端的中断源,我们只需要将多出来的这部分中断源不做配置,只配置934 独有的中断源即可,因此934 的配置方式及示例代码请参考964/962 的配置。
4.1. 964/962 同步模式下中断相关的配置
964/962 有三种同步输出模式,分别是Basic Synchronized/Line-Interleave/Line- Concatenated。在同步模式下,TX Port 会将各个RX Port 输入的视频数据,根据相应的模式同步好之后,再进行输出。当其中一个或者多个RX Port 的视频数据超过一个行长度的时间还没有输入到buffer 里面的话,即认为当前packet 数据同步失败,964/962 就会将buffer 里面其它RX Port 的视频数据清除,并接收下一个video line 数据,此时MIPI CSI 口会没有数据输出。 所以,在同步模式下,因为964/962 会将所有RX Port 的数据同步之后再进行输出,建议只用TX 的独立中断源来检测MIPI CSI 数据是否有异常,这样做相对比较简单,软件处理中断任务的时间及占用的资源相对较少。另外,因为每一个终端产品的设计/线束/应用环境等参数都有所差异,造成不同的系统可能因不同的原因而对某种中断源比较敏感, 所以在独立中断源的使能上也需要因系统而异,根据调试结果逐步减少独立中断源的使能,从而防止中断重复上报而过多占用系统资源。
示例程序:
#0x30 为964 的7bit I2C 地址 #使能964 TX0_1 的独立中断源 Write( 0x30, 0x32, 0x01) //选通TX0 Write( 0x30, 0x36, 0x1F) //可以根据测试效果减少独立中断源 Write( 0x30, 0x32, 0x12) //选通TX1 Write( 0x30, 0x36, 0x1F) //可以根据测试效果减少独立中断源 #使能964 的全局中断,以及TX0_1 中断源 Write( 0x30, 0x23, 0xB0)
#当检测到中断事件后,通过读取相关寄存器判断中断源并清除中断
INTERRUPT_STS = ReadI2C(0x30, 0x24) //读取0x24,判断中断源是来自哪个TX port
if ((INTERRUPT_STS & 0x80) >> 7):
print "# GLOBAL INTERRUPT DETECTED "//如果bit 7 为1,则为全局中断
if ((INTERRUPT_STS & 0x20) >> 5):
print "# IS_CSI_TX1 DETECTED " //如果bit 5 为1,则为TX1 中断
if ((INTERRUPT_STS & 0x10) >> 4):
print "# IS_CSI_TX0 DETECTED " //如果bit 4 为1,则为TX0 中断
#如果是来自与TX1 的中断,可通过0x37 判断中断类型并清除中断
Write( 0x30, 0x32, 0x12) //选通TX1
CSI_TX_ISR = ReadI2C(0x30, 0x37) //读取0x37 状态并清除中断
if ((CSI_TX_ISR & 0x10) >> 4):
print "# IS_RX_PORT_INT " //如果bit 4 为1,则为RX 出现中断故障
if ((CSI_TX_ISR & 0x08) >> 3):
print "# IS_CSI_SYNC_ERROR " //如果bit 3 为1,则为输入信号同步错误故障
if ((CSI_TX_ISR & 0x04) >> 2):
print "# IS_CSI_SYNC " //如果bit 2 为1,则为TX 同步时出现错误故障
if ((CSI_TX_ISR & 0x02) >> 1):
print "# IS_CSI_PASS_ERROR " //如果bit 1 为1,则为RX 数据不符合PASS 标准
if ((CSI_TX_ISR & 0x01)):
print "# IS_CSI_PASS " //如果bit 0 为1,则为TX 数据不符合PASS 标准
4.2. 964/962 异步模式下中断相关的配置
当964/962 的输出模式配置为best-effort round robin forwarding 时,便工作在异步输出模式。在该模式下,TX Port 使用标准的CSI-2 格式传输视频流,且各个摄像头的视频数据的输出没有特定的顺序,当RX Port 的数据ready 后就进行输出,而不会等待同步完成后再输出。而如果同一时间多个packet 都ready 的话,TX 的发送器会工作在round robin 的循环模式,逐个将RX 的数据循环进行输出。
异步模式可以接受RX Port 的数据是不同的格式,并且不需要各个port 之间的数据同步, 但是需要接收端的SOC 能根据VC ID 和data type 来区分不同输入源。
在异步模式下,因为962/964 不会检测同步信号,所以为了提高系统处理的效率,可以不使用TX 端的独立中断源来进行故障的判断,而是使能RX Port 的独立中断源来进行检测。同样的,在对系统进行测试的时候,如果发现964/962 有重复上报中断的话,需要优化0x23/0xD8/0xD9 的独立中断源使能,看系统对哪些中断源比较敏感,然后关闭不必要的中断源,避免重复上报中断导致多帧画面被丢弃。
示例程序:
#0x30为964的7bit I2C地址 #使能964 RX0_1_2_3的独立中断源 Write( 0x30, 0x4C, 0x01) //选通RX_0 Write( 0x30, 0xD8, 0x07) //需要根据测试效果减少独立中断源 Write( 0x30, 0xD9, 0x77) Write( 0x30, 0x4C, 0x12) //选通RX_1 Write( 0x30, 0xD8, 0x07) //需要根据测试效果减少独立中断源 Write( 0x30, 0xD9, 0x77) Write( 0x30, 0x4C, 0x24) //选通RX_2 Write( 0x30, 0xD8, 0x07) //需要根据测试效果减少独立中断源 Write( 0x30, 0xD9, 0x77) Write( 0x30, 0x4C, 0x38) //选通RX_3 Write( 0x30, 0xD8, 0x07) //需要根据测试效果减少独立中断源 Write( 0x30, 0xD9, 0x77) #使能964的全局中断,以及RX0_1_2_3中断源 Write( 0x30, 0x23, 0x8F)
#当检测到中断事件后,通过读取相关寄存器判断中断源并清除中断
INTERRUPT_STS = ReadI2C(0x30, 0x24) //读取0x24,判断中断源是来自哪个RX port
if ((INTERRUPT_STS & 0x80) >> 7):
print "# GLOBAL INTERRUPT DETECTED " //如果bit 7为1,则为全局中断
if ((INTERRUPT_STS & 0x08) >> 3):
print "# IS_RX3 DETECTED " //如果bit 3为1,则为RX3中断
if ((INTERRUPT_STS & 0x04) >> 2):
print "# IS_RX2 DETECTED " //如果bit 2为1,则为RX2中断
if ((INTERRUPT_STS & 0x02) >> 1):
print "# IS_RX1 DETECTED " //如果bit 1为1,则为RX1中断
if ((INTERRUPT_STS & 0x01) ):
print "# IS_RX0 DETECTED " //如果bit 0为1,则为RX0中断
#假如RX0中断,通过0xDB/0xDA寄存器来判断具体的中断类型。
#对RX_1_2_3的中断施行同样的操作。
Write(0x30, 0x4C,0x01) //选通RX0
PORT_ISR_LO = ReadI2C(0x30, 0xDB) //读取0xDB状态
PORT_ISR_HI = ReadI2C(0x30, 0xDA) //读取0xDA状态
if ((PORT_ISR_LO & 0x40) >> 6):
print "# IS_LINE_LEN_CHG INTERRUPT DETECTED " //如果bit 6为1,则为水平宽度变化故障
if ((PORT_ISR_LO & 0x20) >> 5):
print "# IS_LINE_CNT_CHG DETECTED " //如果bit 5为1,则为垂直宽度变化故障
if ((PORT_ISR_LO & 0x10) >> 4):
print "# IS_BUFFER_ERR DETECTED " //如果bit 4为1,则为RX buffer 溢出故障
if ((PORT_ISR_LO & 0x04) >> 2):
print "# IS_FPD3_PAR_ERR DETECTED " //如果bit 2为1,则为RX 奇偶校验错误
if ((PORT_ISR_LO & 0x02) >> 1):
print "# IS_PORT_PASS DETECTED " //如果bit 1为1,则为RX Pass Fail 故障
if ((PORT_ISR_LO & 0x01) ) :
print "# IS_LOCK_STS DETECTED " //如果bit 0为1,则为LOCK状态变更故障
if ((PORT_ISR_HI & 0x04) >> 2):
print "# IS_FPD3_ENC_ERR DETECTED " //如果bit 2为1,则为RX 编码失败故障
if ((PORT_ISR_HI & 0x02) >> 1):
print "# IS_BCC_SEQ_ERR DETECTED " //如果bit 1为1,则为BC时序错误故障
if ((PORT_ISR_HI & 0x01) ) :
print "# IS_BCC_CRC_ERR DETECTED "//如果bit 0为1,则为BC CRC校验错误故障
#通过读取0x4D/0x4E/0x7A中断状态指示寄存器,清除中断状态
Write(0x30, 0x4C,0x01) //选通RX0
ReadI2C(0x30, 0x4D) //清除中断
ReadI2C(0x30, 0x4E)
ReadI2C(0x30, 0x7A)
|