Skip navigation
Home > All Places > USB > USB Superspeed Peripherals > Blog > Authors YangyangC_06

     在本篇 blog 中,我们学习如何在固件中已有的分辨率基础上,添加新的分辨率。本篇 blog ,我们在上一篇 blog 的固件的基础上进行修改,所以用的硬件还是CX3      Denebola RDK。原固件中只定义了 1080P@30fps,此处我们增加 720P@60fps。

 

  1. 首先我们需要在描述符文件中添加相应的 frame descriptor。
    /* Class specific Uncompressed VS frame descriptor 2 - 720p@ 60fps*/
    0x1E,                               /* Descriptor size */
    CX3_CS_INTRFC_DESCR,                /* Descriptor type*/
    0x05,                               /* Subtype: Uncompressed frame interface*/
    0x02,                               /* Frame Descriptor Index: 2 */
    0x00,                               /* No Still image capture supported */
    0x00, 0x05,                         /* Width in pixel: 1280 */
    0xD0, 0x02,                         /* Height in pixel: 720 */
    0x00, 0x00, 0x57, 0x30,             /* Min bit rate @55fps (bits/s): 720 x 1280 x 2 x 55 x 8 = 811008000 */
    0x00, 0x00, 0xBC, 0x34,             /* Max bit rate @60fps (bits/s). 720 x 1280 x 2 x 60 x 8 = 884736000 */
    0x00, 0x20, 0x1C, 0x00,             /* Maximum video frame size in bytes(Deprecated): 1280 x 720 x 2   */
    0x0A, 0x8B, 0x02, 0x00,             /* Default frame interval (in 100ns units): (1/60)x10^7 */
    0x01,                               /* Frame interval type : No of discrete intervals */
    0x0A, 0x8B, 0x02, 0x00,             /* Frame interval 3: Same as Default frame interval */

  

可以看到,此处定义720P@60fps 的frame index 为2.

 

2. 修改 VS format descriptor  中的 frame descriptor 的个数。

    0x02,                               /* Number of Frame Descriptors that follow this descriptor: 2 */

 

3. 修改 Class-specific Video Streaming Input Header Descriptor  中的 Total size of Class specific VS descr.

    /* Class-specific Video Streaming Input Header Descriptor */
    0x0E,                               /* Descriptor size */
    CX3_CS_INTRFC_DESCR,                /* Class-specific VS I/f Type */
    0x01,                               /* Descriptor Subtype: Input Header */
    0x01,                               /* 1 format desciptor follows */
#ifdef Two_frame_rate
//    0x56,0x00,                          /* Total size of Class specific VS descr */
    0x74,0x00, /* Total size of Class specific VS descr */
#else
    0x52,0x00,                          /* Total size of Class specific VS descr */
#endif
    CX3_EP_BULK_VIDEO,                  /* EP address for BULK video data: EP 3 IN */
    0x00,                               /* No dynamic format change supported */
    0x04,                               /* Output terminal ID : 4 */
    0x02,                               /* > Still image capture method supported */
    0x00,                               /* Hardware trigger NOT supported */
    0x00,                               /* Hardware to initiate still image capture not supported */
    0x01,                               /* Size of controls field : 1 byte */
    0x00,                               /* D2 : Compression quality supported - No compression*/

 

4. 修改 configuration descriptor 的总长度

   /* Configuration Descriptor*/
    0x09,                               /* Descriptor Size */
    CY_U3P_USB_CONFIG_DESCR,            /* Configuration Descriptor Type */
#ifdef Two_frame_rate
//    0xe9,0x00,                         /* Length of this descriptor and all sub descriptors */
    0x07,0x01, /* Length of this descriptor and all sub descriptors */
#else
    0xe5,0x00,                         /* Length of this descriptor and all sub descriptors */
#endif
    0x02,                               /* Number of interfaces */
    0x01,                               /* Configuration number */
    0x03,                               /* Configuration string index */
    0xC0,                               /* Config characteristics - Self Powered */
    0x0C,                               /* Max power consumption of device (in 8mA unit) : 96mA */

 

5. 添加 Probe structure

/* UVC Probe Control Setting - 720p@60fps*/
uint8_t const gl720pProbeCtrl[CX3_APP_MAX_PROBE_SETTING] = {
    0x00, 0x00,                         /* bmHint : No fixed parameters */
    0x01,                               /* Use 1st Video format index */
    0x02,                               /* Use 2nd Video frame index */
    0x0A, 0x8B, 0x02, 0x00,             /* Desired frame interval in 100ns = (1/60)x10^7*/
    0x00, 0x00,                         /* Key frame rate in key frame/video frame units */
    0x00, 0x00,                         /* PFrame rate in PFrame / key frame units */
    0x00, 0x00,                         /* Compression quality control */
    0x00, 0x00,                         /* Window size for average bit rate */
    0x00, 0x00,                         /* Internal video streaming i/f latency in ms */
    0x00, 0x20, 0x1C, 0x00,             /* Max video frame size in bytes: 720 x 1280 x 2*/
#ifdef CX3_UVC_1_0_SUPPORT
    0x00, 0x90, 0x00, 0x00              /* No. of bytes device can rx in single payload: 36KB */
#else
    /* UVC 1.1 Probe Control has additional fields from UVC 1.0 */
    0x00, 0x90, 0x00, 0x00,             /* No. of bytes device can rx in single payload: 36KB */
    0x00, 0x60, 0xE3, 0x16,             /* Device Clock */
    0x00,                               /* Framing Information - Ignored for uncompressed format*/
    0x00,                               /* Preferred payload format version */
    0x00,                               /* Minimum payload format version */
    0x00                                /* Maximum payload format version */
#endif
};

 

6. 在添加 if 分支 以向主机返回相应的 Probe structure

