I want to develop mass storage device using LPC2148.I am just referring code from Keil for USBMem. My problem is - I get Get_descriptor command from PC to which I respond with device descriptor. On receiving 8th byte it generates Reset. Then I get Set_address command. On response to it, I execute Set Address command in protocol engine. Then again I get Get_descriptor command (It should actually have index field of 18 but I receive with 64). Again after 8th byte it generates Reset and again gives Set_address command instead of Get_descriptor command for Configuration descriptor. What can be the problem?
This is given in USB in a nutshell. Normally when something is wrong with a descriptor or how it is being sent, the host will attempt to read it three times with long pauses in between requests. After the third attempt, the host gives up reporting an error with your device. I am getting Get_descriptor 3 times and then nothing happens. But if I can send 8 bytes successfully then I think 18 bytes also would have gone succesfully. And I have already shown my device descriptor before. And t seems to be fine. What else can be the problem?
Still not getting Get_descriptor command for configuration descriptor. But getting it for device descriptor three times. What can be the problem?
Most of points have been discussed already. I don't think of any more. If you would have a hardware analyzer, you could get more detailed sign to focus on the firmware bug...
Do you have any account on a server to share your code? Post your code to the sharing server so that we can look into it. If it can, I'll run your code on my LPC2148 board (IAR or Olimex), and monitor it with a hardware analyzer.
Tsuneo
If it can, I'll run your code on my LPC2148 board (IAR or Olimex), and monitor it with a hardware analyzer.
you have a good soul!
I have sent my code on your yahoo account which I got from LPC2000 group. Problem still continues......
> I have sent my code on your yahoo account which I got from LPC2000 group.
I don't see the yahoo mail at all. The account is held just to post to LPC2000. Until you noticed to me on above post, I wasn't aware of your mail ;-) Fortunately, yahoo server still kept your mail. Now, your code is running on my Olimex LPC2148 board. The outline of the trace on a hardware analyzer is as follows
- Bus Reset - Get_Descriptor( Device ) --- incomplete - Bus Reset - Set_Address --- success - Get_Descriptor( Device ) --- incomplete - Get_Descriptor( Device ) --- incomplete - Get_Descriptor( Device ) --- incomplete
All of Get_Descriptor fails on its STATUS stage. Host puts ZLP (Zero-Length Packet) to the default OUT endpoint, but the device is NAKing until time out.
This means the default OUT endpoint is still occupied by the SETUP packet. The endpoint buffer is not cleared correctly, after read out on the SETUP handler.
In USB_ReadEP(), you try to send "Select Endpoint" and "Clear Buffer" command to the device protocol engine using wr_cmd_H(). But these commands don't take any data to write on the data phase. Just optional read. Then, I add new wr_cmd() and modified USB_ReadEP() as follows.
// <------- add a subroutine to write a command to the protocol engine without any data void wr_cmd( unsigned long send_cmd ) { USBDevIntClr=0x10; //clear cmd_code_empty USBCmdCode=send_cmd|usbcmd; //configure device while(!(USBDevIntSt & 0x10)); //wait cmd_code_empty USBDevIntClr=0x10; //clear cmd_code_empty interrupt bit } unsigned long USB_ReadEP (unsigned long EPNum, unsigned char *pData) { unsigned long cnt, n, phy_num; USBCtrl = 0x00000001|EPNum<<2; do { cnt = USBRxPLen; }while ((cnt & PKT_RDY) == 0); cnt &= PKT_LNGTH_MASK; for (n = 0; n < (cnt + 3) / 4; n++) { *((__packed unsigned long *)pData) = USBRxData; pData += 4; } USBCtrl = 0; phy_num = EPAdr(EPNum); // wr_cmd_H(phy_num,(phy_num|0x00000200)); // <------ these commands are wrong // wr_cmd_H(0xF2,0x00F20200); // <------ replaced with right ones wr_cmd( 0x00000500 | phy_num ); // select endpoint command wr_cmd( 0x00F20500 ); // clear buffer command return (cnt); }
Also, to unload ZLP of the STATUS stage from the default OUT endpoint, this temporary fix was added.
void USB_ISR (void) __irq { ... ... if (val & 0x04) //STP user manual page number 229 { USBDevIntClr = dev_stat; Ep0_setup(); continue; } //**************** modified from here else { // temporary fix for status stage USB_ReadEP(0x00, EP0Data.pData); // unload ZLP } //**************** modified to here ... ...
Now, the trace was improved one step further.
- Bus Reset - Get_Descriptor( Device ) --- success - Bus Reset - Set_Address --- success - Get_Descriptor( Device ) --- success - Get_Descriptor( Config ) --- incomplete
Get_Descriptor( Config ) is disturbed by "while(1);", inserted by you for debug ;-)
Not just USB_ReadEP(). You are using wr_cmd_H() wrongly everywhere on your code. Check them all.
Thank you very much! I made those changes in my code and it worked properly. You have helped us a lot in our project and we will require your valuable guidance in further development.
We successfully sent our configuration descriptor. Now when our board is connected, it shows mass storage device found. But still does not support that device. I am getting Set_cofiguration command but what am I supposed to do in its response? I am executing configure command in protocol engine in its response. As mine is mass storage device, can you please tell me what events are expected further? What is sequence of next requests from host?
> What is sequence of next requests from host?
For device firmware, you should not expect requests in sequence. Host puts any request as it likes. Device responds to it and does the requested job, if the device supports it. Otherwise, the device returns STALL.
> As mine is mass storage device, can you please tell me what events are expected further.
Ummm MSC (Mass Storage Class), It's really tough for starter, because you have to implement two layers of protocol. I recommend HID for the starting project, which is simpler.
But if you dare to try MSC, Read out the MSC specs I refer in this post. Also, Jan Axelson's book, USB Mass Storage ( http://www.lvr.com/usbms.htm ) is your friend. Trace a successful implementation, like LPCUSB lpcusb.svn.sourceforge.net/.../msc_bot.c lpcusb.svn.sourceforge.net/.../msc_scsi.c And then, attack to the implementation.
For MSC Bulk-Only Transport (BOT) implementation, Firstly, you have to implement the handlers for required class-specific request(s) at least, in addition to the standard device requests. Secondly, MSC-BOT carries SCSI command over bulk IN/OUT endpoints with command wrapper packets. You have to unwrap/wrap SCSI command and status, and transfer requested data or media sector (cluster) data Thirdly, SCSI command parser upon above MSC-BOT protocol, which handles the media actually.
1. Class specific request
these USB specs are the must.
Mass Storage Class Specification Overview 1.3 www.usb.org/.../usb-msc-overview-1.3b.pdf
Mass Storage Bulk Only 1.0 www.usb.org/.../usbmassbulk_10.pdf
In "3 Functional Characteristics (usbmassbulk_10.pdf p7)" section, you'll find these class-specific requests. - 3.1 Bulk-Only Mass Storage Reset (class-specific request) - 3.2 Get Max LUN (class-specific request)
"Bulk-Only Mass Storage Reset" is required, but "Get Max LUN" is optional for single-LUN device. If you don't implement "Get Max LUN", return STALL to this request.
Other than these class-specific requests, these standard requests are used for error recovery. - Get_Status( ENDPOINT ) (usb_20.pdf 9.4.5 Get Status) - Clear_Feater( ENDPOINT_HALT ) (usb_20.pdf 9.4.1 Clear Feature)
USB 2.0 spec www.usb.org/.../usb_20_122909-2.zip
2. Command/Data/Status Protocol over bulk IN/OUT endpoints
1) Command transport SCSI command comes to bulk OUT EP included in Command Block Wrapper (CBW) (usbmassbulk_10.pdf 5.1 Command Block Wrapper (CBW)) Check the integrity of the CBW following to "6.2 Valid and Meaningful CBW" section. If it isn't valid, return STALL to bulk IN EP, following "6.6.1 CBW Not Valid" For valid CBW, pass the SCSI command to the parser. Depending on the SCSI command, MSC-BOT handler moves to one of Data In/ Data Out / Status transport stage.
2) Data IN/Out transport Most of SCSI command exchange data on this stage. For example, Inquiry returns fixed inquiry response (a block of data) to bulk IN EP. Read(10)/Write(10) exchange block data (sector - 512 bytes or cluster - 4K bytes) over bulk IN/OUT EP. But some SCSI commands, like Test Unit Ready, don't have this stage.
3) Status transport All of SCSI commands conclude the session in this stage. Firmware passes back Status report (the result of the SCSI command), included in Command Status Wrapper (CSW), to the bulk IN EP.
3. SCSI command over above MSC protocol
The required SCSI commands are listed up in "4.2 Command Set Information" (PDT=00h) section of this spec.
MSC Compliance Test Specification www.usb.org/.../MSC-compliance-0_9a.pdf
required SCSI commands - Inquiry - spc3r23.pdf(p142) - Request Sense - spc3r23.pdf(p221) - Test Unit Ready - spc3r23.pdf(p232) - Read(10) - sbc2r16.pdf(p47) - Read Capacity(10) - sbc2r16.pdf(p54) - Write(10) - sbc2r16.pdf(p78)
Implement them all following the SCSI spec. As of these SCSI specs, the original t10.org has closed the links just for their members. Search "sbc2r16.pdf" on Goooogle, and you'll find them floating over the internet. This is just a brief outline of MSC-BOT and SCSI implementation. You'll learn a lot from a running example, the specs and the reference book.
Good luck.
Implementing class requests for mass storage class. Got GET MAX LUN request. Replied it with value zero. using bus hound software. so my device replies with 1 byte that is 0. but host does not respond. why is this so?
Uho, you are actually attacking to MSC implementation. Impressed with your guts. > Got GET MAX LUN request. Replied it with value zero. using bus hound software. so my device replies with 1 byte that is 0. but host does not respond.
Ah, you are trapped with Get_Max_LUN pitfall. Maybe you weren't aware of this sentence on the MSC-BOT spec. www.usb.org/.../usbmassbulk_10.pdf
3.2 Get Max LUN (class-specific request) The device shall return one byte of data that contains the maximum LUN supported by the device. For example, if the device supports four LUNs then the LUNs would be numbered from 0 to 3 and the return value would be 3. If no LUN is associated with the device, the value returned shall be 0. ... Devices that do not support multiple LUNs may STALL this command.
That is, for single LUN, you have to return STALL Surely, it's confusing. ;-) I've seen many ones also have been trapped.
To return STALL to IN EP0, put this protocol engine command. - Set_Endpoint_Status (IN EP0: 0x00410500, ST bit: 0x00010100)
When next SETUP transaction comes, STALL is cleared automatically by the protocol engine.
1. I stalled control IN endpoint. I got clear_feature command then. I replied to it just by executing Set_Endpoint_Status (IN EP0: 0x00410500, ST bit: 0x00000100) and sent zero length packet. When i analyzed Bus hound, host does not respond after clear_feature. It again asks 1. Get max lun 2. Clear_feature and does it for 3 times to Reset the device. What should i do?
2. I am getting string descriptor request for language id and serial no. but not for manufacturer string. I checked for device descriptor index fields. it seems to be fine. What can be the problem?
> 1. I stalled control IN endpoint. I got clear_feature command then.
Ummm... Clear_Feature is unexpected response. For protocol STALL on default endpoint, Clear_Feature is not issued. Clear_Feature is used for recovery of bulk/interrupt endpoint.
a) Which endpoint does the Clear_Feature points, Post the 8 byte SETUP data of the Clear_Feature
b) Do you see any other bus activity between Get_Max_LUN and Clear_Feature on bus hound? Does the host happen to send CBW to bulk OUT endpoint?
Which endpoint does the Clear_Feature points, Post the 8 byte SETUP data of the Clear_Feature
important fields of setup packet are -> recipient - endpoint endpoint no - 0 feature - endpoint_halt
on bus hound we found in following sequence GetMaxLun(3 times) Stall pid Clear feature(3) cancelled Reset(3) no response
We have not yet written structure for CBW. There is no interrupt on bulk endpoints.
> endpoint no - 0
Do you mean OUT EP0 ? wIndex = 0x0000 : OUT EP0, 0x0080 : IN EP0
It's better to show the 8-bytes SETUP data of the request directly, than giving the interpreted value. On Bus Hound log, You'll see the original SETUP data. It's more reliable evidence. Anyway, host should be satisfied by both of these device responses. - Return 1 byte of 0 on data stage to Get_Max_LUN request - STALL to Get_Max_LUN request
I investigated more on this issue, and found this sentence on the compliance test spec.
MSC Compliance Test Specification www.usb.org/.../MSC-compliance-0_9a.pdf - Class-Specific Request Assertions 5.5.2 If the device supports only one LUN, it may report so via the Get Max LUN request or may fail that request.
Also, I observed enumeration of six USB memories on a hardware analyzer. All of them returns "0" to Get_Max_LUN. Did you "realize" the bulk IN/OUT endpoints on the handling of Set_Configuration request ? These bulk EPs should be "realized" like the default EP. Sound like the error is caused by disabled bulk EPs
I was realizing bulk endpoints one after the other. i.e. USBReEp=0x00000010 USBReEp=0x00000020 That i changed to USBReEp=0x00000030. And i got bulk OUT interrupt.
Could not save the bus hound file but details are - GetMaxLun(2) stall pid CLEARFEATURE(2) -> data - 02 01 00 00 00 00 00 00 canceled -> data - c0010000 no response -> data - c0000005 RESET(2) ok USBCBW