ARM TI chip am335x, how to set up USB HOST endpoint 1

40 Views Asked by At

This question of for anyone who has done bare metal access on the TI ARM am335x CPI.

I tried to create a new tag am335x, but I don't have a high enough reputation.

I am trying to get the am3358/am3352 CPU running in USB Host mode. I want to access a USB thumbdrive.

In summary, I cannot get EP1 to work. EP0 appears to be working fine.

The environment is Bios 6.76.03.01 with XDC 3.55.2.22, using GNUC 7.3.1. Although for this unit development, it is essentially running it's own single threaded operation.

I am using the original "AM335X_StarterWare_02_00_01_01" as a beginning point, and attempting to simply open the USB drive and communicate with it. I examined the WireShark log for this UBS drive when attached to a PC. I can see all the descriptor commands send as transactions to/from EP0, and also the first inquiry it sends on EP1.

So, naturally the endpoints for this thumbdrive work as expected in the PC.

In the ARM firmware, I can successfully enumerate the device, and perform a GET LUN command which returns successfully. These are all transaction messages on EP0. However it is failing to communicate through the data pipes. I am printing out the data and messages to a UART log of my own messages, which is included at the bottom of the post.

There are a couple dozen source files, so it's not practical to post them here (I tried just a few, and broke the 30,000 character limit) If requested, I can zip up the CCS project and place it on some server somewhere. I've never needed to include files in a StackOverflow post, so I'm open to suggestions on what to do to share it.

I can't output any message inside a ISR, but I can simply write to some memory. So I have a large buffer, and a few functions that simply write a message to that buffer: AddToIntBuffer(), AddHEXToIntBuffer() . Then I can pause or interrupt the execution, and have the CCS IDE do a memory dump of that, so I can see what happens inside the ISR.

The configuration descriptor, as read from the device, matches the one that I sniffed with WireShark. the the value parse correctly. The some data is shown below:

09 02 20 00 01 01 00 80 32 09 04 00 00 02 08 06
50 00 07 05 01 02 00 02 00 07 05 81 02 00 02 00

Which is a Mass storage device, 2 endpoints, class MSC, protocol x50, etc...

The pipe descriptors are shown here:

07 05 01 02 00 02 00        EP 1 OUT   Bulk  512 bytes
07 05 81 02 00 02 00        EP 1 IN    Bulk  512 bytes

So they are all okay.

Here is where things get insane...

When I create the pipes using the function USBHCDPipeAllocSize(), USBHCDPipeConfig(), etc and set the type to "BULK" the first attempt to send the MSC device a query out PIPE 1 gives a PIPE_ERROR.

Here's what's really weird: The value that holds the state is from the global structure "g_sUSBHCD", "eState" member. And it is ONLY set inside the ISR. And every step in the ISR is recorded to my memory log... That member is never set to PIPE_ERROR in the ISR, since it's not recorded anywhere in my ISR log buffer... So I'm lost as to how the eState member gets set to error, if the ISR never set that flag.

So how it is getting set?

More importantly: Why can I not send any data out EP1?

Can anyone offer some recommendation? Or even code that works on this device to open EP1 in host mode as BULK?

There has to be something simple and easy as to what I am doing wrong and why the EP1 isn't working. But I have yet to find any clue in the code or any of the doc.

Just a few things I've tweaked:

I have tried playing with the "ulInterval" stuff that sets timeouts. No difference.

I have tried changing the DMA type (I am not using CPPI routine at this stage).

I have tried changing the EP type.

When I change the setting of the pipes from BULK to INTERUPT, it actually does send the inquiry request to the device (well, gives me a success anyway) but when I try to read back from the pipe, it gives me a STALL. Maybe that is normal to get a STALL if you try to read a pipe that is BULK. I don't know.

But the same issue about that state flag: The only place that eState member is set is within the ISR, and every step in the ISR is recorded to my memory log. And that member is NEVER set inside the ISR.

I tried reading the TI doc, which is the Tech Ref they call "spruh73". But that was a waste of time. It's missing a BUNCH of information. For example:

Section 16.2.8.2 - Host mode:

"This allows that one packet can be received while another is being read. Double packet buffering is enabled by setting the DPB bit of RXFIFOSZ register (bit 4)."

Well, that RXFIFOSZ register is not defined.

For that matter, neither is HOST_RXTYPE, HOST_RXINTERVAL, INTRRXE, etc... and bunches of other things.