/*Returns the pointer to the Probe Control structure for the corresponding frame index.*/
uint8_t *
CyCx3UvcAppGetProbeControlData (
        CyU3PUSBSpeed_t usbConType,
        uint8_t         frameIndex,
        uint32_t glCurrentFrameInterval
        )
{
uint32_t frame_fps = 10000000 / glCurrentFrameInterval;
    if (usbConType == CY_U3P_SUPER_SPEED)
    {
       if (frameIndex == 1)
        {
       if(frame_fps == 30)
       {
            /* 1920 x 1080 @30.0 fps */
       CyU3PDebugPrint(4,"\n Line:%d: Return 30 fps structure",__LINE__);
               return ((uint8_t *) gl1080pProbeCtrl_30fps);
       }
       else if(frame_fps == 60)
       {              /* 1920 x 1080 @60.0 fps */
       CyU3PDebugPrint(4,"\n Line:%d Return 60 fps structure",__LINE__);
                  return ((uint8_t *) gl1080pProbeCtrl_60fps);
       }


        }
       else if (frameIndex == 2)
       {
           return ((uint8_t *) gl720pProbeCtrl);


       }
    }
    else if (usbConType == CY_U3P_HIGH_SPEED)
    {
    }
    else
    {


    }
    return NULL;
}







 

7. 添加 720P 对应的 MIPI CSI 初始化参数 结构体,此处我们直接添加 SDK 目录下的 Cx3UVCOV5640 例子中的参数。用户在使用其他sensor以及添加其他分辨率的支持时,需要首先确认 sensor 的配置参数,将参数输入到 MIPI configuration tool 里面进行计算,从而找到一组合适 的 MIPI CSI的初始化参数。需要注意的是,同样一组sensor 的 配置参数,与之对应的MIPI CSI 初始化参数不止一组,找到一组可用值即可。用户在MIPI configuration tool里面也可以看到, 很多参数都是有一个允许的取值范围,而不是唯一值。

/* Configuration parameters for 720p @60FPS for the OV5640 sensor */
CyU3PMipicsiCfg_t cfgUvc720p60NoMclk =  { 
    CY_U3P_CSI_DF_YUV422_8_2,     /* dataFormat   */
    2,                          /* numDataLanes */
    1,                        /* pllPrd       */
    62,                         /* pllFbd       */
    CY_U3P_CSI_PLL_FRS_250_500M, /* pllFrs      */
    CY_U3P_CSI_PLL_CLK_DIV_4,   /* csiRxClkDiv  */
    CY_U3P_CSI_PLL_CLK_DIV_4,   /* parClkDiv    */
    0x00,                       /* mclkCtl      */
    CY_U3P_CSI_PLL_CLK_DIV_8,   /* mClkRefDiv   */
    1280,                       /* hResolution  */
    0x01                       /* fifoDelay    */
};

 

8. 在 SetVideoResolution 中添加720P对应分支。

static void
CyCx3UvcAppImageSensorSetVideoResolution(
        uint8_t resolution_index,
        uint32_t frame_Interval
        )
{
CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
uint32_t frameRate= 10000000/frame_Interval;
switch (CyU3PUsbGetSpeed ())
{
case CY_U3P_SUPER_SPEED:
switch (resolution_index)
{
case 0x01:
{
if(frameRate == 30)
{
CyU3PDebugPrint(4,"\r\n Line:%d: Set 30 fps",__LINE__);
/* Write 1080pSettings */
#ifndef FX3_STREAMING
status = CyU3PMipicsiSetIntfParams (&OV5640_YUY2_1080p, CyFalse);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "\n\rUSBStpCB:SetIntfParams SS1 Err = 0x%x", status);
}
#endif
CyCx3_ImageSensor_Set_1080p ();


}
else if (frameRate == 60)
{
CyU3PDebugPrint(4,"\r\n Line:%d: Set 60 fps",__LINE__);
/* Write 1080pSettings */
#ifndef FX3_STREAMING
status = CyU3PMipicsiSetIntfParams (&OV5640_YUY2_1080p, CyFalse);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "\n\rUSBStpCB:SetIntfParams SS1 Err = 0x%x", status);
}
#endif
CyCx3_ImageSensor_Set_1080p ();


}


}
break;


case 0x02:
{
CyU3PDebugPrint(4,"\r\n Line:%d: Set 720P@60fps",__LINE__);
/* Write 720pSettings */
#ifndef FX3_STREAMING
status = CyU3PMipicsiSetIntfParams (&cfgUvc720p60NoMclk, CyFalse);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "\n\rUSBStpCB:SetIntfParams SS1 Err = 0x%x", status);
}
#endif
CyCx3_ImageSensor_Set_720p ();


}
break;


}
break;


case CY_U3P_HIGH_SPEED:
switch (resolution_index)
{




}
break;
}
}













 

至此,固件修改完成。编译并下载到Demo 板中测试。可以看到,现在固件可以支持 720P@60fps 的视频传输。

Snipaste_2019-08-03_12-05-18.png

Snipaste_2019-08-03_12-05-02.png

 

同样,附件提供修改后的固件,供用户参考。

在本篇 blog 中,我们学习如何在同一个分辨率下支持多个帧率的视频传输。

 

  1. 首先,我们需要对 frame descriptor 进行修改。此处,我们配置分辨率为 1920 x 1080,帧率分别为 30 fps 和 60 fps。
    0x22,                               /* Descriptor size */
    CX3_CS_INTRFC_DESCR,                /* Descriptor type*/
    0x05,                               /* Subtype:  frame interface*/
    0x01,                               /* Frame Descriptor Index: 1 */
    0x00,                               /* No Still image capture method supported */
    0x80,0x07,                         /* Width in pixel:  1920 */
    0x38,0x04,                         /* Height in pixel: 1080 */
    0x00,0x00,0xa7,0x76,             /* Max bit rate (bits/s): 1920 x 1080 x 16 x 60 = 0x76a70000 */
    0x00,0x80,0x53,0x3b,             /* Min bit rate (bits/s): 1920 x 1080 x 16 x 30 = 995328000 */
    0x00,0x48,0x3f,0x00,             /* Maximum video or still frame size in bytes(Deprecated): 1920 x 1080 x 2 */
    0x15,0x16,0x05,0x00,             /* Default frame interval (in 100ns units): (1/30)x10^7 */
    0x02,                               /* Frame interval type : No of discrete intervals */
    0x0a,0x8b,0x02,0x00, /* 60 fps */
    0x15,0x16,0x05,0x00,             /* 30 fps */

 

2.随后修改 Class-specific Video Streaming Input Header Descriptor  中的长度值。

 

    0x56,0x00,                          /* Total size of Class specific VS descr */

 

