草庐IT

xilinx PL测 DP 点屏 /接收(二)--RX

hhh_fpga 2023-12-10 原文

环境:

a)硬件:官方ZCU106开发板 , tb-fmch-vfmc-dp子卡。

b)软件:vivado2021.1,vitis2021.1,裸机程序。

1、官方例程:

 

2、DP RX IP :

 

 

 

3、DP RX寄存器:

 

 

 

 

 

4、时钟:

 

5、像素:

Stream模式:

native模式:

 

6、timming:注意de非连续,每帧hsync个数和h_active一致。

 

 

7、vitis代码分析:

a)、iic使用ps测,和官方例程不一样,所以在MCDP6000这个文件夹定义iic:

PS侧iic初始化代码:iIc速率:100K

void ps_iic_init()

{

int Status;

XIicPs_Config *Config;

/*     * Initialize the IIC driver so that it's ready to use

 * Look up the configuration in the config table,

 * then initialize it.     */

Config = XIicPs_LookupConfig(XPAR_XIICPS_1_DEVICE_ID);

if (NULL == Config) {

printf("XIicPs_LookupConfig Failed\r\n");

return XST_FAILURE;

}

Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);

if (Status != XST_SUCCESS) {

printf("XIicPs_CfgInitialize Failed\r\n");

return XST_FAILURE;

}

/*     * Perform a self-test to ensure that the hardware was built correctly.     */

Status = XIicPs_SelfTest(&Iic);

if (Status != XST_SUCCESS) {

printf("XIicPs_SelfTest Failed\r\n");

return XST_FAILURE;

}

/*     * Set the IIC serial clock rate.     */

XIicPs_SetSClk(&Iic, 100000);

}

 

DP RX的初始化:

u32 Dprx_init(void)

{

u32 Status;

XDpRxSs_Config *ConfigPtr_rx;

xil_printf("config dp rx \n\r");

ConfigPtr_rx = XDpRxSs_LookupConfig(XDPRXSS_DEVICE_ID);

if (!ConfigPtr_rx) {

xil_printf("DPRXSS Lookup Config failed.\n\r");

return XST_FAILURE;

}

Status = XDpRxSs_CfgInitialize(&DpRxSsInst, ConfigPtr_rx,ConfigPtr_rx->BaseAddress);

if (Status != XST_SUCCESS) {

xil_printf("DPRXSS config initialization failed.\n\r");

return XST_FAILURE;

}

/* Check for SST/MST support */

if (DpRxSsInst.UsrOpt.MstSupport) {

xil_printf("INFO:DPRXSS is MST enabled. DPRXSS can be "    "switched to SST/MST\n\r");

} else {

xil_printf("INFO:DPRXSS is SST enabled. DPRXSS works "    "only in SST mode.\n\r");

}

xil_printf("Dprx_init   end .\n\r");

return XST_SUCCESS;

}

 

中断初始化:这里RX,TX都有包含

u32 DpSs_SetupIntrSystem(void)

