CY4521 Read TYPE-C cable E-marker IC VDM data

Announcements

Live Webinar: USB-C adoption. Simple & Cost-efficient solutions | April 18th @9am or 5pm CEST. Register now !

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
WiCh_3149431
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Our project need read TYPE-C cable E-marker IC VDM data like below picture, now we are work on CY4521.

WEB-U2 E-marker.jpg

We modify FW can read ID Header & Cert Stat correct, but the VDM Header the same as ID Header, Product VDO & Cable VDO the same as Cert Stat as below picture. There are not correct.

E-marker.jpg

This is my source code for send VDM data via UART. Please Cypress help me correct read all VDM data. Please let me know if you need more information to help us fix this problem, thanks a lot.

void get_cable_vdo (void)

{

    char temp[64];

    tPD_DO cbl_vdo_get;

    tPD_DEV_POLICY_STATUS *PTR;

     if(is_emca_present())

    {

        PTR = get_dev_policy();

        SW_Tx_UART_1_PutChar('K');

        sprintf(temp, "\nVDM Header = %x\n", PTR->cbl_vdo.std_vdm_hdr);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));       

        sprintf(temp, "\nID Header VDO = %x\n", PTR->cbl_vdo.std_id_hdr);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "\nCert Stat VDO = %x\n", PTR->cbl_id_header_vdo.std_cert_vdo);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "\nProduct VDO = %x\n", PTR->cbl_id_header_vdo.std_prod_vdo);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "\nCable VDO = %x\n", PTR->cbl_id_header_vdo.std_cbl_vdo);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

    }

}

0 Likes
1 Solution

Hi,

CCG2 receives all the VDOs of SOP prime Discover ID from cable. However, the PD stack does not expose this information outside. It just exposes cable VDO & cable id header VDO.

All data objects (DO) are 4 byte wide. Vendor data object (VDO) is one such type of data object. This union is used to store the data object and access it based on specific types on need basis. You can see that cable VDO is accessed within dp_source.c to check for the product type. If cable VDO is accessed using a different type (say std_cert_vdo), then it would not have correct meaning.


Regards,

Muthu

View solution in original post

0 Likes
17 Replies
WiCh_3149431
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

By the way, when CY4521 type-C receptacle plug with a TYPE-C cable with E-marker IC, send_discover_id(void) function always return false, that I can not get E-marker VDM data, what should I do to make this function return true to let me get E-marker VDM data?

bool send_discover_id(void)

{

    /* Store state of operation. */

    //pd_command_issued = true;

    //pd_command_completed = false;

    /* Format the command parameters.

    Single DO with standard Discover_ID command to SOP controller.

    Timeout is set to 100 ms.

    */

    cmd_buf.cmd_sop = SOP;

    //cmd_buf.cmd_do[0].std_vdm_hdr.cmd = STD_VDM_DSC_ID_CMD; //0xFF008001;

    cmd_buf.cmd_do[0].val = STD_VDM_DSC_ID_CMD ;

    cmd_buf.no_of_cmd_do = 1;

    //cmd_buf.timeout = 100;

    /* Initiate the command. Keep trying until accepted. */

    //while (dpm_pd_command(port, DPM_CMD_SEND_VDM,

    //        &cmd_buf, pd_command_cb) != CCG_STAT_SUCCESS)

    //{

        /* Can implement a timeout/abort here. */

    //    if (abort_cmd)

    //        return false;

    //}

  

    if (handle_pd_command(DPM_CMD_IDENTITY_DISCOVERY, &cmd_buf, &pd_command_cb))

    {

        SW_Tx_UART_1_PutChar('T');

        /* Command has been queued. We cannot block for callback here. */

        return true;

    }

    else

    {

        SW_Tx_UART_1_PutChar('F');

        /* Command has been queued. We cannot block for callback here. */

        return false;

    }

    //handle_pd_command(STD_VDM_DSC_ID_CMD, &cmd_buf, &pd_command_cb);

    //handle_pd_command(DPM_CMD_SVIDS_DISCOVERY, &cmd_buf, pd_command_cb);

    //handle_pd_command(DPM_CMD_MODES_DISCOVERY, &cmd_buf, pd_command_cb);

}

