cancel
Showing results for 
Search instead for 
Did you mean: 

PD Soft Reset doesn't work

jefflongo
Associate III

Hello,

I have developed an application which can dynamically detect source capabilities by reading the capabilities soon after a PD charger is plugged in. In order to renegotiate with the new PDO, I currently must issue a reset by writing to the RESET_CTRL register. Unfortunately, this approach causes VBUS to be lost momentarily, an undesirable side-effect.

From browsing ST's example application source code, I noticed the use of "PdMessage_SoftReset", a way to soft reset the PD negotiation using the PD protocol. Seems simple enough: write the soft reset message 0x0D to the TX_header register at address 0x51, then write the send PD message command 0x26 to the address 0x1A.

Unfortunately, I've had absolutely zero luck with this approach. I have tried with multiple different PD compliant chargers, neither of them renegotiate after issuing the soft reset message. I have also tried two separate STUSB4500 chips. I have tried writing the soft reset message as a single byte 0x0D, as well as writing it as a 2 bytes, 0x000D. I have only been successful using the register reset approach.

What could I be missing here?

Best,

Jeff

1 ACCEPTED SOLUTION

Accepted Solutions
NBALL
ST Employee

​Hello,

I'm wondering wether the source takes into account the 2nd soft_reset and sends its source capa, when its PSRdy has not been sent. Can you please check on scope that after each soft_reset you got source_capa ?

For your application, I would suggest to follow the proposed code and wait for state PE_SNK_READY of PE_FSM, before to send Soft_reset.

Best regards

Nathalie

View solution in original post

8 REPLIES 8
NBALL
ST Employee

Hello

Could you please share your code and/or USBPD trace ?

Thanks

Best regards

Nathalie

jefflongo
Associate III

Attached the relevant code here. Basically, I can read the source capabilities successfully, and my code selects the "optimal" pdo based desired user voltage/current parameters, writing it to the high priority PDO3 profile. I cannot get the renegotiation to this profile until I use the provided register "reset()" function provided in the code. It does work after that. However, I would like to use the function "send_pd_message()" with the parameter PD_SOFT_RESET to force the renegotiation. The writes are successful, but nothing seems to happen afterwards. Thanks for looking into this.

// STUSB4500 i2c address
#define STUSB_ADDR 0x28
 
// STUSB4500 registers
#define PORT_STATUS 0x0E
#define PRT_STATUS 0x16
#define CMD_CTRL 0x1A
#define RESET_CTRL 0x23
#define WHO_AM_I 0x2F
#define RX_BYTE_CNT 0x30
#define RX_HEADER 0x31
#define RX_DATA_OBJ 0x33
#define TX_HEADER 0x51
#define DPM_SNK_PDO1 0x85
 
// STUSB4500 masks/constants
#define STUSB4500_ID 0x25
#define STUSB4500B_ID 0x21
#define SW_RESET_ON 0x01
#define SW_RESET_OFF 0x00
#define ATTACH 0x01
#define PRT_MESSAGE_RECEIVED 0x04
#define SRC_CAPABILITIES_MSG 0x01
 
// Maximum number of source power profiles
#define MAX_SRC_PDOS 10
 
// PD protocol commands, see USB PD spec Table 6-3
#define PD_CMD 0x26
#define PD_GET_SRC_CAP 0x0007
#define PD_SOFT_RESET 0x000D
 
#define RESET_DELAY_MS 27
#define PLUG_TIMEOUT_MS 3000
#define RETRIEVE_TIMEOUT_MS 500
 
static bool send_pd_message(const uint16_t msg) {
    return (
      i2c_master_write_u16(STUSB_ADDR, TX_HEADER, msg) &&
      i2c_master_write_u8(STUSB_ADDR, CMD_CTRL, PD_CMD));
}
 
static bool is_present(stusb4500_config_t* config) {
    uint32_t time = config->get_ms();
    uint8_t res;
    do {
        if (!i2c_master_read_u8(STUSB_ADDR, WHO_AM_I, &res)) return false;
        if (config->get_ms() - time > RETRIEVE_TIMEOUT_MS) return false;
    } while (res != STUSB4500_ID && res != STUSB4500B_ID);
 
    return true;
}
 
