We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I need to write a custom USB controller to communicate with a PC. Over the USB we will perform firmware upgrades, upload new operating parameters, download device performance data, etc. The PC side will use WinUSB mechanism to manage the USB device. I need to implement the USB control using a single interface with 2 bulf transfer endpoints, input and output. Have experimented with the USB CDC device example that came with the Keil toolset. I was thinking of taking that example and modify the descriptors and remove any unneeded logic that implemeted the CDC device and add what I need for my project.
Does this seem like a reasonebly place to start? For example, are the handling of the control endpoint esentially the same regardless of device class type?
"I do see the IUSB_SR firing on reset, it executes a USB_Suspend () and USB_Reset(), then the ISR never seems to execute again.
Your description is interpreted that no signaling comes from the host side, except for the very early one of the device connection.
Sound like the problem of D+ pull-up resistor (1.5k). Host side (PC root hub or external hub) detects the connection of the device seeing the voltage change of D+ line, caused by this resistor. As the host side doesn't detect the device connection, no signaling comes from the host.
Depending on your board, this resistor is, a) fixed one b) controlled by a port of the chip using a transistor (PNP or Pch FET)
a) fixed one Check the soldering of D+ pull-up resistor. Or check the voltage supply to this resistor.
b) controlled by a port Enable D+ pull-up resistor after finishing initialization of the USB SIE.
Tsuneo
Thanks, that was the first thing I suspected as well. Turns out the new board I was porting to has a different clock speed, once I adjust the clock registers all was well.
Thanks again.
Tsuneo,
If I may impose again, I just started seeing a problem when I happen to send USB packets of exactly 64 bytes. I am actually sending 4 separate packets of 64 bytes each from the device up to the host. (In between sends I wait for the USB ISR to set a flag that tells me the buffer has been read). The host seems to get this as 1 big packet of 256 bytes. I am looking at a USB packet sniffer (SourceUSB) and I see this 1 big packet sent over. As an experiment if I set the packet size to 63 or 65, I see 4 distinct packets being sent.
Do you send a zero-byte packet after the 64-byte packet, to tell the receiving side that 64 bytes really is the full amount of data?
I do not. Yes, this must be the problem, how else would the host know the entire response has been received. Thanks!
"As an experiment if I set the packet size to 63 or 65, I see 4 distinct packets being sent."
65 bytes packet is not fine, because its size exceeds wMaxPacketSize (= 64 bytes). "how else would the host know the entire response has been received."
As Per said, you have to send ZLP (Zero-Length Packet) to finish the transfer, when the last transaction (packet) is just 64 bytes. No other way.
Windows usbser.sys (CDC device driver) assigns 4K bytes of real memory for DMA to the host controller, to receive each bulk IN transfer. ie. 4K bytes is the expected transfer size. While the device sends full (64 bytes) packets, the host controller regards that the transfer continues, and hold the data on this 4K bytes buffer. When the device sends a short packet (less than 64 bytes, including ZLP), the host controller takes it the end of transfer, and it passes the entire transfer on the buffer to the device driver.
Short packet (including ZLP) cuts off the expected size of transfer. 4K bytes is the page memory size of PCI bus, max real memory size for single DMA session.
Not sending the 0 length packet was indeed the problem. By the way my last post was misleading, I never attempt to send more than 64 bytes, larger packets are first broken up to smaller (max 64 bytes) packets and sent individually.
Thanks again for your repsonse.
If I may I have another question. I would like my device to detect when the host connected and disconneted. Probably not just physically connected but rather when the commuication pipe has been establised or broken. If you recall I am using a modified verstion of the Keil mass storage driver, all our communication is done over BULK endpoints. I did experiment with this a bit by setting breakpoints in the USB ISR but I either could not find what I wanted or did not hita breakpoint when I thought I should. I do sometimes have trouble with breakponts being recognized when debugging some of the USB code, code I know that is executing. Any suggestions where how to detect pipe connection events?
So this was the problem on the device side. The host side (being devleoped by a third party and using WinUSB) is having some problems with the 0 length packet. The device appropriately sends this 0 length packet after the 64 byte packet, but the host thinks it got some data associated with the 0 length packet. No data sent is confirmed by a USB sniffer. I beleive the host is just attempting to read whatever next information might aynchronously be sent by the device, and somehow it is interpretting this 0 packet as having data.
"The host side (being devleoped by a third party and using WinUSB) is having some problems with the 0 length packet. The device appropriately sends this 0 length packet after the 64 byte packet, but the host thinks it got some data associated with the 0 length packet."
When the device sends just the size host requested, device doesn't attach zero-length packet (ZLP), even when the size is just the multiple of 64 bytes.
ZLP is attached when, - the host requests more than the size device to send - the device sends just the multiple of 64 bytes.
For WinUsb_ReadPipe, its BufferLength parameter is the size host requests.
I explained it more in details in this post. Termination of transfer www.cygnal.org/.../001627.html