和 CyCx3USBSSConfigDscr 中的总长度值。

 

    0xe9,0x00,                         /* Length of this descriptor and all sub descriptors */

 

 

3. 分别配置 30fps 和 60fps 对应的 probe 结构体

/* UVC Probe Control Setting - 1080p_60fps*/
uint8_t const gl1080pProbeCtrl_60fps[CX3_UVC_MAX_PROBE_SETTING] = {
    0x00, 0x00,                         /* bmHint : No fixed parameters */
    0x01,                               /* Use 1st Video format index */
    0x01,                               /* Use 1st Video frame index */
    0x0a,0x8b,0x02,0x00,             /* Desired frame interval in 100ns = (1/30)x10^7 */
    0x00, 0x00,                         /* Key frame rate in key frame/video frame units */
    0x00, 0x00,                         /* PFrame rate in PFrame / key frame units */
    0x00, 0x00,                         /* Compression quality control */
    0x00, 0x00,                         /* Window size for average bit rate */
    0x00, 0x00,                         /* Internal video streaming i/f latency in ms */
    0x00,0x48,0x3f,0x00,             /* Max video frame size in bytes = 1920 x 1080 x 2 */
#ifdef CX3_UVC_1_0_SUPPORT
    0x00, 0x90, 0x00, 0x00              /* No. of bytes device can rx in single payload: 36KB */
#else
    /* UVC 1.1 Probe Control has additional fields from UVC 1.0 */
    0x00, 0x90, 0x00, 0x00,             /* No. of bytes device can rx in single payload: 36KB */
    0x00, 0x60, 0xE3, 0x16,             /* Device Clock */
    0x00,                               /* Framing Information - Ignored for uncompressed format*/
    0x00,                               /* Preferred payload format version */
    0x00,                               /* Minimum payload format version */
    0x00                                /* Maximum payload format version */
#endif
};


 

/* UVC Probe Control Setting - 1080p_30fps*/
uint8_t const gl1080pProbeCtrl_30fps[CX3_UVC_MAX_PROBE_SETTING] = {
    0x00, 0x00,                         /* bmHint : No fixed parameters */
    0x01,                               /* Use 1st Video format index */
    0x01,                               /* Use 1st Video frame index */
    0x15,0x16,0x05,0x00,             /* Desired frame interval in 100ns = (1/30)x10^7 */
    0x00, 0x00,                         /* Key frame rate in key frame/video frame units */
    0x00, 0x00,                         /* PFrame rate in PFrame / key frame units */
    0x00, 0x00,                         /* Compression quality control */
    0x00, 0x00,                         /* Window size for average bit rate */
    0x00, 0x00,                         /* Internal video streaming i/f latency in ms */
    0x00,0x48,0x3f,0x00,             /* Max video frame size in bytes = 1920 x 1080 x 2 */ 
#ifdef CX3_UVC_1_0_SUPPORT 
    0x00, 0x90, 0x00, 0x00              /* No. of bytes device can rx in single payload: 36KB */
#else
    /* UVC 1.1 Probe Control has additional fields from UVC 1.0 */
    0x00, 0x90, 0x00, 0x00,             /* No. of bytes device can rx in single payload: 36KB */
    0x00, 0x60, 0xE3, 0x16,             /* Device Clock */
    0x00,                               /* Framing Information - Ignored for uncompressed format*/
    0x00,                               /* Preferred payload format version */
    0x00,                               /* Minimum payload format version */
    0x00                                /* Maximum payload format version */
#endif
};


 

 

4.修改 CyCx3UvcAppGetProbeControlData 以返回相应的 probe 结构体

/*Returns the pointer to the Probe Control structure for the corresponding frame index.*/
uint8_t *
CyCx3UvcAppGetProbeControlData (
        CyU3PUSBSpeed_t usbConType,
        uint8_t         frameIndex,
        uint32_t glCurrentFrameInterval
        )
{
uint32_t frame_fps = 10000000 / glCurrentFrameInterval;
    if (usbConType == CY_U3P_SUPER_SPEED)
    {
       if (frameIndex == 1)
        {
       if(frame_fps == 30)
       {
            /* 1920 x 1080 @30.0 fps */
       CyU3PDebugPrint(4,"\n Line:%d: Return 30 fps structure",__LINE__);
               return ((uint8_t *) gl1080pProbeCtrl_30fps);
       }
       else if(frame_fps == 60)
       {              /* 1920 x 1080 @60.0 fps */
       CyU3PDebugPrint(4,"\n Line:%d Return 60 fps structure",__LINE__);
                  return ((uint8_t *) gl1080pProbeCtrl_60fps);
       }


        }
    }
    else if (usbConType == CY_U3P_HIGH_SPEED)
    {
    }
    else
    {


    }
    return NULL;
}







 

 

5. 在 Callback 函数中修改 Set_cur 的代码

 

    /* Set Probe Control */
    if (wValue == CX3_UVC_VS_PROBE_CONTROL)
    {
        glCurrentFrameIndex = glCommitCtrl[3];
#ifdef Two_frame_rate
        glCurrentFrameInterval = ((uint32_t)glCommitCtrl[7] << 24) | ((uint32_t)glCommitCtrl[6] << 16) |
((uint32_t)glCommitCtrl[5] << 8) | ((uint32_t)glCommitCtrl[4] << 0);
        CyU3PDebugPrint(4,"\r\n Line:%d: glCurrentFrameInterval = 0x%x",__LINE__,glCurrentFrameInterval);
#endif
    }

 

6. 修改 SetVideoResolution 函数的实现

 

/* Set the video resolution through this function. This function lists all the
 *  supported resolutions in SuperSpeed and HighSpeed. The frame index of resolutions
 *  supported in Still Capture can be different from the frame index of resolutions supported
 *  in Video streaming.
 */
