- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Now,I can use the API of pd_phy_load_msg()and pd_phy_send_msg() send vdm message to EMCA, but I can not get EMCA ACK message.
Actually,EMCA have been send GOODCRC msg and VDM ACK msg (that msg check by CY4500),however, the program does not generate the RX interrupt signal and enters the interrupt processing function(pdss_intr0_handler()),which mean I can‘t use pd_phy_get_rx_packet() to get EMCA ACK MSG;
There are things need to be clear that :
1. I have been invoke pd_prot_rx_en() to enable RX interrupt;
2. my test chip is CYPD4126;
3. every time after sending VDM Discover ID message to EMCA, the program will generate TX interrupt (PDSS_INTR0_CRC_RX_TIMER_EXP),then invoke pdss_intr0_handler() to handle this interrupt ,I have no idea about why the TX interrupt is generated;
this is my test code:
static cc_state_t InitEmarkChannel(uint8_t port) {
uint8_t eMarkCommCha = 2u;
uint8_t eMarkVconnCha = 2u;
cc_state_t cc_state;
pd_typec_en_rp(port, CC_CHANNEL_1, RP_TERM_RP_CUR_DEF);
pd_typec_en_rp(port, CC_CHANNEL_2, RP_TERM_RP_CUR_DEF);
cc_state = pd_typec_get_cc_status(port);
if (cc_state.cc[CC_CHANNEL_1] == RP_RA) {
eMarkVconnCha = CC_CHANNEL_1;
eMarkCommCha = CC_CHANNEL_2;
} else if (cc_state.cc[CC_CHANNEL_2] == RP_RA) {
eMarkVconnCha = CC_CHANNEL_2;
eMarkCommCha = CC_CHANNEL_1;
}
(void)eMarkCommCha;
if (eMarkVconnCha < 2u) {
pd_typec_dis_rp(port, eMarkCommCha);
pd_typec_dis_rp(port, eMarkVconnCha);
pd_typec_en_rp(port, eMarkCommCha, RP_TERM_RP_CUR_3A);
pd_vconn_enable(port, eMarkVconnCha);
}
return cc_state;
}
#define GOODCRC_MSG_TYPE (1u)
#define VMD_DEFINED_TYPE (15u)
typedef union
{
uint32_t val;
struct MSG_HDR {
uint32_t msg_type : 5;//0:4 bit
uint32_t port_data_role : 1;// 5 bit
uint32_t spec_rev : 2;// 6:7 bit
uint32_t port_pwr_role : 1;//8 bit
uint32_t msg_id : 3;//9:11bit
uint32_t num_doj : 3;//12:14bit
uint32_t extended : 1;//15bit
uint32_t extendheader : 16;// 16:31 bit
} msg_hdr;
} phy_msg_header_t;
static void pd_phy_task(uint8_t port, uint16_t svid, uint8_t vdm_cmd, uint8_t* msg_id, sop_t sop){
uint8_t retries = 0;
uint8_t doj_size = 1;
phy_msg_header_t msg_header;
pd_do_t msg_doj;
msg_header.msg_hdr.extendheader = 0x0000;
msg_header.msg_hdr.msg_type = VMD_DEFINED_TYPE; // Vendor_Defined
msg_header.msg_hdr.num_doj = 1; // data object number(32 bits)
msg_header.msg_hdr.port_data_role = 0; // SOP* set 0
msg_header.msg_hdr.port_pwr_role = 0; // SOP: 0:UFP 1:DFP;SOP* is cable plug: 0 indicate DFP_UFP 1:cable
msg_header.msg_hdr.spec_rev = 2; // 2:spec_rev3 1:spec_rev2;
msg_header.msg_hdr.msg_id = *msg_id; // 0~7, increment after every send
msg_header.msg_hdr.extended = 0;
msg_doj.std_vdm_hdr.cmd = vdm_cmd; //discover modes:3 discover ID:1 Discover SVIDs:2
msg_doj.std_vdm_hdr.rsvd1 = 0;
msg_doj.std_vdm_hdr.rsvd2 = 0;
msg_doj.std_vdm_hdr.cmd_type = 0;
msg_doj.std_vdm_hdr.obj_pos = 0;
msg_doj.std_vdm_hdr.st_ver = 1;
msg_doj.std_vdm_hdr.vdm_type = 1;
msg_doj.std_vdm_hdr.svid = svid;
if (!pd_phy_is_busy(port)) {
pd_phy_load_msg(
port,
sop,
retries,
doj_size,
(uint32_t)msg_header.val,
false,
(uint32_t *)&msg_doj.val
);
pd_phy_send_msg(port);
*msg_id = *msg_id + 1;
if (*msg_id > 7) {
*msg_id = 0;
}
}
}
static void send_goodcrc(uint8_t port, uint8_t msg_id, sop_t sop, uint32_t spec_rev) {
uint8_t retries = 0;
uint8_t doj_size = 0;
phy_msg_header_t msg_header;
pd_do_t msg_doj = {0} ;
msg_header.msg_hdr.extendheader = 0x0000; // not extend msg
msg_header.msg_hdr.msg_type = GOODCRC_MSG_TYPE; // goodcrc
msg_header.msg_hdr.num_doj = 0; // data object number(32 bits)
msg_header.msg_hdr.port_data_role = 0; // SOP* set 0
msg_header.msg_hdr.port_pwr_role = 0; // SOP: 0:UFP 1:DFP; SOP* is cable plug: 0<=>DFP_UFP 1<=>cable
msg_header.msg_hdr.spec_rev = spec_rev; // 2:spec_rev3 1:spec_rev2;
msg_header.msg_hdr.msg_id = msg_id; // 0~7, increment after every send
msg_header.msg_hdr.extended = 0;
if (!pd_phy_is_busy(port)) {
pd_phy_load_msg(
port,
sop,
retries,
doj_size,
(uint32_t)msg_header.val,
false,
(uint32_t *)&msg_doj.val
);
pd_phy_send_msg(port);
}
}
#endif
#if 1
static pd_packet_extd_t pd_packet;
static uint8_t event_id;
static void pd_phy_cbk_func(uint8_t port, pd_phy_evt_t event){
// PD_PHY_EVT_TX_MSG_COLLISION, /**< Bus busy at message transmission. */
// PD_PHY_EVT_TX_MSG_PHY_IDLE, /**< Bus idle, ready for message transmission. */
// PD_PHY_EVT_TX_MSG_FAILED, /**< Message transmission was not successful. */
// PD_PHY_EVT_TX_MSG_SUCCESS, /**< Message transmission was successful. */
// PD_PHY_EVT_TX_RST_COLLISION, /**< Bus busy just before reset transmission. */
// PD_PHY_EVT_TX_RST_SUCCESS, /**< Reset transmission was successful. */
// PD_PHY_EVT_RX_MSG, /**< Message received. */
// PD_PHY_EVT_RX_MSG_CMPLT, /**< Message received and GoodCRC sent aka collision type 3. */
// PD_PHY_EVT_RX_RST, /**< Reset was received. */
// PD_PHY_EVT_FRS_SIG_RCVD, /**< FRS signal was received. */
// PD_PHY_EVT_FRS_SIG_SENT, /**< FRS signal was transmitted. */
// PD_PHY_EVT_CRC_ERROR /**< Message recieved with CRC error. */
pd_packet_extd_t* rx_pd_packet = NULL;
event_id = event;
switch (event)
{
case PD_PHY_EVT_RX_MSG:
rx_pd_packet = pd_phy_get_rx_packet(port);
if (rx_pd_packet != NULL) {
memcpy(&pd_packet, rx_pd_packet, sizeof(pd_packet_extd_t));
}
break;
case PD_PHY_EVT_TX_MSG_FAILED:
break;
case PD_PHY_EVT_TX_MSG_SUCCESS:
break;
default:
break;
}
}
#endif
int main()
{
uint32_t conf_addr;
uint8_t i;
/* Enable this to delay the firmware execution under SWD connect. */
#ifdef BREAK_AT_MAIN
uint8_t volatile x = 0;
while(x==0);
#endif /* BREAK_AT_MAIN */
#if (CYDEV_BCLK__SYSCLK__MHZ == 48)
/* Use the maximum number of flash access wait states when the CPU clock frequency is 48 MHz. */
CPUSS_FLASH_CTL = 0x13;
#endif /* (CYDEV_BCLK__SYSCLK__MHZ == 48) */
#if CCG_FIRMWARE_APP_ONLY
sys_set_device_mode (SYS_FW_MODE_FWIMAGE_1);
#else /* !CCG_FIRMWARE_APP_ONLY */
if ((uint32_t)&base_version < CCG_FW1_CONFTABLE_MAX_ADDR)
{
sys_set_device_mode (SYS_FW_MODE_FWIMAGE_1);
}
else
{
sys_set_device_mode (SYS_FW_MODE_FWIMAGE_2);
}
#endif /* CCG_FIRMWARE_APP_ONLY */
/* Validate the signature and checksum of the configuration table. */
conf_addr = (uint32_t)get_pd_config ();
if ((boot_validate_configtable ((uint8_t *)conf_addr) != CCG_STAT_SUCCESS) ||
(!app_validate_configtable_offsets()))
{
#if CCG_FIRMWARE_APP_ONLY
/* Can't do anything if config table is not valid. */
while (1);
#else /* !CCG_FIRMWARE_APP_ONLY */
/* Erase the firmware metadata so that this binary stops loading. */
if (sys_get_device_mode() == SYS_FW_MODE_FWIMAGE_1)
{
flash_row_clear (CCG_IMG1_METADATA_ROW_NUM);
}
else
{
flash_row_clear (CCG_IMG2_METADATA_ROW_NUM);
}
/* Now reset the device. */
CySoftwareReset ();
#endif /* CCG_FIRMWARE_APP_ONLY */
}
/*
* Configure the FET type usage model. This should be modified only if
* the board supports a different configuration. Wrong configuration
* shall result in damage of the boards and attached devices. Leave it
* to default configuration for working with standard cypress design.
*
* For CCG4, the default for PCTRL is active high and CCTRL is active low.
*/
pd_hal_set_fet_drive(PD_FET_DR_ACTIVE_HIGH, PD_FET_DR_ACTIVE_LOW);
/* Configure the ADC block and input used for VBus detach detection. */
pd_hal_set_vbus_detach_params(APP_VBUS_DETACH_ADC_ID, APP_VBUS_DETACH_ADC_INPUT);
system_init();
/* Timer INIT has to be done first. */
timer_init();
/* Enable global interrupts */
CyGlobalIntEnable;
#if RIDGE_SLAVE_ENABLE
/* Initialize the Alpine-Ridge slave interface. */
ridge_slave_init (RIDGE_SLAVE_SCB_INDEX, 0);
#endif /* RIDGE_SLAVE_ENABLE */
#if CCG_HPI_ENABLE
#if (DISABLE_I2C_ADDR_CONFIG == 0)
/* Set the HPI slave address based on the state of the I2C_CFG pin. */
get_hpi_slave_addr();
#endif /* (DISABLE_I2C_ADDR_CONFIG == 0) */
#if CCG_FIRMWARE_APP_ONLY
/* Configure HPI for no-boot operation. */
hpi_set_no_boot_mode (true);
#endif /* CCG_FIRMWARE_APP_ONLY */
/* Set the flash sizes and bootloader size limits. */
hpi_set_flash_params (CCG_FLASH_SIZE, CCG_FLASH_ROW_SIZE, CCG_LAST_FLASH_ROW_NUM + 1, CCG_BOOT_LOADER_LAST_ROW);
/* Initialize the HPI interface. */
hpi_init (HPI_SCB_INDEX);
/* Update HPI registers with mode and version information. */
update_hpi_regs ();
#endif /* CCG_HPI_ENABLE */
/* Initialize the instrumentation related data structures. */
instrumentation_init();
#if (MUX_INIT_DELAY_MS != 0)
/* Specify the MUX enable delay value to be used. */
dpm_update_mux_enable_wait_period(MUX_INIT_DELAY_MS);
#endif /* (MUX_INIT_DELAY_MS != 0) */
#if CCG_UCSI_ENABLE
/* Initialize the UCSI interface */
ucsi_init ();
#endif /* CCG_UCSI_ENABLE */
/* Perform application level initialization. */
app_init();
/* Initialize the Device Policy Manager for each PD port on the device. */
for (i = TYPEC_PORT_0_IDX; i < NO_OF_TYPEC_PORTS; i++)
{
// dpm_init (i, app_get_callback_ptr(i));
}
// init pd hal
for(i = TYPEC_PORT_0_IDX ; i < NO_OF_TYPEC_PORTS; i++)
{
// for debug
pd_hal_init(i);
pd_typec_init(i);
pd_phy_init(i, pd_phy_cbk_func);
pd_typec_start(i);
pd_prot_rx_en(i);
}
#if CCG_HPI_ENABLE
/* Send a reset complete event to the EC. */
hpi_send_fw_ready_event ();
/* Wait until EC ready event has been received or 100 ms has elapsed. */
for (i = 0; i < 100; i++)
{
hpi_task ();
if (hpi_is_ec_ready ())
break;
#if (CYDEV_BCLK__SYSCLK__MHZ == 48)
/*
* Using CyDelayCycles as CyDelay is leading to a 25% error.
* The parameter used here assumes that CPU clock is running at 48 MHz.
*/
CyDelayCycles (38400);
#else
/*
* Using CyDelayCycles as CyDelay is leading to a 25% error.
* The parameter used here assumes that CPU clock is running at 24 MHz.
*/
CyDelayCycles (19200);
#endif /* (CYDEV_BCLK__SYSCLK__MHZ == 48) */
}
#endif /* CCG_HPI_ENABLE */
#if APP_FW_LED_ENABLE
/* Configure the LED control GPIO as an output. */
gpio_hsiom_set_config (FW_LED_GPIO_PORT_PIN, HSIOM_MODE_GPIO, GPIO_DM_STRONG, true);
/* Start a timer that will blink the FW ACTIVE LED, if required. */
timer_start (0, LED_TIMER_ID, LED_TIMER_PERIOD, led_timer_cb);
#endif /* APP_FW_LED_ENABLE */
/* Start any timers or tasks associated with application instrumentation. */
instrumentation_start();
for (i = TYPEC_PORT_0_IDX ; i < NO_OF_TYPEC_PORTS; i++)
{
#if CCG_HPI_ENABLE
/* Start the DPM for the port only if it is enabled at the HPI level. It is possible that the port
got disabled before we got here.
*/
if ((hpi_get_port_enable () & (1 << i)) != 0)
#endif /* CCG_HPI_ENABLE */
{
// dpm_start (i);
}
}
memset(&pd_packet, 0, sizeof(pd_packet_extd_t));
event_id = 255;
while (1)
{
/* Perform DPM, APP and HPI tasks. */
for (i = TYPEC_PORT_0_IDX; i < NO_OF_TYPEC_PORTS; i++)
{
dpm_task (i);
app_task (i);
// for debug
static uint32_t send_count = 0;
static uint8_t msg_id = 0;
static bool init_count[2] = {false, false};
//pd_packet_extd_t pd_protocol_packet;
if (init_count == false) {
// cc_state_t cc_state;
// cc_state = InitEmarkChannel(i);
// init_count = true;
// uint16_t cc1_2 = 0x0000;
// cc1_2 = cc_state.cc[CC_CHANNEL_1];
// cc1_2 |= (cc_state.cc[CC_CHANNEL_2] << 8);
// CyDelayUs(2000);
// pd_phy_task(i, cc1_2, 1);
InitEmarkChannel(i);
init_count = true;
// pd_phy_task(i, 0xff00, 1, &msg_id);
} else if (send_count == 1000) {
cc_state_t cc_state = pd_typec_get_cc_status(i);
(void)cc_state;
pd_phy_task(i, 0xff00, 1, &msg_id, SOP_PRIME);
//pd_dpm_send_vdm_msg(i, 0x1234, 1, SOP_PRIME);
send_count = 0;
} else if (send_count == 2500) {
//pd_prot_send_ctrl_msg(i, SOP_PRIME, CTRL_MSG_GOOD_CRC);
pd_phy_task(i, 0xff00, 2, &msg_id, SOP_PRIME);
} else if (send_count == 3000) {
pd_phy_task(i, 0xff00, 3, &msg_id, SOP_PRIME);
send_count = 0;
} else if (send_count == 4000) {
send_goodcrc(i, msg_id, SOP_PRIME, 2);
send_count = 0;
}
if (pd_packet.hdr.hdr.msg_type != 0) {
send_goodcrc(i, pd_packet.hdr.hdr.msg_id, SOP_PRIME, 2);
memset(&pd_packet, 0, sizeof(pd_packet_extd_t));
event_id = 255;
} else if (event_id != 255) {
pd_phy_task(i, event_id, 2, &msg_id, SOP);
event_id = 255;
}
CyDelayUs(1000); //1ms
// send_count++;
#if CCG_HPI_ENABLE
/* Handle any pending HPI commands. */
hpi_task ();
#endif /* CCG_HPI_ENABLE */
#if CCG_UCSI_ENABLE
/* Handle any pending UCSI commands. */
ucsi_task ();
#endif /* CCG_UCSI_ENABLE */
/* Perform tasks associated with instrumentation. */
instrumentation_task();
}
#if SYS_DEEPSLEEP_ENABLE
/* If possible, enter sleep mode for power saving. */
system_sleep();
#endif /* SYS_DEEPSLEEP_ENABLE */
}
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I have been fix the problem:
I geuss pd phy default RX msg only for SOP msg, so I set pd->rx_order_set_ctrl |= EN_PRIME_SOP_DET_VAL,then I can see the RX msg which sent by EMCA!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Can you please send me the code and the relevant logs where "pdss_intr0_handler()" is invoked.
Regards,
Abhilash P
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I have been fix the problem:
I geuss pd phy default RX msg only for SOP msg, so I set pd->rx_order_set_ctrl |= EN_PRIME_SOP_DET_VAL,then I can see the RX msg which sent by EMCA!