0 Likes

We modify get_cable_vdo (void) as below:

void get_cable_vdo (void)

{

    char temp[64];

    tPD_DO cbl_vdo_get;

    tPD_DO *PTR;

    tPD_DEV_POLICY_STATUS* dpm_p;

    int i;

   

    if(is_emca_present())

    {

        dpm_p = get_dev_policy();

        PTR = &(dpm_p->src_pdo[0]);

        //PTR = get_dev_policy()->cbl_id_header_vdo;

       

        //SW_Tx_UART_1_PutChar('K');

        //cbl_vdo_get.std_cbl_vdo.cbl_fw_ver = get_dev_policy()->cbl_vdo.std_cbl_vdo.cbl_fw_ver;

        //cbl_vdo_get.std_cbl_vdo.vbus_cur = get_dev_policy()->cbl_vdo.std_cbl_vdo.vbus_cur;

        //sprintf(temp, "\nver = %d\n", cbl_vdo_get.std_cbl_vdo.cbl_fw_ver);

        //SW_Tx_UART_1_PutArray(temp, strlen(temp));

        //sprintf(temp, "\ncur = %d\n", get_dev_policy()->cbl_vdo.std_cbl_vdo.vbus_cur);

        //SW_Tx_UART_1_PutArray(temp, strlen(temp));

       

        for (i=0; i<MAX_NO_OF_PDO; i++)

        {

            sprintf(temp, "\n%x\n", PTR->val);

            SW_Tx_UART_1_PutArray(temp, strlen(temp));

            PTR++;

        }

       

        PTR = &(dpm_p->snk_pdo[0]);

        //PTR = get_dev_policy()->cbl_id_header_vdo;

       

        //SW_Tx_UART_1_PutChar('K');

        //cbl_vdo_get.std_cbl_vdo.cbl_fw_ver = get_dev_policy()->cbl_vdo.std_cbl_vdo.cbl_fw_ver;

        //cbl_vdo_get.std_cbl_vdo.vbus_cur = get_dev_policy()->cbl_vdo.std_cbl_vdo.vbus_cur;

        //sprintf(temp, "\nver = %d\n", cbl_vdo_get.std_cbl_vdo.cbl_fw_ver);

        //SW_Tx_UART_1_PutArray(temp, strlen(temp));

        //sprintf(temp, "\ncur = %d\n", get_dev_policy()->cbl_vdo.std_cbl_vdo.vbus_cur);

        //SW_Tx_UART_1_PutArray(temp, strlen(temp));

       

        for (i=0; i<MAX_NO_OF_PDO; i++)

        {

            sprintf(temp, "\n%x\n", PTR->val);

            SW_Tx_UART_1_PutArray(temp, strlen(temp));

            PTR++;

        }

       

        PTR = &dpm_p->cbl_id_header_vdo;

        sprintf(temp, "\ncbl_id_header_vdo = %x\n", PTR->val);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

       

        PTR = &dpm_p->cbl_vdo;

        sprintf(temp, "\ncbl_vdo = %x\n", PTR->val);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

       

        check_emca = 0;

    }

}

We get below from UART Tx, the id_header_vdo is correct, please Cypress help us or give us instructions on how to read the other E-marker data correctly.

uart2.jpg

0 Likes

Right now we are make sure cbl_id_header_vdo = 18002109 and cbl_vdo = 82832 are correct. Please Cypress specify where we can or how to get E-marker VDM Header, Cert Stat VDO, Product VDO data correctly.

0 Likes

Is passive cable only has ID Header VDO and Cable VDO in the E-marker IC. The active cable has extra VDM Header, Cert Stat VDO, Product VDO? Could Cypress help answer question?

0 Likes