static void
CyCx3UvcAppImageSensorSetVideoResolution(
        uint8_t resolution_index,
        uint32_t frame_Interval
        )
{
CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
uint32_t frameRate= 10000000/frame_Interval;
switch (CyU3PUsbGetSpeed ())
{
case CY_U3P_SUPER_SPEED:
switch (resolution_index)
{
case 0x01:
{
if(frameRate == 30)
{
CyU3PDebugPrint(4,"\r\n Line:%d: Set 30 fps",__LINE__);
/* Write 1080pSettings */
#ifndef FX3_STREAMING
status = CyU3PMipicsiSetIntfParams (&OV5640_YUY2_1080p, CyFalse);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "\n\rUSBStpCB:SetIntfParams SS1 Err = 0x%x", status);
}
#endif
CyCx3_ImageSensor_Set_1080p ();


}
else if (frameRate == 60)
{
CyU3PDebugPrint(4,"\r\n Line:%d: Set 60 fps",__LINE__);
/* Write 1080pSettings */
#ifndef FX3_STREAMING
status = CyU3PMipicsiSetIntfParams (&OV5640_YUY2_1080p, CyFalse);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "\n\rUSBStpCB:SetIntfParams SS1 Err = 0x%x", status);
}
#endif
CyCx3_ImageSensor_Set_1080p ();


}


}
break;


}
break;


case CY_U3P_HIGH_SPEED:
switch (resolution_index)
{




}
break;
}
}



 

 

按以上的步骤修改后,将固件下载至Demo 板,进行测试。

 

Snipaste_2019-08-02_17-12-35.png

 

 

Snipaste_2019-08-02_17-12-13.png

 

 

Snipaste_2019-08-02_17-11-58.png

 

可以看到,用户可以在主机端软件中对不同 fps 的配置进行正常切换。用户可以参考附件的工程获取更多细节信息。

 

注:

  • 出于演示的目的,本篇文档所附的固件中,只配置了USB3.0 的配置描述符(以及其他所有相关的 处理函数),没有 设置 USB2.0 及以下速度对应的配置描述符。如有需要,用户可以自行进行添加。
  • 同上,本篇 blog 所附的固件中,实际上当主机设置不同的 fps 时,固件采用相同的参数对 MIPI CSI 模块和 sensor进行配置(即执行相同的代码),只是采用 UART 打印的方式演示函数分支可以正常执行。实际使用中,用户当然需要做不同的配置。
  • 在主机软件的分辨率列表中,同一分辨率只会显示默认的帧率,不会同时列出所有帧率。
  • 在第一步中,需要先定义Max bits/s 后 Min bits/s,先 高帧率 后低帧率,否则烧录固件后不能正常工作。参考 CX3 multiple framerate support in same resolution

在本篇blog中,我们学习如何在UVC 应用中实现对图像属性的控制。本篇笔记中应用到的 固件 为 第四篇笔记 的附件,硬件 为 CX3 Denebola 板。

 

从 UVC 1.5 协议上可以看到,亮度控制属于 processing unit的内容,必需支持的控制命令有 SET_CUR、GET_CUR、GET_MIN、GET_MAX、GET_RES、GET_INFO 和 GET_DEF。

BaiduShurufa_2019-6-13_10-11-21.png

 

首先,在cycx3_uvcdscr.c 描述符文件中找到 processing unit 描述符部分

    /* Processing Unit Descriptor */
    0x0D,                               /* Descriptor size */
    CX3_CS_INTRFC_DESCR,                /* Class specific interface desc type */
    0x05,                               /* Processing Unit Descriptor type: VC_PROCESSING_UNIT*/
    0x02,                               /* ID of this unit */
    0x01,                               /* Source ID: 1: Conencted to input terminal */
    0x00, 0x40,                         /* Digital multiplier */
    0x03,                               /* Size of controls field for this terminal: 3 bytes */
    0x00, 0x00, 0x00,                   /* No controls supported */
    0x00,                               /* String desc index: Not used */
    0x00,                               /* Analog Video Standards Supported: None */

 

查询 UVC 协议可以看到,Byte 8/9/10 用来指定UVC支持哪些控制属性。

BaiduShurufa_2019-6-13_10-21-50.png

可以看到,bit[0] 用来指定是否支持亮度控制,所以这里我们将 bit[0] 设置为1.

    /* Processing Unit Descriptor */
    0x0D,                               /* Descriptor size */
    CX3_CS_INTRFC_DESCR,                /* Class specific interface desc type */
    0x05,                               /* Processing Unit Descriptor type: VC_PROCESSING_UNIT*/
    0x02,                               /* ID of this unit */
    0x01,                               /* Source ID: 1: Conencted to input terminal */
    0x00, 0x40,                         /* Digital multiplier */
    0x03,                               /* Size of controls field for this terminal: 3 bytes */
    0x01, 0x00, 0x00,                   /* Brigntness control is supported */
    0x00,                               /* String desc index: Not used */
    0x00,                               /* Analog Video Standards Supported: None */

 

在函数 CyCx3UvcAppUSBSetupCB 中添加如下代码

 

#ifdef Add_brightness_control
/* Handle Video control commands here*/
        status =  HandleVCInterfaceRequest(wIndex, wValue, bRequest);
            if (status != CY_U3P_SUCCESS)
            {
                CyU3PDebugPrint (4, "\n\rUSBStpCB:VCI SendEP0Data = %d", status);
                isHandled=CyFalse;
            }
            else
            isHandled = CyTrue;


#endif

 

添加 定义

 

#ifdef Add_brightness_control


CyU3PReturnStatus_t HandleVCInterfaceRequest(uint16_t wIndex, uint16_t wValue,uint8_t bRequest)
{
CyU3PReturnStatus_t status = CY_U3P_ERROR_BAD_ARGUMENT;
  if (CY_U3P_GET_MSB(wIndex) == CX3_UVC_VC_PROCESSING_UNIT_ID) /*Video Control- Camera Teminal*/
  {
    CyU3PDebugPrint(4,"\n\r\n\rLine:%d\tVC:T ID 0x%x CS 0x%x Req 0x%x ", __LINE__,CY_U3P_GET_MSB(wIndex), wValue, bRequest);


    switch (wValue)
    {
    case CX3_UVC_PU_BRIGHTNESS_CONTROL: /*LED control*/
        CyU3PDebugPrint(4,"\r\n Brightness control\n");
      status = HandleBrightnessControlReq(bRequest);
      break;


    default:
//       glerrorstatus = VC_ERROR_CODE_INVALID_CONTROL;
      break;
    }
  }
return status;
}




