1 Attachment(s)
Problem with DT_HID (maybe!)
Hi all,
Im having a little trouble using Darrel Taylors USB DT_HID "framework".
Apologies for the long winded post, but I want to give as much information as possible as opposed to the classic "My code doesn't work, HELP!" ones you often see.
Everything enumerates OK and my device transmits data correctly but receiving data is a different story. I have defned a set of 'messages' to allow simple communication between host and device. The messages take the form of two bytes - ID and data. Depending on what ID is received the approriate action is taken, e.g. Device receives Message ID "F", which indicates it should repsond by sending its firmware version string. In order to make sure errors are handled and reported if the device does not recognise the command it receives it responds by sending Message ID "u" and data = the message ID it does not recognise. The host software then alerts the user that an unknown command was sent to the devce.
My problem is that any command I send results in the device responding with a "u" and what initially seemed to be a nonsense byte. It also seemed that this byte remained constant no matter what unrecognised command I sent e.g. I send 0x02 0x00 and I get the response 0x75 0x43 (equivalent to "u" "+"), then I send 0x03 0x00 and I still get 0x75 0x43 returned.
However I later realised that if I reset my device the next time it responds the unknown command is set to whatever the last unknown command I sent was. This may sound confusing so I will illustrate:
Code:
Device reprogrammed here...
Host sends: Device Responds:
============================
0x02 0x00 0x75 0x43
0x02 0x00 0x75 0x43
0x03 0x00 0x75 0x43
0x03 0x00 0x75 0x43
Device reset here.....
0x02 0x00 0x75 0x03
0x02 0x00 0x75 0x03
0x03 0x00 0x75 0x03
0x03 0x00 0x75 0x03
0x04 0x00 0x75 0x03
Device reset again...
0x03 0x00 0x75 0x04
0x70 0x00 0x75 0x04 <-- 0x70 is a valid command but is not being recognised
etc.
So as far as I can reason there are two possible problems - the Firmware on the device is somehow storing the unknown command but only recalling it when the device is reset and then freezing the buffer again until another reset - seems very unlikely since I do not believe the USB module uses non-volatile memory, unless toggling !MCLR is not actually resetting the USB memory?
Or the device is working fine but the host software is failing to update its OUT buffer when I wish it to and is instead repeating the previous send until the device is reset whereupon it finally updates the buffer with the most recent requested bytes. This seems like the most intuitive simply because I would expect resetting the device would destroy any past knowledge of bytes I have sent. However I have used a USB analyser program and it suggests I am sending what I am trying to send and receiving what I think I am receiving. Assuming this is monitoring at the lowest level then it must be the device that is incorrect.
Basically I am at hair pulling frustration levels! If anyone knows exactly whats wrong then great! If not then any suggestions on what I could try would be welcome.
Heres a description of my setup:
PBP 2.60 developing in MPLAB. PIC18F2550, 4MHz Clock.
DT_HID260.pbp - modified slightly for my needs - changed the Usage Page information so that my software can pick up Windows Messages from it more easily
VB6.0 host software.
Attached is my firmware code. If you need me to I can attach some of the vb 6 code but its an activex which makes it a little complicated - let me know if it would be helpful.
Thanks in advance!
Re: Problem with DT_HID (maybe!)
OK, so obviously nobody has any thoughts so far but I have done a little more investigation and found out the probem lies with me using an interrupt to perform the reads...
I started from scratch using Darrells BasicUSB.pbp test program adapted for pic18f2550 4MHz. I wrote a very simple loop that checks for Rx data then sends out the RX buffer straight back to the PC. It sits there quite happily spewing out whatever the last RX data was, everytime I send a new set of data it updates correctly and everything works as expected.
I started adapting this simple routine to become more like my original (faulty) code. The first step was to take the DoUSBIn out of the main loop and into an interrupt driven by TMR2. So now the program runs the main loop where it echoes whatever is in the RX buffer, pauses for 100ms and repeats, whilst TMR2 interrupts when it overflows (no preload, it just keeps running) and checks for received data using the @ ON_USBRX_GOSUB macro. This is where it seems to fail. Basically the data I send the device does not get copied over into the Tx buffer. I also get the same effect as before where after a reset the TX buffer contains whatever the previous RX data was.
I have confirmed that the PC end is working as expected by using a variety of different methods of communicating the device. It is definately the PIC that is not operating as expected.
So I think there is something funny going on with the interrupts, either I am missing some statements somewhere or DT_HID is doing something funny.
Does anybody have any thoughts?
Thanks
Andy
Re: Problem with DT_HID (maybe!)
Andy,
When you GOSUB from a high priority interrupt handler by using @ ON_USBRX_GOSUB ... all interrupts stop.
USB is no longer being serviced. Nothing can be transmitted or received.
When you hang around blinking LED's and PAUSING for several seconds, the USB connection will be dropped. Actually it will be dropped much sooner than that.
You might get away with it if tick_timer: was a low priority interrupt, but certainly not the way you have it.
Re: Problem with DT_HID (maybe!)
Hi Darrel
Thanks for the reply, that certainly makes some sense. However I have replaced my tick timer routine with this one:
Code:
tick_timer:
USBSERVICE
USBIn 1, USBRXBuffer, USBRXBufferCount, NoData ' read data, if available
USBSERVICE
goto DataOK
NoData:
' zero out the USBRXBuffer[0] byte
USBRXBuffer[0] = 0
DataOK:
@ INT_RETURN
And in the main loop I can check USBRXBuffer[0] for a non zero value which indicates a valid command has been received and I can act on it. Given that the only thing not USB related is setting that byte to 0 I would not have thought that the device would drop off the bus, especially given that this is the 'traditional' way of handling USBSERVICE routines. I have also set the tick_timer interrupt to be Low Priority.
However this suffers from the same problem as before. Any thoughts?
Thanks
Andy
Re: Problem with DT_HID (maybe!)
If you've set that to low priority, then the high priority interrupts will interrupt that routine and service the USB in the middle of a USBSERVICE statement.
That will knock out the USB in short order.
When you are servicing USB via interrupts, you cannot have a USBSERVICE statement anywhere else in your program.
Only in the USB_INT or other high priority handlers that can't be interrupted.
Re: Problem with DT_HID (maybe!)
Why do you need to check for incomming USB reports every ~340uS ?
Re: Problem with DT_HID (maybe!)
There is no specific timing requirement, the period is just the maximum Timer2 would allow.
I realise that I can of course just resort to checking for incoming traffic in the main loop and in this instance that works OK. However there is obviously a restriction here that it would nice to be able to solve, i.e. how do you perform a USB read triggered by an interrupt?
I suppose that in the ideal case the receipt of USB data would trigger an interrupt of its own where the data can be processed, therefore negating the need for polling (that I do not consider to be very elegant!).
Do you think this is something worth exploring? Or is it a bit of a lost cause?
Re: Problem with DT_HID (maybe!)
Hi Darrel,
I realised that there was no dedicated USB RX interupt, hence my problem, but that is a very nice little workaround.
It works perfectly in my current setup and will no doubt be useful in the future. Thanks for all the help!
Cheers
Andy