We keep try send_discover_id(), but why handle_pd_command(cmd_typ, &cmd_buf, pd_command_cb) in send_discover_id() always failed? Please Cypress can answer our question? This is our source code:

tCMD_BUF cmd_buf;

#define PD_SVID_VDO_START_IDX          (2u)

#define STD_VDM_DSC_ID_CMD              (0xFF008001u)

#define STD_VDM_DSC_SVID_CMD            (0xFF008002u)

static void pd_command_cb(tRES_STATUS status, uint32_t* d_obj)

{

    /* Response received. Check handshake. */

    //response = vdm_ptr->dat[0].std_vdm_hdr.cmd_type;

  

    char temp[64];

    uint32_t i ;

    uint32_t count ;

    uint32_t response ;

    tPD_DO* obj = (tPD_DO*)(&d_obj[1]);

    response = obj->std_vdm_hdr.cmd_type;

    count = GET_PD_HDR_CNT(d_obj[PD_HDR_IDX]);

    //timer_stop(DP_SRC_RETRY_TIMER);

  

    SW_Tx_UART_1_PutString("call back");

    if(status == RES_ACKED)

    {

        SW_Tx_UART_1_PutString("ack");

    }

    else

    {

        SW_Tx_UART_1_PutString("nack");

        return;

    }

  

    for(i = 0 ; i <= count ; i++)

    {

        sprintf(temp, "\n%x\n", d_obj);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

    }

}

bool send_discover_id(int cmd)

{

    /* Store state of operation. */

    //pd_command_issued = true;

    //pd_command_completed = false;

    /* Format the command parameters.

    Single DO with standard Discover_ID command to SOP controller.

    Timeout is set to 100 ms.

    */

  

    tCMD_TYPE cmd_typ;

  

    if (cmd == STD_VDM_DSC_ID_CMD)

        cmd_typ = DPM_CMD_IDENTITY_DISCOVERY;

    else if (cmd == STD_VDM_DSC_SVID_CMD)

        cmd_typ = DPM_CMD_SVIDS_DISCOVERY;

  

    cmd_buf.cmd_sop = SOP;

    //cmd_buf.cmd_do[0].std_vdm_hdr.cmd = STD_VDM_DSC_ID_CMD; //0xFF008001;

    cmd_buf.cmd_do[0].val = cmd;

    cmd_buf.no_of_cmd_do = 1;

    //cmd_buf.timeout = 100;

    /* Initiate the command. Keep trying until accepted. */

    //while (dpm_pd_command(port, DPM_CMD_SEND_VDM,

    //        &cmd_buf, pd_command_cb) != CCG_STAT_SUCCESS)

    //{

        /* Can implement a timeout/abort here. */

    //    if (abort_cmd)

    //        return false;

    //}

  

    if (handle_pd_command(cmd_typ, &cmd_buf, pd_command_cb))

    {

        cb_status = 1;

        SW_Tx_UART_1_PutString("send id discovery ok");

        /* Command has been queued. We cannot block for callback here. */

        return true;

    }

    else

    {

        SW_Tx_UART_1_PutString("send id discovery fail");

        /* Command has been queued. We cannot block for callback here. */

        return false;

    }

}

void check_ra_status(void)

{

#if LISZ_DEBUG

    SW_Tx_UART_1_PutChar('d');

#endif

    if((get_cc_status() == RP_CC1_OPEN_CC2_RA))

    {

#if LISZ_DEBUG

    SW_Tx_UART_1_PutChar('a');

#endif      

        typec_cc(CC_CHANNEL_1,CC_RD,CC_ENABLE);

//        turn_on_vconn(CC_CHANNEL_2);

    }

    if((get_cc_status() == RP_CC1_RA_CC2_OPEN))

    {

#if LISZ_DEBUG

    SW_Tx_UART_1_PutChar('b');

#endif

        typec_cc(CC_CHANNEL_2,CC_RD,CC_ENABLE);

//        turn_on_vconn(CC_CHANNEL_1);

    }

}