CyU3PReturnStatus_t HandleBrightnessControlReq(uint8_t bRequest)
{
CyU3PReturnStatus_t status=1;
uint16_t readCount;
uint8_t WrBuff[2]={0,0},RdBuff;
switch(bRequest)
{
case CX3_USB_UVC_GET_CUR_REQ:
WrBuff[0] = Brightness.CurrentVal;
        CyU3PDebugPrint(4,"\r\nLine:%d  UVC Brightness get cur %d\n",__LINE__,WrBuff);
break;


case CX3_USB_UVC_SET_CUR_REQ:
        status = CyU3PUsbGetEP0Data (2, &WrBuff[0], &readCount);
CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness set cur %d\n",__LINE__,WrBuff);
return status;
break;


case CX3_USB_UVC_GET_MIN_REQ:
WrBuff[0] = Brightness.MinVal;
        CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness get Min %d\n",__LINE__,WrBuff);
break;
case CX3_USB_UVC_GET_MAX_REQ:
WrBuff[0] = Brightness.MinVal;
        CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness get Max %d\n",__LINE__,WrBuff);
break;
case CX3_USB_UVC_GET_RES_REQ:
WrBuff[0] = Brightness.Res;
        CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness get RES %d\n",__LINE__,WrBuff);
break;
case CX3_USB_UVC_GET_INFO_REQ:
WrBuff[0] = Brightness.Info;
        CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness get INFO %d\n",__LINE__,WrBuff);
        break;
case CX3_USB_UVC_GET_DEF_REQ:
WrBuff[0] = Brightness.DefaultVal;
        CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness get default %d\n",__LINE__,WrBuff);
break;
case CX3_USB_UVC_GET_LEN_REQ:
WrBuff[0] = 2;
        CyU3PDebugPrint(4,"\r\n Line:%d UVC brightness get len %d\n",__LINE__,WrBuff);
break;
default:
CyU3PUsbStall(0,CyTrue,CyFalse);
break;


}
status = CyU3PUsbSendEP0Data(2,(uint8_t*)&WrBuff);
if (status != 0)
{
CyU3PDebugPrint(4,"\n\r Send EP0 Data failed = 0x%X", status);
}


return status;


}


#endif























 

 

关于其他必要的变量定义和函数声明,请参考附件工程。编译工程并下载到Demo板中,在E-cam viewer属性面板中我们可以看到 亮度控制已经使能。

BaiduShurufa_2019-6-13_14-1-10.png

 

更多细节信息,请参考附件工程。

添加其他控制属性的步骤和亮度控制的步骤方法一致,这里就不再重复。

在前面三篇中,我们学习了如何选定适用于 CX3 的Image sensor/ISP 、如何构建 UVC 工程模板,以及一些调试 CX3 UVC 应用的基本方法。

在本篇笔记中,我们将会对前述的调试的笔记进行回顾和补充。为方便说明和理解,我们会按照第二篇学习笔记,采用 CX3 配置向导生成工程模板,在 Denebola 板上进行演示。如未另外说明,本笔记涉及到的 函数名、变量名、文件名等对应于附件工程。

 

  • 关于配置工具中参数的说明

首先我们熟悉下 CX3 配置工具的界面、参数的含义以及如何进行正确配置。

BaiduShurufa_2019-6-12_16-2-47.png

 

 

 

 

BaiduShurufa_2019-6-12_16-7-31.png

 

用户可以参考如上两幅截图,了解配置工具界面以及涉及到的参数说明。其中,sensor 部分的参数需要和 sensor 的技术人员确认准确。配置工具会根据用户输入的参数,判断输入的 CX3 端的 PLL 参数是否与之匹配。如果不匹配,则会出现警告,用户需要根据警告信息修正对应的参数,直到工具没有报错为止。

用户可以看到,很多参数都是 具有 范围的,即 最小值 和最大值,并不是唯一值。也就是说,对于某个分辨率的配置,可行的参数并不是唯一的一组,一般会有不同的几组。

 

  • 关于固件调试的方法

前面我们提到过,在调试 CX3 固件时,需要首先确保 CX3 摄像头在连接到主机端后,能够正确枚举为一个 UVC 设备。默认的情况下,在系统上电后,会执行CyCx3UvcAppInit()函数。此函数会初始化 必要的硬件模块、注册设备描述信息、配置端点、DMA 以及初始化 MIPI CSI 接口。需要保证CyCx3UvcAppInit 成功执行并返回。

用户可以用 BUS HOUND、USBlyzer,UART terminal等软件工具或者 硬件的 USB 协议分析仪抓取 USB通信判断函数执行过程和结果。此时,在设备管理器里,用户应当能看到名为 CX3-UVC 的设备。如果没有显示或者有黄色感叹号,一般是因为主机不能正确获取描述符或者回复的描述符不正确,需要着重进行检查。

BaiduShurufa_2019-6-12_14-49-23.png

 

当用户在主机端用 看图软件(MPC-HC、E-cam viewer 或者Amcap 等软件)打开相机并选择分辨率后,固件会运行到 CyCx3UvcAppHandleSetCurReq() 函数 执行CyCx3UvcAppImageSensorSetVideoResolution() 函数。这个函数的输入参数是 frame index, 这个数值其实是对应到描述符文件 cycx3_uvcdscr.c 里定义的 frame 的index。

BaiduShurufa_2019-6-12_15-7-3.png

此处的固件只配置了一个 分辨率,所以index 为1。如果用户手动添加新的分辨率,请注意index 的值需要是正确的。

 

回到CyCx3UvcAppImageSensorSetVideoResolution() 函数,这个函数根据选择的 分辨率 的序号对 MIPI CSI 接口和 sensor 进行配置,此处需要确保 这两处的配置正确。

对于 MIPI CSI 接口,用户可以调用 CyU3PMipicsiQueryIntfParams() 函数读回配置参数,检查是否和固件里配置的一致。

对于 sensor 或者 ISP,可以调用 I2C 读函数 读回写出的所有寄存器,与写出的参数进行比较,确保所有的寄存器都已正确配置。

 

配置完成后,sensor 或者 ISP 则会输出信号,使用示波器对信号进行检查(详见第三篇笔记),确保CX3 端信号解析正确。

 

