USB host troubles: K60f with custom board

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB host troubles: K60f with custom board

1,372 Views
djhoop
Contributor II

Hi all,

I don't tend to ask questions in forums since typically somebody else has had a similar problem and searching can get me close enough to solve my issue. Thus, I post here as an act of desperation. That said, here's the problem:

I have a custom board with MK60FN1M0LQ12 that I would like to use as a USB host. On the board is a permanent Texas Instruments TUSB2046B USB hub (datasheet) with its DP0/DM0 connected to USB0_DP (pin 19) and USB0_DM (pin 20). The TUSB2046B's reset pin (active low) is connected to PTA19 (pin 73). I'm using Codewarrior 10.3 (or 10.4, I have both) with PEx.  The TI chip is a full-speed hub. Naturally, I would like to connect up to 4 devices through the hub, run the appropriate enumeration, and leverage the devices as CDC components. Also, as a side note, I have a 32 mHz crystal connected to pins 45 and 46 (System Oscillator 1 in the PEx component).  If I ground then raise PTA19, I can watch the DP0 channel ground and raise also. If I understand correctly, this means that the hub is correctly announcing itself as a full speed device.

I have tried a few variants on getting the K60 to work as a host:

  1. First, I tried the Freescale USB Stack and running the CDC host demo with tweaks as necessary for my specific clock settings and processor configuration. I can watch the host initialize on debug, and it clears that just fine. However, it never detects an attachment, regardless of what I do to the registers or to the reset pin that outputs to the TUSB2046B. When checking connections, I can see the SOFs being sent (if forced).
  2. Next, I tried using the MQX USB CDC host. Basically the same story as with the bareboard USB stack, except I edited the bsp for the TWR-K60F120M for my configuration. It seems to correctly use the bsp code, the psp code, and the usbh code from MQX to initialize the host.  But again, no attach event.
  3. Lastly, I collected and, after some tweaks again to the processor settings and other variations for my hardware, used the code related to Erich Styger's blog article here.  In this code, I can see that when the second line of the USB_LDD init function is called, I immediately get an attach event (regardless of whether the USB_ISR is enabled). After allowing the attach event to proceed, it pushes the usb reset and the code ever clears past the USB reset to the wait.  I have commented this out and made it progress, but after it detects the hub as a full speed device, it doesn't grab the identifiers correctly.  Two things seem odd to me here: first is the immediate USB attach event when the init code hasn't completed, and second is the freeze up. It doesn't lock up everything, just the attachment and enumeration process. The poll loops still function, though I'm also getting a ton of calls to the USB_ISR.  I'm not sure if this is related, or part of the normal process.

Reading over other posts and through Erich's blog, I see things that indicate that clock settings may be a problem. I've looped through them numerous times and I'm pretty sure they're correct for my hardware.  Also, since I can't physically detach the hub from the K60, is there something I can do in the code to "force" the USB0 initialization aside from the hub? I have tried separately initializing the reset pin and holding that down until the PE_low_level_init completes to no avail.  I have a feeling that I'm just not finding the right knob to turn.

Labels (1)
4 Replies

701 Views
djhoop
Contributor II

An update:

I have discovered that it was a combination of issues: first, the USB reset pin needed to be set to match the official TUSB2046b timings, of about 200us-1ms. I fixed that, got the hub to enumerate, but it was reporting that it didn't have any ports.  This was due to a bad hub. Now, I have a new board with a new hub and correct timings on the USB reset pin, and I can get the hub to work. It also detects the attachment of my device.  However, this leads me to a new problem...

I'm running the bare metal USB Host example for the K60f, with the tweaks necessary to drive the USB reset pin and to match my clocks. Another application with identical settings functions correctly under these settings, but it does not use the USB. After the USB device connects to a downstream port on the hub, I can see the hub state machine transition to the HUB_ADDRESS_DEVICE_PORT_PROCESS. This happens reliably when the device is attached, provided it wasn't previously attached and removed. It then goes through the device attachment just fine, enumerates it, then continues running. After this, it picks up messages and rolls on to TR_MSG_RECV in khci.c, where every message is a NAK.

The USB device is an Arduino-based sensor that sends its information string once every second. It functions correctly on a PC, and the virtual serial port on the PC at 115200 baud shows the data correctly.

So, the device works on a PC, and it shows up and is enumerated on the K60f. I don't appear to be getting the data that the device sends, nor does it look like it's applying the driver to recognize that it's a USB CDC ACM interface that it needs to use. Any ideas?