void get_cable_vdo (void)

{

    char temp[32];

    tPD_DEV_POLICY_STATUS *ptr;

    tPD_DO cbl_vdo_get;

    if(is_emca_present())

    {

        test = 2;

        ptr = get_dev_policy();

        cbl_vdo_get.std_cbl_vdo.cbl_fw_ver = get_dev_policy()->cbl_vdo.std_cbl_vdo.cbl_fw_ver;

        cbl_vdo_get.std_cbl_vdo.vbus_cur = get_dev_policy()->cbl_vdo.std_cbl_vdo.vbus_cur;

        sprintf(temp, "%d\n", cbl_vdo_get.std_cbl_vdo.cbl_fw_ver);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "%d\n", cbl_vdo_get.std_cbl_vdo.vbus_cur);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

    }

}

int main(void)

{

#ifndef CCG_FW_NO_BOOT

#ifdef CCG_CONFIG_TABLE

    /* Validate the configuration table. */

    if ((get_pd_conf()->table_sign != CY_PD_CONFIG_TABLE_SIGN) ||

        (get_pd_conf()->table_checksum != cy_pd_calc_checksum((uint8_t *)&get_pd_conf()->reserved0,

                                                              502)))

    {

        /* Jump back to the bootloader. */

        jump_to_boot(CY_PD_CONFIG_TABLE_INVALID_REASON);

    }

#endif /* CCG_CONFIG_TABLE. */

#endif

    /* Register function callback. */

    pe_register_psupply_ops(get_psource_ops());

    pe_register_psink_ops(get_psink_ops());

    pe_register_vdm_ops(get_vdm_ops());

    pe_register_pd_ops(get_pd_ops()) ;

    typec_register_psupply_ops(get_psource_ops());

    typec_register_psink_ops(get_psink_ops());

    /* Initialize the system. */

    system_init();

    /* Start the deep sleep is enabled. */

    timer_start(SYS_DEEPSLEEP_TIMER, get_pd_conf()->ec_init_period + SYS_DRP_DEEP_SLEEP_TIMER_PERIOD, NULL);

#if (HPI_CONFIGURATION == HPI_SUPPORTED)

    /* Device is initialized. Send a 'Reset Complete' event. */

    reg_space_update_response(STATUS_CODE_RESET_COMPLETE, 0);

    /* Emulate as DFP or UFP as per device type. */

    update_typec_skip_flag(1);

    /* Initialize the EC timer for HPI. */

    timer_start(SYS_EC_INIT_TIMER, get_pd_conf()->ec_init_period, NULL);

#else

    type_c_init();

#endif /* (HPI_CONFIGURATION == HPI_SUPPORTED) */

#if (APP_FW_LED_ENABLE == APP_FW_LED_ENABLED)

    timer_start(LED_TIMER_ID, LED_TIMER_PERIOD, led_timer_cb);

#endif /* APP_FW_LED_ENABLE */

    /* Enable system interrupts. */

    CyGlobalIntEnable;

#if LISZ_DEBUG

    SW_Tx_UART_1_Start();

    SW_Tx_UART_1_PutString("start");

#endif

  

    while (1)

    {

#if (HPI_CONFIGURATION == HPI_SUPPORTED)

        if(get_typec_bootup_flag() == false)

        {

            if(timer_is_running(SYS_EC_INIT_TIMER) == false)

            {

                type_c_init();

            }

            continue;

        }

    #endif /* (HPI_CONFIGURATION == HPI_SUPPORTED) */

      

        type_c_state_machine();

        pe_state_machine();

      

    #if (VCONN_SOURCE_CONFIGURATION == VCONN_SOURCE_CONTROL_ENABLED)

        auto_swaps_logic();

    #endif /* (VCONN_SOURCE_CONFIGURATION == VCONN_SOURCE_CONTROL_ENABLED) */

      

#ifndef CC_CONFIG_SINGLE_INC

        cbl_discovery();

#endif

#ifdef CCG_CONTROLLED_DP_SOURCE

        dp_state_machine();

#endif /* CCG_CONTROLLED_DP_SOURCE */

#if (HPI_CONFIGURATION == HPI_SUPPORTED)

        /* HPI handling. */

        handle_hpi();

#ifdef HPI_SET_TYPE_C_CONFIG_ENABLED_INC

    #if defined CFG_SRC_INC || defined  CFG_SRC_SNK_INC

        /* Check if a SET_TYPEC_CURRENT_LEVEL command is pending. */      

        if (gl_cur_level_update_request)

        {

            apply_typec_cur_level();

            gl_cur_level_update_request = false;

        }

    #endif /* CFG_SRC_INC || CFG_SRC_SNK_INC */

#endif /* HPI_SET_TYPE_C_CONFIG_ENABLED_INC */

        /* Check if a PORT DISABLE command is pending. */

        if (gl_port_disable_request)

        {

            gl_port_disable_request = false;

            disable_port();

        }

        /*

        * Check if go to deep sleep flag is set. This indicates that CCG has disabled TYPE C

        * and PD modules due to PORT_DISBALE command and is expected to stay in Deep Sleep.

        */

        if (gl_port_deep_sleep_enable)

        {

            if ((is_i2c_state_idle()) != false)

            {

                /*

                *  Only I2C need to be re-configured for wake-up.

                * But since this call is more code size efficient using this.

                */

                config_i2c_as_wakeup_source();

                CySysPmDeepSleep();

            }

        }

        else

#endif /* (HPI_CONFIGURATION == HPI_SUPPORTED) */

        {

#ifdef CFG_SRC_SNK_INC

            handle_drp_toggle();

#endif  /* CFG_SRC_SNK_INC. */

//LISZ            handle_deepsleep() ;

        }

    //LISZ for ROIN

  

    check_ra_status();

    get_cable_vdo ();

    if(is_emca_present())

    {

        send_discover_id(STD_VDM_DSC_ID_CMD);

    }

}

0 Likes

Hi,

Can you change send_discover_id's argument type to uint32_t?

Are you seeing any PD message sent over the CC lines? Can you provide CC trace?

Is the contract in place already?

BTW, regarding your first post on 9th May:

        sprintf(temp, "\nVDM Header = %x\n", PTR->cbl_vdo.std_vdm_hdr);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));      

        sprintf(temp, "\nID Header VDO = %x\n", PTR->cbl_vdo.std_id_hdr);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "\nCert Stat VDO = %x\n", PTR->cbl_id_header_vdo.std_cert_vdo);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "\nProduct VDO = %x\n", PTR->cbl_id_header_vdo.std_prod_vdo);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

        sprintf(temp, "\nCable VDO = %x\n", PTR->cbl_id_header_vdo.std_cbl_vdo);

        SW_Tx_UART_1_PutArray(temp, strlen(temp));