{

u32 Status;

XINTC *IntcInstPtr = &IntcInst;

// Tx side

DpTxSs_SetupIntrSystem();

// Rx side

#ifdef DP_RX_EN

DpRxSs_SetupIntrSystem();

#endif

/* The configuration parameters of the interrupt controller */

XScuGic_Config *IntcConfig;

/* Initialize the interrupt controller

 * driver so that it is ready to use. */

IntcConfig = XScuGic_LookupConfig(XINTC_DEVICE_ID);

if (NULL == IntcConfig) {

xil_printf("XINTC_DEVICE_ID XScuGic_LookupConfig failed!\n\r");

return XST_FAILURE;

}

Status = XScuGic_CfgInitialize(IntcInstPtr, IntcConfig,    IntcConfig->CpuBaseAddress);

if (Status != XST_SUCCESS) {

xil_printf("XINTC_DEVICE_ID XScuGic_CfgInitialize failed!\n\r");

return XST_FAILURE;

}

/* Connect the device driver handler that will be called when an

 * interrupt for the device occurs, the handler defined

 * above performs the specific interrupt processing for the device.

 * */

#ifdef DP_RX_EN

Status = XScuGic_Connect(IntcInstPtr, XINTC_DPRXSS_DP_INTERRUPT_ID,    (Xil_InterruptHandler)XDpRxSs_DpIntrHandler,&DpRxSsInst);

if (Status != XST_SUCCESS) {

xil_printf("ERR: DP RX SS DP interrupt connect failed!\n\r");

return XST_FAILURE;

}

/* Enable the interrupt for the DP device */

XScuGic_Enable(IntcInstPtr, XINTC_DPRXSS_DP_INTERRUPT_ID);

#endif

/* Connect the device driver handler that will be called when an

 * interrupt for the device occurs, the handler defined above performs

 * the specific interrupt processing for the device

 */

Status = XScuGic_Connect(IntcInstPtr, XINTC_DPTXSS_DP_INTERRUPT_ID,    (Xil_InterruptHandler)XDpTxSs_DpIntrHandler,&DpTxSsInst);

if (Status != XST_SUCCESS) {

xil_printf("ERR: DP TX SS DP interrupt connect failed!\r\n");

return XST_FAILURE;

}

/* Enable the interrupt */

XScuGic_Enable(IntcInstPtr, XINTC_DPTXSS_DP_INTERRUPT_ID);

/* Initialize the exception table. */

Xil_ExceptionInit();

/* Register the interrupt controller handler with the exception

 * table.*/

Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XINTC_HANDLER,IntcInstPtr);

/* Enable exceptions. */

Xil_ExceptionEnable();

return (XST_SUCCESS);

}

 

 

DP RX的中断申请:

u32 DpRxSs_SetupIntrSystem(void)

{

//    u32 Status;

//    XINTC *IntcInstPtr = &IntcInst;

/* Set callbacks for all the interrupts */

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_PWR_CHG_EVENT,            &DpRxSs_PowerChangeHandler, &DpRxSsInst);//2

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_NO_VID_EVENT,            &DpRxSs_NoVideoHandler, &DpRxSsInst);    //3

// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_VM_CHG_EVENT,            &DpRxSs_VmChangeHandler, &DpRxSsInst);

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_VBLANK_EVENT,                &DpRxSs_VerticalBlankHandler, &DpRxSsInst);//4

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_TLOST_EVENT,            &DpRxSs_TrainingLostHandler, &DpRxSsInst);//5

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_VID_EVENT,                &DpRxSs_VideoHandler, &DpRxSsInst);        //6

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_TDONE_EVENT,            &DpRxSs_TrainingDoneHandler, &DpRxSsInst);//9

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_UNPLUG_EVENT,                &DpRxSs_UnplugHandler, &DpRxSsInst);    //17

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_LINKBW_EVENT,                &DpRxSs_LinkBandwidthHandler, &DpRxSsInst);//18

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_PLL_RESET_EVENT,            &DpRxSs_PllResetHandler, &DpRxSsInst);    //19

XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_BW_CHG_EVENT,            &DpRxSs_BWChangeHandler, &DpRxSsInst);    //10

// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_ACCESS_LINK_QUAL_EVENT,    &DpRxSs_AccessLinkQualHandler, &DpRxSsInst);

// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_ACCESS_ERROR_COUNTER_EVENT,&DpRxSs_AccessErrorCounterHandler, &DpRxSsInst);

// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_CRC_TEST_EVENT,            &DpRxSs_CRCTestEventHandler, &DpRxSsInst);

// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_INFO_PKT_EVENT,            &DpRxSs_InfoPacketHandler, &DpRxSsInst);

// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_EXT_PKT_EVENT,            &DpRxSs_ExtPacketHandler, &DpRxSsInst);

/* Set custom timer wait */

XDpRxSs_SetUserTimerHandler(&DpRxSsInst, &CustomWaitUs, &TmrCtr);

return (XST_SUCCESS);

}

 

 

 

PHY的初始化:

u32 DpSs_PhyInit(u16 DeviceId)