另外,可以使用 UART 接口提供 debug 信息。附件工程定义了 宏 PRINT_FRAME_INFO, 用户可以查看

 

#ifdef PRINT_FRAME_INFO
...
...
#endif

 

部分的代码已获知细节。特别的,附件固件在 主线程中循环打印 frame相关信息。

/*For video streaming application of higher FPS refrain from using this debug print or try to reduce the print information*/
CyU3PDebugPrint(4,"\n\rProd = %d Cons = %d  Prtl_Sz = %d Frm_Cnt = %d Frm_Sz = %d B", TxCountflag, RxCountflag, PartialBufSize, FrameCount, ((TxCountflag*CX3_UVC_DATA_BUF_SIZE)+PartialBufSize));
Printflag = 0;


if (fpsflag == 1)
{
fps = 30000/(time1 -time0); //FPS calculate using time difference for 30 frames
CyU3PDebugPrint(4,"\n\rTimeDiff = %d ms FPS = %d", (time1 -time0), fps);
fpsflag = 0;




}

 

 

此处需要检查打印的 Prod 是否等于 Cons 的数量,Partial 包的大小为每一帧最后一个包的大小,这个值需要稳定不变(在分辨率没有切换时),FrameCount需要连续,没有丢帧。((TxCountflag*CX3_UVC_DATA_BUF_SIZE)+PartialBufSize)是计算的每一帧的大小,这个值需要与设定的分辨率大小一致。

 

注意,不要在 DMACallBack 函数里调用任何的UART 打印函数。

 

  • 其他相关的KBA 或者 论坛帖子

CX3 视频时间参数解析 – KBA226779 (ZH)

How to configure the MIPI Receiver in CX3 ?

How to configure CX3 MIPI receiver configuration for streaming RAW10 4096x3072 @ 10 fps ?

Streaming RAW10 Format Input Data to 16/24-bit Output Format in CX3 MIPI CSI-2 - KBA224387

Invalid Sequence Error in Multi-Channel Commit Buffer - KBA218830

CX3, i2c , 2-bytes address, 2-bytes data

经过了第二篇笔记的学习,用户可以自行创建出一个支持视频流传输的UVC工程,其中 具体的 sensor/ISP 配置部分需要用户将获得的参数写入到工程框架中。但是,生成的工程下载到用户的硬件板中,并不是每次都能正确地出图。本篇笔记介绍在这种情况下,如何排查和解决这种问题。

 

从大的方面来讲,可以从硬件软件(固件,下同)两个方面进行排查。

 

首先来讲硬件方面可能的原因。

  • USB 部分原理图设计。主要检查 CX3 的 USB3.0 的 SSRX 和 SSTX 引脚是否正确地连接到了板子上的 USB 接口引脚上。 如果硬件设计中采用标准 USB 插座(这里特指母座,下同)和线缆,则 CX3 的 SSRX+/-  引脚需要接到 USB 插座的 SSRX+/- 引脚上(正负可交换),CX3 的 SSTX+/- 引脚需要接到 USB插座的SSTX+/-引脚上(正负可交换)。如果这里连接错误,则会导致 下载固件后 CX3 不能正确枚举为USB3.0 设备。

 

  • USB 部分PCB设计。关于这一部分的细则,用户可以参考AN70707,其中包含了应当遵守的设计细则。

 

  • PCB 板供电部分。用户需要确保上电后,各个电压域都稳定可靠。采用示波器对电压的波形和幅值进行检查。

 

  • 时钟部分。一般的,CX3需要 一个晶振或者时钟源提供必要的时钟输入,sensor 或者 ISP 同时也需要相应的时钟。用户需要检查这两种时钟是否都正常工作。另外,根据 CX3 的 datasheet, CX3 的 MCLK 可以对外提供时钟输出给 sensor。但是由于各种原因,即使在开发测试环节,也不建议使用此引脚。建议用户为sensor 设计独立可靠的时钟电路。

 

  • 检查是否正确枚举为USB3.0。因为 720P 和 1080P 的分辨已经极为常见,用户也通常以此分辨率入手搭建UVC相机,但是一般这都需要 CX3 工作在 USB3.0 模式下。经常的,CX3 的配置工具生成的代码中并没有 USB2.0 模式下的描述符信息和配置代码(如下图)。如果由于某些硬件设计原因,CX3无法枚举为 USB3.0 的设备,也就无法完成必需的初始化和视频推流。

BaiduShurufa_2019-4-2_14-20-4.png

Fig.1 USB2.0 描述符不可用的提示

 

  • 检查 CX3 datasheet中标明的 DNU 引脚是否接地。datasheet 中注明 DNU 的引脚需要悬空,禁止接地或高电平。以下的引脚禁止接地或高电平。

Table.1 CX3 DNU pins list

No.
Pin #Note

1

F10DNU
2F9DNU
3F7DNU
4G10DNU
5G9DNU
6F8DNU
7H10DNU
8H9DNU
9J10DNU
10H7DNU
11K11DNU
12L10DNU
13K10DNU
14K9DNU
15G7DNU
16G8DNU
17H8PCLK(Clock output from bridge)
18G6Hsync(Horizontal sync)
19H5Vsync(vertical sync)
20F1INT#
21K2DNU
22J4DNU
23K1DNU
24J2DNU
25J3DNU
26J1DNU
27H2DNU
28H3DNU

 

 