As you can see from tPD_DEV_POLICY_STATUS structure, cbl_vdo and cbl_id_header_vdo are of tPD_DO type. tPD_DO is an union of 4 byte wide. So, they represent cable vdo and cable id header vdo only. They cannot be used to print other VDOs like cert stat vdo or id header vdo, etc.

Regards,

Muthu

0 Likes

Thanks, Muthu. change send_discover_id's argument type to uint32_t, the result is still the same. I do not have CY4500 Protocol Analyzer, but I have this product (ChargerLab Power-Z KM001 USB Power Monitor/Trigger - quick look - YouTube ), it has PD Protocol Analyzer function, I am not familiar with it, I will try to familiar with it and post the CC trace, I also has Logic Analyzer can decode USB PD protocol.

Protocol Analyzer.jpg

0 Likes

Hi,

From the CC trace you have posted, there is no Good_Crc and Request in response to Src_Cap sent by source. So, until there is successful explicit contract (i.e., Src_Cap, Request, Accept, PS_Rdy flow), alternate mode commands cannot be sent.

Regards,

Muthu

0 Likes

Hi, Muthu:

Looks like the no.01 shows PD source send Discover Identity command to E-marker IC, the no.03 shows E-marker IC response for Discover Identity command, send back VDM Header, ID Header VDO, Cert Stat VDO, Product VDO and Cable VDO, but why we cannot read on FW, how to correct read them?