{

XVphy_Config *ConfigPtr;

u32 Status;

/* Obtain the device configuration for the DisplayPort RX Subsystem */

ConfigPtr = XVphy_LookupConfig(DeviceId);

if (!ConfigPtr) {

return XST_FAILURE;

}

XVphy_DpInitialize(&VPhyInst, ConfigPtr, 0,

ONBOARD_REF_CLK,

ONBOARD_REF_CLK,

XVPHY_PLL_TYPE_QPLL1,

XVPHY_PLL_TYPE_CPLL,

DP_LINK_RATE);

//set the default vswing and pe for v0po

PLLRefClkSel (&VPhyInst, DP_LINK_RATE);

#if 1

    //setting vswing

    XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH1,    XVPHY_GTHE4_DIFF_SWING_DP_V0P0);

    XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH2,    XVPHY_GTHE4_DIFF_SWING_DP_V0P0);

    XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH3,    XVPHY_GTHE4_DIFF_SWING_DP_V0P0);

    XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH4,    XVPHY_GTHE4_DIFF_SWING_DP_V0P0);

    //setting postcursor

    XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH1,    XVPHY_GTHE4_PREEMP_DP_L0);

    XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH2,    XVPHY_GTHE4_PREEMP_DP_L0);

    XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH3,    XVPHY_GTHE4_PREEMP_DP_L0);

    XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH4,    XVPHY_GTHE4_PREEMP_DP_L0);

#endif

PHY_Two_byte_set (&VPhyInst, SET_RX_TO_2BYTE, SET_TX_TO_2BYTE);//SET_TX_TO_2BYTE

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX,(TRUE));

XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_TX,(TRUE));

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX,(FALSE));

XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_TX,(FALSE));

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX,(TRUE));

XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(TRUE));

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX,(FALSE));

XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(FALSE));

xil_printf("DpSs_PhyInit   end .\n\r");

Status = XVphy_ReadReg(XVPHY_BASEADDR, XVPHY_RX_INIT_STATUS_REG);

xil_printf("\n   DpSs_PhyInit  rx initialization Status 0x28 data = %x \n\r",Status);

    Status = XVphy_ReadReg(XVPHY_BASEADDR, XVPHY_PLL_LOCK_STATUS_REG);

    xil_printf("\n   DpSs_PhyInit  rx initialization Status 0x18 data = %x \n\r",Status);

return XST_SUCCESS;       

}

 

 

PHY的速率设置:

u32 config_phy(int LineRate_init_tx){

u32 Status=0;

//    u8 linerate;

//    u32 dptx_sts = 0;

switch(LineRate_init_tx){

case XDP_LINK_BW_SET_162GBPS:

Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 0 : 3]);

break;

case XDP_LINK_BW_SET_270GBPS:

Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 1 : 4]);

break;

case XDP_LINK_BW_SET_540GBPS:

Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 2 : 5]);

break;

case XDP_LINK_BW_SET_810GBPS:

Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 9 : 10]);

break;

}

xil_printf ("config_phy LineRate_init_tx = %x \r\n",LineRate_init_tx);

if (Status != XST_SUCCESS) {

xil_printf ("++++++++++ TX GT configuration encountered a failure +++++++\r\n");

}

return Status;

}

u32 PHY_Configuration(XVphy *InstancePtr,XVphy_User_Config PHY_User_Config_Table)

{

XVphy_PllRefClkSelType QpllRefClkSel;

XVphy_PllRefClkSelType CpllRefClkSel;

XVphy_PllType TxPllSelect;

XVphy_PllType RxPllSelect;

XVphy_ChannelId TxChId;

XVphy_ChannelId RxChId;

u8 QuadId = 0;

u32 Status = XST_FAILURE;

u32 retries = 0;

QpllRefClkSel   = PHY_User_Config_Table.QPLLRefClkSrc;

CpllRefClkSel   = PHY_User_Config_Table.CPLLRefClkSrc;

TxPllSelect     = PHY_User_Config_Table.TxPLL;

RxPllSelect     = PHY_User_Config_Table.RxPLL;

TxChId          = PHY_User_Config_Table.TxChId;

RxChId          = PHY_User_Config_Table.RxChId;

//Set the Ref Clock Frequency

XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, QpllRefClkSel,    PHY_User_Config_Table.QPLLRefClkFreqHz);

XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, CpllRefClkSel,    PHY_User_Config_Table.CPLLRefClkFreqHz);

XVphy_CfgLineRate(InstancePtr, QuadId, TxChId,    PHY_User_Config_Table.LineRateHz);

