USB Hub CY7C65634 NAKing IN transfer following Get Descriptor Request

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

cross mob
Anonymous
Not applicable

Good afternoon,

   

I have a Cypress hub (CY7C65634) connected to a Cypress FX3 (CYUSB3014) by means of a Maxim SPI-to-USB bridge (MAX3421E). The hub seems to be reseting correctly, and receives control transfers without error. However, when I try to retrieve the descriptor via a BULK-IN transfer (as specified in MAX3421E datasheet), I am greeted first with a NAK, and subsequently by J-STATE. NAK seems to indicate that no data is available to send. Do you know of any reason why the hub has not prepared the descriptor?

I've attached my code FWIW, though it may require some familiarity with the MAX3421E. Any help would be appreciated.

   
    

<code>

    

void configureUsb(void){

    

    /*The CPU sets this bit to instruct the SIE to issue a bus reset on the D+ and D- lines. After setting
    this bit, the CPU can detect the end of the 50ms interval either by polling the BUSRST bit for
    zero, or by responding to the BUSEVENTIRQ. To program a bus reset, follow this sequence of steps:

    

    1.   Set BUSRST = 1.
    2.   Test for BUSRST = 0 or respond to the BUSEVENTIRQ.
    3.   Turn on frame markers by setting SOFKAENAB = 1.
    4.   Wait for at least one FRAMEIRQ.
    Step 4 ensures that the host logic is ready to generate the
    first host transaction.
    */
    dragonDebug("configuring", 100);

    

    //reset the bus    
    maxWriteReg(rHCTL, bmBUSRST);
    dragonDebug("pre bus", 100);
    //wait for reset
    while(!(maxReadReg(rHIRQ) & bmBUSEVENTIRQ)){
        dragonDebug("bus reset", maxReadReg(rHCTL) & bmBUSRST);
        CyU3PThreadRelinquish ();
    }
    // clear reset interrupt
    maxWriteReg(rHIRQ, bmBUSEVENTIRQ);
    maxWriteReg(rMODE ,  bmDPPULLDN|bmDMPULLDN|bmSOFKAENAB|bmHOST|bmSEPIRQ); // set into full speed host mode, separate I/O interrupt line

    

    dragonDebug("post bus reset", 100);

    

    // Relinquish the thread
    //CyU3PThreadRelinquish ();
    CyU3PThreadSleep (1);

    

    // the following steps need to be completed:
    /*
     *    -- Plug-in of a hub, enumeration of hub --
                                                     SETUP data
     Bus Reset                                                                 --- (1)
     Get Device Descriptor                           80 06 00 01 00 00 08 00
     Set Address (0x03)                              00 05 03 00 00 00 00 00
     Get Device Descriptor                           80 06 00 01 00 00 12 00
     Get Configuration Descriptor                    80 06 00 02 00 00 04 00
     Get Configuration Descriptor                    80 06 00 02 00 00 19 00
     Set Configuration (0x01)                        00 09 01 00 00 00 00 00

    

     Get Descriptor (Hub)                            A0 06 00 29 00 00 17 00   --- (2)
                  09 29 04 00 00 32 40 00 1E
     Set Port Feature (Port1, PORT_POWER)            23 03 08 00 01 00 00 00   --- (3)
     Set Port Feature (Port2, PORT_POWER)            23 03 08 00 02 00 00 00
     Set Port Feature (Port3, PORT_POWER)            23 03 08 00 03 00 00 00
     Set Port Feature (Port4, PORT_POWER)            23 03 08 00 04 00 00 00

    

        -- Hub ports watch, periodical --
     Interrupt-IN (Hub Status Change EP) (0x81)                                --- (4)
        -- optionally, repeated port scan --
     Get Port Status (Port1)                         A3 00 00 00 01 00 04 00
                  00 01 00 00        PORT_POWER
     Get Port Status (Port2)                         A3 00 00 00 02 00 04 00
                  00 01 00 00        PORT_POWER
     Get Port Status (Port3)                         A3 00 00 00 03 00 04 00
                  00 01 00 00        PORT_POWER
     Get Port Status (Port4)                         A3 00 00 00 04 00 04 00
                  00 01 00 00        PORT_POWER

    

     */

    

    /*
     * USB Request Field Sizes
     * bmRequestType 1
     * bRequest      1
     * wValue        2
     * wIndex        2
     * wLength       2
     */

    


    CyU3PMutexGet(&usbmutex, 1000);
    uint8_t error1, error2, error3;
    uint8_t address = 0x00;
    // set address req to 3 : 00 05 03 00 00 00 00 00
    //uint8_t stdUSBReq[8] = {0x00, 0x05, address, 0x00, 0x00, 0x00, 0x00, 0x00};
    //CyU3PThreadSleep (1000);
    //error1 = usbControlTransfer(0, stdUSBReq);
    //dragonDebug("address", error1+1);
    //CyU3PThreadSleep (1000);

    

    //USB 2.0 9.4.3
    //80 06 00 01 00 00 08 00
    uint8_t stdDescReq[8] =
    // standard USB request
    {0x80,
    // request is to get descriptor
    0x06,
    // device type, index 0
    0x00, 0x01,
    // no language id
    0x00,0x00,
    // length 8 bytes
    0x08,0x00};

    

    uint8_t descript[512];

    

    error1 = usbControlTransfer(address, stdDescReq);
    dragonDebug("control", error1);

    

    int i;
    for(i = 0; i < 5; i++){
        error2 = usbBulkIn(address, 0, descript);
        dragonDebug("bulk in", error2);
        error3 = hsout();
        if(error2==0 && error3==0)
            break;
        //CyU3PThreadRelinquish ();
    }

    

    CyU3PMutexPut(&usbmutex);

    

    dragonDebug("done     ", 10);

    


}

    