01.jpg

03.jpg

03-2.jpg

0 Likes

Hi,

Except cable VDO & cable id header VDO, other VDOs are not exposed outside the library.

Regards,

Muthu

0 Likes

Hi, Muthu:

Our source code is reference to Sending a DISCOVER_ID VDM on chapter 6.2.6.3 of CCGx SDK v3.0.2 UserGuide.

6.2.6.3.jpg

0 Likes

Hi, Muthu:

Are you sure that other VDOs are not exposed outside the library? But according to USB PD specification Revision: 3.0, the Discover Identity command should get response include all E-marker VDO.

Discover Identity Command response.jpg

0 Likes

Hi, Muthu:

If library only support Cable VDO & Cable id header VDO, why define the data structure for VDM Header, Cert Stat VDO and Product VDO in usbpd.h ?

    struct STD_VDM_HDR {

        uint32_t cmd                      : 5;

        uint32_t rsvd1                    : 1;

        uint32_t cmd_type                 : 2;

        uint32_t obj_pos                  : 3;

        uint32_t rsvd2                    : 2;

        uint32_t st_ver                   : 2;

        uint32_t vdm_type                 : 1;

        uint32_t svid                     : 16;

    }std_vdm_hdr;

    struct STD_CERT_VDO {

        uint32_t usb_cmpl                 : 20;

        uint32_t rsvd1                    : 12;

    }std_cert_vdo;

    struct STD_CBL_VDO {

        uint32_t usb_ss_sup               : 3;

        uint32_t sop_dp                   : 1;

        uint32_t vbus_thru_cbl            : 1;

        uint32_t vbus_cur                 : 2;

        uint32_t ssrx2                    : 1;

        uint32_t ssrx1                    : 1;

        uint32_t sstx2                    : 1;

        uint32_t sstx1                    : 1;

        uint32_t cbl_term                 : 2;

        uint32_t cbl_latency              : 4;

        uint32_t typec_plug               : 1;

        uint32_t typec_abc                : 2;

        uint32_t rsvd1                    : 4;

        uint32_t cbl_fw_ver               : 4;

        uint32_t cbl_hw_ver               : 4;

    }std_cbl_vdo;

0 Likes

Hi,

CCG2 receives all the VDOs of SOP prime Discover ID from cable. However, the PD stack does not expose this information outside. It just exposes cable VDO & cable id header VDO.

All data objects (DO) are 4 byte wide. Vendor data object (VDO) is one such type of data object. This union is used to store the data object and access it based on specific types on need basis. You can see that cable VDO is accessed within dp_source.c to check for the product type. If cable VDO is accessed using a different type (say std_cert_vdo), then it would not have correct meaning.


Regards,

Muthu

0 Likes

Hi, Muthu:

If so, we also has CY4541 kit, Does CY4541 FW library support read all E-marker VDM data? 

0 Likes

Hi, Muthu:

On #5 reply, the send_discover_id(int cmd) is try to read all E-marker VDM data without go through CCG2 library, would you please detail check the source code, let us know which part is wrong for read the other VDO data.

0 Likes

Hi William,

1. We also has CY4541 kit, Does CY4541 FW library support read all E-marker VDM data?

>> Yes. You can. You could get the E-marker VDM:

vdm_msg_info_t is struct holds received/sent VDM info.

vdm_msg_info_t *msg_p  = get_msg (port);

2. send_discover_id(int cmd)

You are correct that this function will send out discovery identity, but the retrieve back VDM is not out of lib.

Best Regards,

Lisa

0 Likes