701 Views
djhoop
Contributor II

In case it helps anybody else, I have it solved now.

As it turns out, the khci task was taking minutes to finish the enumeration because of a few default timeouts. It would get the hub just fine, and then when I added a device, it would cover a few steps before it would then wait. This wait was caused by a message being received while the device was still in setup. Then, the task would wait for the timeout (5 seconds), then retry the message 10 times before finally checking for new messages. I hacked my way around this, shortening the timeout (KHCI_TICK_WAIT) by a couple zeros and having it recheck the queue every time (seq_ints is 1 instead of 10). Now my device enumerates quickly. This change may make it so my handler is not "officially" USB compliant, but I'm fine with that since it works much faster now.

On the device side, I found out that it was an FTDI device. I have written a driver to support it based on the code at http://www.intra2net.com/en/developer/libftdi/, but it is still buggy and I don't want to post it here in its current state. Everything is working, minus the bugs, and I can collect the data as needed from the device. I'll still need to finish clearing the bugs out and make it support multiple FTDI devices simultaneously, but this issue is finally solved for me.

I integrated everything yesterday, so I now have a lovely USB host for FTDI devices and a 4-port full speed hub. The application uses FreeRTOS, SD with FAT32 support, A to D, D to A, 3 UARTs, and controls 15 other external hardware devices. Between some of Erich Styger's code and the example programs for CodeWarrior, the rest of it was pretty straightforward and still quite lightweight (about 118kB).

701 Views
georgevernon
Contributor I

Hi DJHoop,

Thanks for following up and posting your solution. I had the same experience with the 20DX256, trying to enumerate an Android tablet through a TI hub chip. I reduced the timeout (KHCI_TICK_WAIT) to 8000 and set the seq_ints to 2 and managed to get beyond the first enumeration step. While I'm not out of the woods (I need to set the Android tablet into accessory mode and I'm not certain the event callback I wrote has been called), your insights have certainly helped to move me along.

A couple of other "gotcha's" that I've run across which aren't well documented are the need to explicitly set the memory protection unit off using "MPU_CESR = 0;" during the low level init process; if using MQX Lite, the need to explicitly set the task stacks to 768 or 1024 to keep from trashing the stacks; If using the PE USB Stack component, the need to explicitly edit the function "USB_LDD_Init()" in the  "USB_LDD.c" file to change the statement "DevDataPtr->EnUser = TRUE;" to "DevDataPtr->EnUser = FALSE;", which then allows the follow up call to "USB_LDD_Enable()" to actually execute something (execution of most of the content of that function is gated by the statement "if (!DevDataPtr->EnUser) {" so if true, the content doesn't execute).

One other item I noted was immediately following the first request to the tablet to extract the control pipe buffer size, after queueing up the device address transaction, the massive delay appears to be the "_usb_khci_task()" function waiting for a reply from the hub, however, no request was made to return data from the hub prior to waiting for this reply. I expect this is some bug in the code, (probably not properly emptying the task queue), which caused the next transaction to be placed further down in the queue. Good luck with your development.

best regards,

george vernon

701 Views
djhoop
Contributor II

I noticed that EnUser part, and I think there was a tweak in one of the PE components where you could select for it to initialize for you, but you have to make sure to NOT select automatic initialization for the USB_LDD component. That made my entire USB code nonfunctional for a while, until I changed the one setting. I agree that the documentation is a little weak on this part, but if you're being very careful with the bean setting, it can be found and fixed. The cross-dependencies were missing.

With my FTDI devices, I don't experience any more massive delays.  There is still some strangeness with the hub, where I do still get an occasional message coming through (of type "RECV" and of 0-byte size) with ONLY the hub active, but this is not important in the grand scheme of things when it comes to the rest of my project.

My current challenge is tweaking my FTDI driver code to support multiple simultaneous devices, but then I think I'll be done with my code writing except for the debugging and cleanup. Overall, I think the USB code is a nice place to start, though it would be really nice to have something built that supported a more straightforward integration of other hardware types.  For example, making the code libUSB compliant (without needing to run a Linux variant on the processor), so someone only needs to grab a source file to add device support, instead of writing one up. This would make future USB host development much more straightforward for everyone. I had considered re-wrapping the existing code to support some of this, but it isn't in the cards since I'm facing a deadline. Maybe this could be a feature request for Freescale, if I'm not alone in my thoughts.

Thanks,

Daylond