//    XVphy_CfgLineRate(InstancePtr, QuadId, RxChId,    PHY_User_Config_Table.LineRateHz);

// Initialize GT with ref clock and PLL selects

XVphy_PllInitialize(InstancePtr, QuadId, TxChId,QpllRefClkSel, CpllRefClkSel,TxPllSelect, RxPllSelect);

while (Status != XST_SUCCESS) {

Status = XVphy_ClkInitialize(InstancePtr, QuadId,   TxChId, XVPHY_DIR_TX);

if (retries > 100) {

retries = 0;

xil_printf ("exhausted\r\n");

break;

}

retries++;

}

// Initialize GT with ref clock and PLL selects

Status = XVphy_ClkInitialize(InstancePtr, QuadId, RxChId, XVPHY_DIR_RX);

XVphy_WriteReg(InstancePtr->Config.BaseAddr,XVPHY_PLL_RESET_REG,(XVPHY_PLL_RESET_CPLL_MASK | XVPHY_PLL_RESET_QPLL1_MASK)); // 0x06

XVphy_WriteReg(InstancePtr->Config.BaseAddr,XVPHY_PLL_RESET_REG, 0x0);

//    XVphy_ResetGtPll(InstancePtr, QuadId, RxChId, XVPHY_DIR_RX,(TRUE));

//    XVphy_ResetGtPll(InstancePtr, QuadId, RxChId, XVPHY_DIR_RX,(FALSE));

XVphy_ResetGtPll(InstancePtr, QuadId,XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX,(FALSE));

//    Status =  XVphy_WaitForResetDone(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);

//    xil_printf("\n   step_phy  XVphy_WaitForResetDone Status = %x \n\r",Status);

//    Status = XVphy_WaitForPllLock(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA);

//    xil_printf("\n   step_phy  XVphy_WaitForPllLock Status = %x \n\r",Status);

Status = XVphy_WaitForPmaResetDone(InstancePtr, QuadId,    TxChId, XVPHY_DIR_TX);

Status += XVphy_WaitForPllLock(InstancePtr, QuadId, TxChId);

Status += XVphy_WaitForResetDone(InstancePtr, QuadId,TxChId, XVPHY_DIR_TX);

if (Status  != XST_SUCCESS) {

xil_printf ("++++TX GT config encountered error++++\r\n");

}

return Status;

}

 

 

DP RX速率,lane的数目设置:

u32 DPRx_step(void)

{

u32 Status;

u32 tmp_rd;

    /* Set Link rate and lane count to maximum */

    XDpRxSs_SetLinkRate(&DpRxSsInst, DP_LINK_RATE);

    XDpRxSs_SetLaneCount(&DpRxSsInst, DP_LANE_COUNT);

    /* Start DPRX Subsystem set */

    Status = XDpRxSs_Start(&DpRxSsInst);

    if (Status != XST_SUCCESS) {

        xil_printf("ERR:DPRX SS start failed\n\r");

        return XST_FAILURE;

    }

    xil_printf("\r\n  DPRx_step  done.\n\r");

    tmp_rd = XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x4);

    tmp_rd |= tmp_rd | 0x06000000;

    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x4, tmp_rd);

    return (XST_SUCCESS);

}

 

DP RX 的开始training函数:

u32 DpRxSs_Setup(void)

{

    u32 ReadVal;

    u32 Status;

    /*Disable Rx*/

    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0);//hpd 拉低

    /*Setting BS Idle timeout value to long value*/

    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr,   XDP_RX_BS_IDLE_TIME, 0x047868C0);//这个参数,在某些应用上要适当的更改。

    /* Load Custom EDID */

    LoadEDID();