TI leaves a LOT to be desired in documenting this peripheral, and in offering support.

In summary: Can anyone steer me toward some example code that correctly opens EP1 and communicates through it? Or even actual, useful, doc that defines all this missing stuff?

Thanks in advance for any advice on this issue.

-Scotty

Below are a bunch of traces and code fragments.

This is essentially my console debug message trace

  SETUP: Data Sent:
80 06 00 01 00 00 08 00
  CONTROL:   Addr 0   Len: 18   Data Sent:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00
  SETUP: Data Sent:
80 06 00 01 00 00 12 00
  CONTROL:   Addr 0   Len: 18   Data Sent:
12 01 00 02 00 00 00 40 00 00 00 00 00 00 00 00
00 00
ST - Connected
12 01 00 02 00 00 00 40 3D 1E 96 20 00 01 01 02
03 01
  ->  Set Address
  SETUP: Data Sent:
00 05 01 00 00 00 00 00
  CONTROL:   Addr 0   Len: 0   Data Sent:

ST - Addressed
  ->  Get Cfg Descriptor
  SETUP: Data Sent:
80 06 00 02 00 00 09 00
  CONTROL:   Addr 1   Len: 9   Data Sent:
00 00 00 00 00 00 00 00 00
  SETUP: Data Sent:
80 06 00 02 00 00 20 00
  CONTROL:   Addr 1   Len: 32   Data Sent:
09 02 20 00 01 01 00 80 32 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

09 02 20 00 01 01 00 80 32 09 04 00 00 02 08 06
50 00 07 05 01 02 00 02 00 07 05 81 02 00 02 00

ST - Addressed
  ->  Set the CFG
  SETUP: Data Sent:
00 09 01 00 00 00 00 00
  CONTROL:   Addr 1   Len: 0   Data Sent:

ST - Setting Interface
  SETUP: Data Sent:
00 0b 00 00 00 00 00 00
  CONTROL:   Addr 1   Len: 0   Data Sent:

ST - Interface Set
 -> Open Driver Index 1  Instance -2146156192
Get Interface
Interface is -2146773055 drivers
Search 1 drivers for class 8
 Testing 8 to 8
Calling open at ADDR 8006c380 for driver # 0 and instance -2146156192
Allocating OUT Pipe Index 1 Address 1  bytes 512
 OUT PIPE 2162688
Allocating IN Pipe Index 1 Address 1  bytes 512
 IN PIPE 2228224
 MSC EVENT-> 1  OPEN
Resulting instance is -2146156192
 -> driver for this is # 0
 -> Setting to Configured
  SETUP: Data Sent:
a1 fe 00 00 00 00 01 00
  CONTROL:   Addr 1   Len: 1   Data Sent:
00
LUN Control result 1  Max LUN is 0
Max LUN  0
SCSI Inquire
Sending Command on Index 1 Pipe 2162688 Count 31 ...  PIPE WRITE: Pipe 2162688   Len: 31
55 53 42 43 90 19 23 54 24 00 00 00 80 00 06 12
00 00 00 24 00 00 00 00 00 00 00 00 00 00 00
 ...  Starting Timer 7000
  OUT State = Error
 sent 0
 Inquire Failed
  SETUP: Data Sent:
a1 fe 00 00 00 00 01 00
  CONTROL:   Addr 1   Len: 1   Data Sent:
00
LUN Control result 1  Max LUN is 0
Max LUN  0
SCSI Inquire
Sending Command on Index 1 Pipe 2162688 Count 31 ...  PIPE WRITE: Pipe 2162688   Len: 31
55 53 42 43 90 19 23 54 24 00 00 00 80 00 06 12
00 00 00 24 00 00 00 00 00 00 00 00 00 00 00
 ...  Starting Timer 7000
  OUT State = Error

This is a small portion of the buffer that holds messages written during the ISR. It's 1000's of entries, mostly just "entered" and "complete". Occasionally there is a EP0 record, but nowhere is there any ISR that signals something regarding EP1 (INT1 in this case refers to the interrupt for USB module 1)

INT1 entered
INT1 complete
INT1 entered
**EP0
  epStatus: 0x00000001  ulStatus: 0x00000000
  Checking pipe 00  EPN 01  DMA 00
INT1 complete
INT1 entered
**EP0
  epStatus: 0x00000001  ulStatus: 0x00000000
  Checking pipe 00  EPN 01  DMA 00
INT1 complete
INT1 entered
INT1 complete
0

There are 0 best solutions below