- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 linedragonDebug("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 00Get 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>
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for your comment. Bulk-in following a control transfer is a particularity of the MAX3421E. I have resolved this issue.