//    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr,    XDP_RX_INTERRUPT_MASK, 0xFFF87FFD);

    /*Disable All Interrupts*/

 //   XDp_RxInterruptDisable(DpRxSsInst.DpPtr, 0xFFFFFFFF);

    xil_printf("RX Link & Lane Capability is set to %x, %x\r\n",

                (XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr ,XDP_RX_DPCD_LINK_BW_SET)),

                (XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr,    XDP_RX_DPCD_LANE_COUNT_SET)));

    /*Enable Training related interrupts*/

   XDp_RxInterruptEnable(DpRxSsInst.DpPtr,

            XDP_RX_INTERRUPT_MASK_TP1_MASK|XDP_RX_INTERRUPT_MASK_TP2_MASK|

            XDP_RX_INTERRUPT_MASK_TP3_MASK|

            XDP_RX_INTERRUPT_MASK_POWER_STATE_MASK|

            XDP_RX_INTERRUPT_MASK_BW_CHANGE_MASK);

    /* Setting AUX Defer Count of Link Status Reads to 8 during Link Training

     * 8 Defer counts is chosen to handle worst case time interrupt service

     * load (PL system working at 100 MHz) when working with R5

     * */

    ReadVal = XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr,XDP_RX_AUX_CLK_DIVIDER);

    ReadVal |= ReadVal | (AUX_DEFER_COUNT<<24);

    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr,    XDP_RX_AUX_CLK_DIVIDER, ReadVal);

//-------------------------------------------------------------------------------------------------------------------

    Status =  XVphy_WaitForResetDone(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);

    Status = XVphy_WaitForPllLock(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA);

    xil_printf("\n   step_dp_rx  XVphy_WaitForPllLock Status = %x \n\r",Status);

    xil_printf("\r\n addr =%x XDP_RX_PHY_STATUS = %x \r\n",XDP_RX_PHY_STATUS,XDp_ReadReg(XDPRXSS_BASEADDR, XDP_RX_PHY_STATUS));

    XScuGic_Enable(&IntcInst, XINTC_DPRXSS_DP_INTERRUPT_ID);

//resetting AUX logic. Needed for some Type C based connectors

XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x1C, 0x80);

XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x1C, 0x0);

  //********************************************

    if(LINK_TRAINING_DEBUG)

    {

        /*Updating Vswing Iteration Count*/

        RxTrainConfig.ChEqOption = 1;

        RxTrainConfig.ClockRecoveryOption = 2;

        RxTrainConfig.Itr1Premp = 0;

        RxTrainConfig.Itr2Premp = 0;

        RxTrainConfig.Itr3Premp = 0;

        RxTrainConfig.Itr4Premp = 0;

        RxTrainConfig.Itr5Premp = 0;

        RxTrainConfig.MinVoltageSwing = 1;

        RxTrainConfig.SetPreemp = 1;

        RxTrainConfig.SetVswing = 0;

        RxTrainConfig.VswingLoopCount = 3;

        XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr,    XDP_RX_MIN_VOLTAGE_SWING,

                RxTrainConfig.MinVoltageSwing |

                (RxTrainConfig.ClockRecoveryOption << 2) |

                (RxTrainConfig.VswingLoopCount << 4) |

                (RxTrainConfig.SetVswing << 8) |

                (RxTrainConfig.ChEqOption << 10) |

                (RxTrainConfig.SetPreemp << 12) |

                (RxTrainConfig.Itr1Premp << 14) |

                (RxTrainConfig.Itr2Premp << 16) |

                (RxTrainConfig.Itr3Premp << 18) |

                (RxTrainConfig.Itr4Premp << 20) |

                (RxTrainConfig.Itr5Premp << 22)

                );

    }

    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x1);//此时HPD会拉高,开始training

    xil_printf("\r\n  DpRxSs_Setup  done.\n\r");

    return XST_SUCCESS;

}

DP RX中断说明:

void DpRxSs_VerticalBlankHandler(void *InstancePtr)    //检测到v_blank,当检测到200个就表示接收到视频

{

//    xil_printf("\r\n   4     \r\n");

DpRxSsInst.VBlankCount++;

dp_rx_ok =0;

video_cnt =0;

if(DpRxSsInst.VBlankCount==200){

XDp_RxInterruptDisable(DpRxSsInst.DpPtr,        XDP_RX_INTERRUPT_MASK_VBLANK_MASK);

DpRxSsInst.VBlankCount=0;

XDp_RxDtgDis(DpRxSsInst.DpPtr);

XDp_RxDtgEn(DpRxSsInst.DpPtr);

XDp_RxSetLineReset(DpRxSsInst.DpPtr,1);

XDp_RxSetUserPixelWidth(DpRxSsInst.DpPtr,0x04);

xil_printf("\r\n   4   VBlankCount=200  \r\n");

video_flag = 1;

}

else if(DpRxSsInst.VBlankCount==80)

{

video_flag =0;

xil_printf("\r\n   4  VBlankCount= 80    \r\n");

}

else if(DpRxSsInst.VBlankCount==20)

{

video_flag =0;

xil_printf("\r\n   4  VBlankCount= 20    \r\n");

XDp_RxInterruptEnable(DpRxSsInst.DpPtr,0x80000000);

}

}

 

