|
|
View previous topic :: View next topic |
Author |
Message |
hawking1122
Joined: 10 Mar 2011 Posts: 11
|
USB Transfer stops suddenly |
Posted: Wed Apr 06, 2011 5:11 am |
|
|
Hi, I'm doing a project using PIC18F2550 to get analog values, then transfer data to PC via USB cable. PC send a 1byte command valued 0x04 so that PIC can start it's job each time. Now the rate is 1 transfer/sec.
The problem is the transfer is stopped just after several hundreds transfers. Here is what I did and what i've checked:
Firmware: I'm using timer1 with overflow = 10ms to check usb rx pipe periodically (using usb_kbhit(1)), if there is a package which values 0x04, then a variable names MeasureNow will be set to 1. main() consists of a while loop which checks MeasureNow, if it is 1, then main() will take adc value and transfer data to PC. Here is the code:
Code: |
//Timer1 Interrupt Service Routine
#int_timer1
void interrupt_timer1()
{
set_timer1(Timer1StartValue_10ms);
//check if a packet has been received over USB
if(usb_kbhit(1))
{
int8 Command = 0;
usb_get_packet(1, &Command, USB_DTS_TOGGLE);
if(Command == GET_DATA_CMD) //host request device to transfer measure data
MeasureNow = 1;
}
}
|
main()
Code: |
if(MeasureNow == 1)
//Get ADC value
...
...
//Finish getting ADC value
//Transmit data over USB cable
usb_puts(1, Data2Send, 32, 10);
|
On PC: I'm using Visual C++ 2005 together with driver and dll from Microchip. Here is the code
Code: |
//Send command to device to get dataDWORD ActualLength;
byte Command = GET_DATA_CMD;
DWORD ActualLength;
while(!MPUSBWrite(EP1OUTHandle, &Command, 1, &ActualLength, 1000))
{
}
System::Threading::Thread::Sleep(500); //wait for PIC to get ADC value
//get data
byte Buffer[32];
MPUSBRead(EP1INHandle, Buffer, 32, &ActualLength, 1000); //Receive the answer from the device firmware through USB
|
I'm using SnoopyPro to capture USB packet. This is the image of where I think the problem happens:
As you can see, normally, after PIC receives 0x04 command from PC, it replies 0x00000000 after just 2-3msec (late due to timer1). But in the first blue line, PIC replies after 43 msec (I don't know why it is so late), the reply is 0x00000005 (I think means a failure). Then PC keeps sending command over and over (it is the MPUSBWrite loop). I notice a packet names RESET_PIPE is sent then but have know idea what it does (I do not find this packet in USB2.0 Spec).
I've also checked PIC state in time of problem, MeasureNow is kept to be 1 all the time, Timer1 still works (it's register values still changes).
I don't know where the problem come from, it is quite a long post, sorry for that! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9255 Location: Greensville,Ontario
|
|
Posted: Wed Apr 06, 2011 7:51 am |
|
|
Welcome to the wonderful world of the USB aka Useless Serial Bus. Since it is not interrupt driven and running under the Windows GUI I'm not surprised at what you see.
Have you cut any PC code to invoke a simple 'loopback' test to properly test the mess that USB has to do to send/rcv a single character ?
Divide and conquer, eliminate the PIC from the problem first, get the PC side up and running flawlessly... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Wed Apr 06, 2011 9:24 am |
|
|
For RESET_PIPE, do a search for 'reset_pipe URB'. Chapter 10 of the current USB spec. They are not USB packets, but a software requests to reset the host controller to it's initial state. Normally triggered by a timeout. Now a USB device, is meant to reply within a certain period to a packet addressed to it. this is why you must not have interrupts disabled in the PIC for more than about 10mSec when using USB.
Things that might cause this:
1) Having some code in the PIC that results in interrupts being disabled for a long time.
2) Bad electrical layout at the USB connector.
3) Not enough smoothing on the Vusb connection.
4) Supply problem at the PIC itself. Brownout or noise.
5) Just a faulty cable.
Plus any number of other similar problems.
Best Wishes |
|
|
hawking1122
Joined: 10 Mar 2011 Posts: 11
|
|
Posted: Thu Apr 07, 2011 2:40 am |
|
|
temtronic wrote: | Since it is not interrupt driven and running under the Windows GUI I'm not surprised at what you see.
Have you cut any PC code to invoke a simple 'loopback' test to properly test the mess that USB has to do to send/rcv a single character ?
Divide and conquer, eliminate the PIC from the problem first,gte the PC side up and running flawlessly... |
Thanks for suggestion, I see that all example codes from CCS are not interrupt driven, so I'm not sure how to start that way, do you know any code does that? Also, how to test "the mess" as you said? SnoopyPro does not provide such deep level of info. I'm reading Spec, hope it help.
Ttelmah wrote: | Things that might cause this:
1) Having some code in the PIC that results in interrupts being disabled for a long time.
2) Bad electrical layout at the USB connector.
3) Not enough smoothing on the Vusb connection.
4) Supply problem at the PIC itself. Brownout or noise.
5) Just a faulty cable.
Plus any number of other similar problems.
|
3) I'm using 470n cap at Vusb pin, is it smooth enough or I have to check with oscilloscope? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Apr 07, 2011 4:46 am |
|
|
What about the actual PIC supply?.
All the CCS USB examples, _are_ interrupt driven. Why do you think they are not?. Only turned 'off', if you define USB_ISR_POLLING, in which case the interrupt bit is polled, rather than directly used, and the polling routines must be called very frequently. USB_TASK enables the interrupt.
Look in the text header of pic18_usb.h 'NOTE ABOUT INTERRUPTS'.
Best Wishes |
|
|
hawking1122
Joined: 10 Mar 2011 Posts: 11
|
|
Posted: Thu Apr 07, 2011 6:22 pm |
|
|
Thanks, Ttelmah, you always give me detail and useful answers!
Now I know I'm mistaken, I'm reading Spec to know how to handle when software send RESET_PIPE or ABORT_PIPE URB, I'll feedback soon. |
|
|
hawking1122
Joined: 10 Mar 2011 Posts: 11
|
|
Posted: Thu Apr 07, 2011 6:24 pm |
|
|
One more thing, PIC is powered from usb port. I'm thinking the problem may not come from hardware, so I'm checking the code. |
|
|
hawking1122
Joined: 10 Mar 2011 Posts: 11
|
|
Posted: Wed Apr 13, 2011 4:24 am |
|
|
I've spent a couple of days reading both USB2.0 Spec and PIC Datasheet but they didn't help much. I've used USBlyzer to check the communication and see that normally, software send packets to a driver names ACPI, then ACPI sends packets to another driver names usbhub, then I guess the packet is sent to device. At time of trouble, command packet is sent correctly to usbhub (then I guess it will be sent to device, am I correct?), but then usbhub receives packets USBD_STATUS_CANCELED. After 3 more transfers, usbhub receives USBD_STATUS_DEV_NOT_RESPONDING URB. Then software sends URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL urb to ACPI.
I do not know how to restart the communication after that, the Spec says (page 290): Resetting a Pipe: The pipe’s IRPs are aborted. The host state is moved to Active. If the reflected endpoint state needs to be changed, that must be commanded explicitly by the USBD client. But it seems that there is no way to restart using Microchip dll? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|