接下来谈谈固件方面可能的原因。

  • I2C 接口相关检查。一般的,CX3 会通过 I2C 接口将必需的配置参数写入到 sensor 中,用户需要确保这一步正确执行。首先,需要检查固件中是否设置了正确的 I2C 设备地址。因为很多 sensor 具有不止一个 I2C 地址,需要特别注意当前有效的地址是什么。其次,需要确保 sensor 正确进行了初始化并且 I2C 接口准备就绪,可以进行 I2C 通信。曾经有一个实际案例,sensor 在上电后 NAK 了所有的 I2C 写命令。通过查看datasheet,得知 sensor 的某个引脚为高,使得 sensor 处于 I2C 不可访问的状态。通过在固件中将此引脚拉低,使得 I2C 可写,解决了问题。最后,需要确保所有的 I2C 写命令被 sensor ACK,即全部写入成功。此处用户可以使用 逻辑分析仪 抓取整个过程中的 I2C 通信数据,与已知的 配置参数对比即可得到结果。也可以在固件中的 I2C 写命令后面添加 I2C 读命令,将寄存器中写入的值读取回来进行对比。

 

  • 检查 sensor 输出信号。正常来讲,在 CX3 通过 I2C 接口写入配置参数后,sensor 开始输出信号。用户可以用示波器检查 sensor 的 MIPI Data、Clock的输出是否符合预期。下图是实际测量的 sensor MIPI Data 引脚上的波形,光标 a 和 b之间代表一帧图像数据。此处,光标 a 和 b 之间的时间差是 33 ms,对应帧率为 30 fps。此处示波器的水平时间尺度一般在 10-20 ms左右,暂时只需要关注波形的轮廓,不必探究信号的细节。这里Data 是差分信号,可以用差分探头测量信号,也可以用普通的单端探头测量(下图即为单端测量结果)。

040327_022348.jpg

Fig.2 Sensor  MIPI data 引脚波形

相应的,也需要确认Clock 信号正确输出。这里 clock 可能有不同的形式,分别叫做 continuous(free running) 模式 和 gate 模式。关于 continuous 和 gate 模式,可 以 参照Fig.2 进行理解。从 Fig 2 可以看到,sensor 并非持续不断地输出数据,而是在一段时间输出后暂停,稍后继续输出。这种模式可以称为 gate 模式。MIPI clock 引脚也可以按照这种模式输出时钟信号,称为 gate 模式 clock信号。Gate 模式的  clock 信号与Fig.2 中的 data 信号有基本一致的信号波形,此处不再重复。而与之相反的模式称为 continuous 模式,即 clock 信号在上电后持续输出。此时 clock 的波形如 Fig.3, 为带有直流分量的,峰峰值大概100-200 mV的信号,需要调节示波器垂直分辨率仔细观察。

微信图片_20190321173750.jpg

Fig.3 Continuous 模式 clock 信号

     此处建议用户将 sensor 的 clock 设置为 gate 模式。

 

  • 检查描述符部分是否正确。一般采用 CX3 配置工具生成的固件,其中的描述符部分是正确的。如果用户基于其他工程修改,需要检查对应的描述符结构体是否正确。

 

  • 检查Probe描述信息是否正确。在系统上电后,host 会通过probe control 命令获知当前的 图像格式、分辨率、帧率以及每秒钟最大传输字节数等信息,需要确认此处 host 所获取的信息正确。可以通过 UART 打印输出相关的 log 信息辅助检查。另外,也可以用BUS HOUND, LeCory 或者 Ellisys 的 USB 协议分析仪抓取USB数据包进行分析。

 

  • 检查 MIPI 解析输出信号。一般的,当 CX3 连接到主机并且与主机之间正确完成枚举阶段的信息沟通后,就会在主机端的设备管理器呈现为USB相机。用户在 host 端打开看图软件,用其打开相机设备并且选择一种图像格式和分辨率的之后,CX3 会通过 I2C 接口像 sensor 写入相应的配置参数。之后 sensor 开始输出 MIPI 数据,CX3 的MIPI block 会解析输入的MIPI数据,并通过 H5/H8/G6 三个引脚输出内部使用的控制信号。CX3 内部的状态机根据这三个控制信号进行工作,这也是前面我们提到 禁止这三个引脚接固定电平的原因。 显而易见,将这三个引脚引出到 TEST 点将会极大地有益于 Debug 工作。因此,强烈建议用户将这三个引脚引出到测试点。 如下附图,为正常的PCLK、Vsync和Hsync 信号。

scope_3.png

Fig.4 Correct PCLK,Vsync and Hsync

scope_4(H_active).png

Fig.5 Zoom in of correct PCLK,Vsync and Hsync

 

  • 添加 UART信息打印。当用户测量到如上的信号并且还是不能正确得到视频流,可以在固件中添加相应的 UART 打印语句输出相关的 log 以便分析。注意,此处禁止用户在 DMA callback 函数调用 UART 打印语句,因为这样会阻塞正常的视频传输。

 

以上即为 CX3 UVC 开发阶段常见的 debug 的方法。

根据 基于CX3的UVC摄像头应用学习笔记-一(CX3 简介) ,用户可以选择一款适用于CX3的Image sensor 或者 Image ISP。本篇文章讨论如何利用 EZ-USB SDK 内置的CX3配置工具生成新的工程模板。

 

CX3 配置向导是一个图形化的工具,用户不需要写任何代码,即可从0开始建立一个可用的UVC工程。下面介绍详细的步骤。

  • 在SDK中点击相应的图标,如下图所示。

  • 在弹出的对话框中,选择Create a Configuration with Basic Settings 并输入相应的工程名称。

  • 点击 Finish。这时用户可以看到 内容为空的 Image sensor 配置窗口。

  • 在 Image sensor configuration 标签页,输入所需要的参数。这里,示例输入 Sensor 名称 为 OV5640,输入的MIPI信号为YUY2,CX3内部采用 16 bit接口传输。分辨率为1920*1080,帧率 30 fps。MIPI CSI clock 是315 MHz, 采用  2 lane传输。 用户可以根据实际情况输入或选择相应的参数。

 

  • 输入以上的sensor相关的参数后,点击 CX3 Receiver configuraion 标签页,将会看到 如下的窗口。从这里可以看到,刚才输入的参数位于窗口的左侧并且为灰色不可改。如果需要修改,则需要返回到上一标签页进行更改,本页只能编辑 CX3 MIPI 模块相关的参数。这里,用户需要参考 CX3 TRM 了解CX3内部的PLL的构成。这里,配置工具会根据输入的 sensor 参数,判断用户配置的参数是否合理,如果不合理,则会出现报错信息。用户需要调整参数以确认没有报错信息。

  • 在输入所有必须的参数,并且工具没有报错信息以后。依次点击右侧的标签保存生成的几个文件。

  • 保存后,可以在左侧的工程浏览器中看到,相应的文件已经保存并且包含到工程下。下图中,cyu3imagesensor.c 及其相应的.h文件用于具体实现对sensor 的配置。或者是说,这两个文件提供了配置sensor所必需的接口函数的实现。但是,具体的配置内容是空缺的。此时用户需要将sensor的配置参数填充到  cyu3imagesensor.c 中相应的结构体中。当然,这里用户同样需要修改默认的I2C设备地址为实际的地址。