uint8_t usbBulkIn(uint8_t addr, uint8_t endpoint, uint8_t * receiveData){

    

    uint8_t error = 0;
    /*
    2. Data
    If a data stage is required, it is programmed as a BULK-IN or BULK-OUT transfer. Some
    CONTROL transfers, such as Set_Address, do not require a data stage because the command
    data fits into the 8 bytes in the SETUP packet.
    */

    

    /*
     * Programming BULK-IN Transfers
     *  The CPU issues an IN token to request a peripheral to send it BULK data . Then the SIE
     *  transfers data into its RCVFIFO, and ACKS the transfer. The CPU writes HXFR = 0000eeee
     *  (Table 4) to initiate the IN transfer, where eeee is the desired endpoint address.
     *  */

    

    maxWriteReg(rPERADDR, addr);
    maxWriteReg(rHXFR, endpoint & 0x0F);
    /*
    The SIE sends an IN token, the address in the PERADDR register, the endpoint number in
    EP[3:0], and a CRC5. It then waits 6.5 bit times for the peripheral to respond.
    If the peripheral responds with a DATA0 or DATA1 PID followed by data, the SIE loads the
    received data bytes into the RCVFIFO and counts the bytes. At the end of the packet
    the SIE checks the packet for errors, updates the RCVBC register and HRSLT bits, and then
    asserts the HXFRDNIRQ bit.
    */

    

    // wait for completion interrupt
    while(!(maxReadReg(rHIRQ) & bmHXFRDNIRQ));
    // check result error code
    error = maxReadReg(rHRSL) & 0x0F;

    

    if(maxReadReg(rHIRQ) & bmRCVDAVIRQ){

    

        // check bytecount
        uint8_t bytecount = maxReadReg(rRCVBC);
        dragonDebug("bytecount", bytecount+1);
        // read that byte count into provided buffer
        maxReadMultiple(rRCVFIFO, receiveData, bytecount);
        // clear receive interrupt
        maxWriteReg(rHIRQ, bmRCVDAVIRQ);
    }

    

    // clear completion interrupt
    maxWriteReg(rHIRQ, bmHXFRDNIRQ);
    /*
    Depending on the transfer outcome, the SIE may or may not assert the RCVDAVIRQ.
    If the IN data was error-free (HRSLT = 0000), the SIE sends an ACK token, complements the
    data toggle, and asserts the RCVDAVIRQ to indicate that new IN data is valid.
    If the IN data was error-free but there was a data toggle mismatch (the DATA0 or DATA1 PID
    send by the peripheral did not match the endpoint toggle value), the SIE sends the ACK
    handshake, but it does not complement the data toggle or assert the RCVDAVIRQ. The SIE sets
    HRSL = 0110 (Toggle Error) for this condition.
    This situation would happen if the peripheral received a corrupted ACK handshake from the previous
    IN transfer. In this case the host ignores the data in the RCVDATA FIFO, because it represents data
    that the peripheral mistakenly resent when it missed the last ACK handshake. By ACK-ing the transfer
    and not updating its own toggle bit, the SIE causes the peripheral to complement its toggle bit,
    thus forcing the data toggle mechanism back into sync.
    If the HRSLT bits indicate a data error, the SIE does not send the ACK, complement the data
    toggle, or assert the RCVDAVIRQ bit. The CPU responds to the HXFRDNIRQ indication
    by examining the result bits in HRSLT[3:0].
    If the result is 0000 (success), the CPU reads RCVBC to determine the byte count, and then
    reads that number of bytes using repeated reads to the RCVFIFO register (page 48). After the
    CPU retrieves the data, it clears the RCVDAVIRQ bit (by writing 1 to it). If there is another
    buffer of IN data in the double-buffered RCVFIFO, the SIE immediately re-asserts the CVDAVIRQ bit.
     */

    

    return error;
}

    

</code>

   
0 Likes
1 Solution
Anonymous
Not applicable

Hi,

   

Control transfers are used for enumeration of the device/hub by the host, using Endpoint 0 only with default address 0. 
The host will send a request to Endpoint 0 of device address 0 to find out the device/hub capabilities. This request is the one to which the device must respond on address 0. After that the device/hub will get an unique address on which it responds to the host requests further.
So, we should not expect the control transfers for enumeration to happen through BULK IN transfer which is for data transfer.

   

Regards,

   

anii

View solution in original post

0 Likes
2 Replies
Anonymous
Not applicable

Hi,

   

Control transfers are used for enumeration of the device/hub by the host, using Endpoint 0 only with default address 0. 
The host will send a request to Endpoint 0 of device address 0 to find out the device/hub capabilities. This request is the one to which the device must respond on address 0. After that the device/hub will get an unique address on which it responds to the host requests further.
So, we should not expect the control transfers for enumeration to happen through BULK IN transfer which is for data transfer.

   

Regards,

   

anii

0 Likes
Anonymous
Not applicable

Thank you for your comment. Bulk-in following a control transfer is a particularity of the MAX3421E. I have resolved this issue.

0 Likes