static bool reset(stusb4500_config_t* config) {
    // Enable software reset
    if (!i2c_master_write_u8(STUSB_ADDR, RESET_CTRL, SW_RESET_ON)) return false;
 
    // Wait for VBUS to discharge
    uint32_t time = config->get_ms();
    while ((uint32_t)(config->get_ms() - time) < RESET_DELAY_MS)
        ;
 
    // Verify reset success
    if (!is_present(config)) return false;
 
    // Disable software reset
    if (!i2c_master_write_u8(STUSB_ADDR, RESET_CTRL, SW_RESET_OFF)) return false;
 
    return true;
}
 
// some other functions here
.....
//
 
bool stusb4500_negotiate(stusb4500_config_t* config, bool on_interrupt) {
    // code to read header here
    .....
 
    // Read source capabilities
    // WARNING: This must happen very soon after the previous code block is
    // executed. The source will send an accept message which partially
    // overwrites the source capabilities message. Use i2c clock >= 300 kHz
    if (!i2c_master_read(
          STUSB_ADDR,
          RX_DATA_OBJ,
          buffer,
          HEADER_NUM_DATA_OBJECTS(header) * sizeof(stusb4500_pdo_t)))
        return false;
 
    // Find and load the optimal PDO, if any
    if (!load_optimal_pdo(config, (stusb4500_pdo_t*)buffer, HEADER_NUM_DATA_OBJECTS(header)))
        return false;
 
    // Force a renegotiation
    // NOTE: vbus will be momentarily lost
    return reset(config);
}

NBALL
ST Employee

Hello

Up to now I did not detect any failure on code you shared.

Can you please ensure that voltage but also current requested is below or equal to source PDO one ?

I attach a snapshot of trace done using the FW demo which we are proposing: sw reset is sent, then source exposes again its capabilities which allows stusb4500 to negociate a new PDO based on its settings.

Can you please share a PD trace ?

Best regards

Nathalie

I am certain that the requested voltage and current are equal to the source PDO. The code can only request a voltage and current that matches a source profile. I'm not sure how I can provide you with a PD trace. I do own an oscilloscope, but I do not own a USB/PD analyzer, and as far as I know I can't get that from the STUSB4500. Please let me know what I can do to further troubleshoot.

Best,

Jeff

NBALL
ST Employee

Hello,

Can it be possible that you log all I2C exchanges done between your MCU and stusb4500 ?

When you check on scope, do you see, on CC pins, the different messages ?

Please refer to zip attached.

Best regards

Nathalie

I hooked up a scope to the CC pins, and was in fact seeing activity when sending the soft reset message. I noticed that the soft-reset message did in fact work, but only while debugging. To reiterate, my method of performing negotiation is:

  1. soft reset to force source capabilities message to transmit, read header + source capabilities, determine the PDO that best fits the user's requirements
  2. write the PDO to the highest priority PDO3 profile
  3. soft reset to force renegotiation

After further investigation, I've determined that the method is only successful IF there is a >= 120ms delay between step 1 and 2. I'm glad that I have something working, but could you clarify what could be making this delay necessary?

NBALL
ST Employee

​Hello,

I'm wondering wether the source takes into account the 2nd soft_reset and sends its source capa, when its PSRdy has not been sent. Can you please check on scope that after each soft_reset you got source_capa ?

For your application, I would suggest to follow the proposed code and wait for state PE_SNK_READY of PE_FSM, before to send Soft_reset.

Best regards

Nathalie

I don't think it had anything to do with the second soft reset, as I said in the previous message, the delay was required between the initial soft reset and the PDO write. However, I do see your point and I replaced the delay with a loop to wait for the PE_SNK_READY state before writing the new PDO. This seems to have solved the problem. I can't thank you enough for your help, it's great to have this level of support in a community forum.

Best,

Jeff