void DpRxSs_TrainingLostHandler(void *InstancePtr)

{

xil_printf("\r\n   5     \r\n");

XDp_RxGenerateHpdInterrupt(DpRxSsInst.DpPtr, 750);

XDpRxSs_AudioDisable(&DpRxSsInst);

sink_power_down(); // close dp tx

vdma_stop(); // close vdma write

video_flag =0;

dp_rx_ok=0;

dp_rx_lost=1;

}

void DpRxSs_VideoHandler(void *InstancePtr)   //此中断,在检测到不同的msa会进入此中断,如果一直在进入此中断,表示training ok,但是msa的数据异常,且在变化

{

xil_printf("\r\n   6     \r\n");

video_cnt++;

if((video_cnt==1)|(video_cnt==2))

dp_rx_ok = 1;

else

dp_rx_ok =0;

if(video_cnt==8)

{

//    XDp_RxGenerateHpdInterrupt(DpRxSsInst.DpPtr, 750);

XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0);

usleep(250000);

XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x1);

}

if(0)//video_flag

{

xil_printf("\r\n   6     \r\n");

dp_rx_ok =1;

}

}

void DpRxSs_UnplugHandler(void *InstancePtr)

{

xil_printf("\r\n   17     \r\n");

video_flag =0;

/*Enable Training related interrupts*/

XDp_RxInterruptDisable(DpRxSsInst.DpPtr,  XDP_RX_INTERRUPT_MASK_ALL_MASK);

//    XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0);

XDp_RxInterruptEnable(DpRxSsInst.DpPtr,

      XDP_RX_INTERRUPT_MASK_TP1_MASK |

      XDP_RX_INTERRUPT_MASK_TP2_MASK |

XDP_RX_INTERRUPT_MASK_TP3_MASK|

XDP_RX_INTERRUPT_MASK_POWER_STATE_MASK|

XDP_RX_INTERRUPT_MASK_CRC_TEST_MASK|

XDP_RX_INTERRUPT_MASK_BW_CHANGE_MASK);

XDp_RxGenerateHpdInterrupt(DpRxSsInst.DpPtr, 5000);

}

void DpRxSs_LinkBandwidthHandler(void *InstancePtr)    // 根据 tx发送的 速率,进行更改phy的速率

{

u32 Status;

//    xil_printf("\r\n   18     \r\n");

/*Program Video PHY to requested line rate*/

PLLRefClkSel (&VPhyInst, DpRxSsInst.UsrOpt.LinkRate);

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA,XVPHY_DIR_RX,(TRUE));

XVphy_PllInitialize(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA,    ONBOARD_REF_CLK, ONBOARD_REF_CLK,XVPHY_PLL_TYPE_QPLL1, XVPHY_PLL_TYPE_CPLL);

Status = XVphy_ClkInitialize(&VPhyInst, 0,    XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);

if(Status != XST_SUCCESS)

xil_printf("XVphy_ClkInitialize failed\r\n");

}

 

void DpRxSs_PllResetHandler(void *InstancePtr)    //phy的速率更改后,重新复位。

{

//    xil_printf("\r\n   19     \r\n");

//    u32 ReadVal;

/* Issue resets to Video PHY - This API

 * called after line rate is programmed */

XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(TRUE));

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA,         XVPHY_DIR_RX,(TRUE));

XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA,         XVPHY_DIR_RX, (FALSE));

XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(FALSE));

XVphy_WaitForResetDone(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA,      XVPHY_DIR_RX);

XVphy_WaitForPllLock(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA);

/*Enable all interrupts */