BaiduShurufa_2019-2-22_11-32-21.png

BaiduShurufa_2019-2-22_11-32-10.png

  • 此处需要注意,按照以上的流程产生的工程,默认引用了 cy_ov5640.a 的库。如果工程中定义的配置分辨率的函数名又恰好与 OV5640.a 中已定义的函数重名,则CX3会执行库中的实现,而并非执行cyu3imagesensor.c 定义。因此,这里建议用户取消 对 cy_ov5640.a 的引用。

BaiduShurufa_2019-2-22_11-14-29.png

  • 完成以上的步骤后,编译工程。正常的话,会得到相应的Img文件。

在用户安装完成 EZ-USB SDK 后,可以在安装目录下看到,Cypress 已经预置了基于四种不同型号的 Image sensor 应用代码。用户可以在这些工程的基础上进行研究和修改,在对固件有了一定的掌握后,可以选择其他型号的 Image Sensor 或者 ISP。本篇文章讨论如何选取适配于 CX3 的 Image sensor,或者 Image ISP 等。

 

根据 CX3 的数据手册(请从https://www.cypress.com/part/cyusb3065-bzxi  获取最新版本的数据手册),CX3 为一款支持 MIPI CSI-2 协议的 USB3.0 接口的设备端控制芯片。MIPI 模块工作在 RX 模式,即 CX3 从 MIPI 接口接收数据,外部的 image sensor 或者 ISP 工作在 MIPI TX 模式,将数据传送给 CX3.

 

判断一款 Image sensor 或者 Image ISP 是否与 CX3 适配,需要考察以下几点

  • MIPI CSI-2 PHY类型

MIPI CSI-2 协议中定义了 PHY 层的规范,目前已有三种类型,包括 D-PHY,C-PHY 和 M-PHY 。CX3 支持 MIPI D-PHY,因为 D-PHY 和 C-PHY 以及 M-PHY不兼容,所以首先需要确认 Image sensor 是否支持 D-PHY。

  • 关于数据速率

目前 CX3 支持的最大数据吞吐速率为 2.4 Gbps,单 lane 的最大速率为 1 Gbps。即,当使用 1 lane时,每lane 1 Gbps 共计 1 Gbps. 当使用 2 lane时,每lane 1 Gbps共计 2 Gbps。当使用 3 lane 时,每 lane 800 Mbps 共计 2.4 Gbps。当使用 4 lane 时,每 lane 600 Mbps 共计 2.4 Gbps。用户需要计算,CX3 是否满足应用场景所要求的数据传输速率。

  • 关于支持的格式

CX3 的数据手册和 TRM 中都有介绍了 CX3 所支持的输入格式,用户可以查看对应的章节以确认。

 

一般来说,符合以上几点的 Image sensor 或者 ISP 可以与CX3 对接,实现 UVC的应用。

     This blog is intended to make a brief introduction to profiling support of ThreadX in FX3/CX3 based application. Cypress has built four variants of buliding configurations in all the example firmwares and these demos are released to customer in latest version of EZ-USB SDK.  The configurations are

 

  1. FX3_debug: This is  the standard debug version of the firmware. This is built at compiler optimization level O0, and performs sanity checks on the parameters passed into the API.
  2. FX3_release:This is the standard release version of the firmware. This is built at compiler optimization level O3, and only has the minimal parameter validity checks required to prevent memory error (NULL pointer access etc.).
  3. FX3_profile_debug:This is a profiling enabled version of the fx3_debug library. This version enables collection and reporting of statistics on the RTOS objects used by the FX3 firmware. It also allows the user to register FX3 GPIOs which can be used for indication of RTOS usage.
  4. FX3_profile_release:This is a profiling enabled version of the fx3_release library. The profiling support is similar to that in the fx3_profile_debug library.

 

For some projects whcih are extracted from previous version of EZ-USB SDK, FX3_profile_debug and FX3_profile_release settings may not be available. Follow the steps below to add profile_debug and profile_release settings into projects.

  • Right click the project name on the project explorer, then choose Build Configurations and then choose Manage.

   1.png

  • Create a new configuration.

 

  • Fill up the blanks of name and description. Here we have import an example project BulkLpAutoCpp in advance which has profile_debug and profile_realease configurations. It could be convenient for users to import configurations from other projects. Choose Import from projects and select BulkLpAutoCpp>ProfileDebug

  • Save the change and set ProfileDebug as the active build option. Profiling APIs are now available in firmware.

 

The profiling-enabled builds of the FX3 library collect a wide range of usage statistics on the RTOS objects used in a firmware application. These statistics are obtained through the APIs below.

No.
API name
Description
1CyU3PThreadPerfGetGet statistics about a specific thread
2CyU3PThreadSystemPerfGetGet overall statistics about all threads used in the application (including SDK internal driver threads)
3CyU3PTimerPerfGetGet statistics about a specific RTOS timer.
4CyU3PTimerSystemPerfGetGet overall statistics about all RTOS timers.
5CyU3PMutexPerfGetGet statistics about a specific Mutex object.
6CyU3PMutexSystemPerfGetGet overall statistics about all Mutex objects.
7CyU3PEventPerfGetGet statistics about a specific Event group.
8CyU3PEventSystemPerfGetGet overall statistics about all Event groups.
9CyU3PQueuePerfGetGet statistics about a specific Message Queue.
10CyU3PQueueSystemPerfGetGet overall statistics about all Message Queues.
11CyU3PDeviceGetCpuLoadGet total CPU loading (in percentage) from start of RTOS execution
12CyU3PDeviceGetThreadLoadGet CPU loading (in percentage) due to a specific thread from start of RTOS execution.
13CyU3PDeviceGetDriverLoadGet CPU loading (in percentage) due to all FX3 driver threads from start of RTOS execution.

 

 

Refer to FX3 API guide to get detailed information about how to use these APIs. The example firmware BulkLpAutoCpp is attached for reference.