XDp_RxInterruptEnable(DpRxSsInst.DpPtr,   XDP_RX_INTERRUPT_MASK_ALL_MASK);

}

 

有关xilinx PL测 DP 点屏 /接收(二)--RX的更多相关文章

  1. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  2. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  3. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  4. ruby - 如何理解 Ruby 中的发送者和接收者? - 2

    我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo

  5. ruby - 接收 block 作为参数的模拟方法 - 2

    我有一个或多或少这样的场景classAdefinitialize(&block)b=B.new(&block)endend我正在对A类进行单元测试,我想知道B#new是否正在接收传递给A#new的block。我使用Mocha作为模拟框架。这可能吗? 最佳答案 我用Mocha和RSpec都试过了,虽然我可以通过测试,但行为不正确。从我的实验中,我得出结论,验证block是否已通过是不可能的。问题:为什么要传递一个block作为参数?block将用于什么目的?什么时候调用?也许这确实是您应该用类似的东西测试的行为:classBlockP

  6. ruby-on-rails - Rails 5 Rspec 接收 ActionController::Params - 2

    我刚刚升级到Rails5。在我的规范中,我有以下内容期望(模型).toreceive(:update).with(foo:'bar')但是,由于params不再扩展Hash而现在是ActionController::Parameters规范失败了,因为with()期待一个散列,但它实际上是ActionController::Parameters是否有更好的方法在Rspec中做同样的事情,例如不同的方法with_hash?我可以使用解决这个问题expect(model).toreceive(:update).with(hash_including(foo:'bar'))但这只是检查参数是

  7. ruby - 如果 `self` 始终是 Ruby 中的隐含接收者,为什么 `self.puts` 不起作用? - 2

    在Ruby中,我的理解是self是任何裸方法调用的隐含接收者。然而:~:irb>>puts"foo"foo=>nil>>self.puts"foo"NoMethodError:privatemethod`puts'calledformain:Object这是什么原因?如果有任何帮助:>>method(:puts).owner=>Kernel 最佳答案 私有(private)方法不能有接收者我认为答案是这样的:Ruby强制方法隐私的方式是它不允许使用显式接收者调用私有(private)方法。一个例子:classBakerdefbake

  8. ruby-on-rails - 如何在 Ruby on Rails 中发送和接收加密的电子邮件? - 2

    我有一个Rails应用程序,可以在某些事件上触发电子邮件。这些电子邮件被发送到一个单独的公司,该公司将在回复时向电子邮件添加一些额外的数据。这一切都已理解并有效,我正在解析回复、提取数据并且一切正常。我现在被要求加密电子邮件。有没有人对执行此操作的最佳方法有任何经验/想法?我无法保证第3方将使用哪种电子邮件客户端,因此我需要一个可以在许多电子邮件客户端中通用的解决方案。加密必须在我发送电子邮件时由我的应用程序进行,在回复时由客户端应用程序(Outlook、Thunderbird、Entourage等)进行。然后我需要接收加密的电子邮件,对其进行解密和解析以提取我需要的新信息。谁能指出可

  9. Ruby:跨进程转发接收者、参数和 block - 2

    给定这样的代码:p=procdo|*args,&block|pselfpargspblock[]ifblockendq=procdo|*args,&block|p'before'instance_exec(*args,&p)endo=Object.newo.define_singleton_method(:my_meth,q)o.my_meth(1,2){3}如何在保留q的接收者的同时将调用从p完全转发到q?基本上我也想打印3,但是instance_exec和所有ruby​​方法一样,只能占用一个block。是否可以在不更改p的情况下,让我可以互换使用p和q(我的想法是让q有时包装p)

  10. ruby-on-rails - RSpec 期望接收带有数组的方法,但顺序无关紧要 - 2

    假设我有方法#sum,它接受一个数组并计算所有元素的总和。我正在stub:beforedoexpect(calculation_service).toreceive(:sum?).with([1,2,3]){6}end不幸的是,我的测试服以随机顺序传递数组。由于引发了该错误:Failure/Error:subject{do_crazy_stuff!}#received:sum?withunexpectedargumentsexpected:([1,2,3])got:([3,2,1])是否可以忽略数组元素的顺序对方法调用进行stub?array_including(1,2,3)无法确保数

随机推荐