04-19-2016 11:51 AM
I am developing firmware for a USB instrument, and using NI-VISA extensively to test and debug it. I would like to be able to read the data packet that comes on the Interrupt-IN endpoint during a USBTMC-USB488.2 service request (SRQ). I think the firmware is doing the right thing because this code works:
ViSession defaultRM = VI_NULL, instr = VI_NULL; // clear status; set OPC (operation complete) in event status enable; // set ESB (event status bit) in Status Byte Enable Register; start an // overlapped command; and generate a service request (SRQ) when // the operation completes. ViByte buf[] = "*CLS;*ESE 1;*SRE 32;:SYST:ARR:CLK 2304;*OPC"; ViUInt32 cnt; ViUInt16 STB; viOpenDefaultRM(&defaultRM); viOpen(defaultRM, "USB0::0x0000::0x0001::0::INSTR", VI_NULL, VI_NULL, &instr); // Service request events go into the standard event queue viEnableEvent(instr, VI_EVENT_SERVICE_REQ, VI_QUEUE, VI_NULL); // start an overlapped command that takes some time to complete, and wait for the // service request that indicates it is finished. viWrite(instr, buf, sizeof(buf)-1, &cnt); viWaitOnEvent(instr, VI_EVENT_SERVICE_REQ, VI_TMO_INFINITE, VI_NULL, VI_NULL); // When you receive a VI_EVENT_SERVICE_REQ on an INSTR session, you must call // viReadSTB() to guarantee delivery of future service request events on the // given session. viReadSTB(instr, &STB);
viWaitOnEvent gets the event, and the status byte I read has the right flags set (SRQ and ESB). Since the status byte value is transmitted from the USB device to the host in a packet from the Interrupt-IN endpoint, it seems like it must be getting that packet.
I would like to see that packet. But various things I have tried to get it from NI-VISA have so far failed. For example, I tried installing this callback handler:
static ViStatus _VI_FUNCH interrupt_in_hndlr(ViSession vi, ViEventType typ, ViEvent evt, ViAddr userHandle) { HANDLE interrupt_in_event = userHandle; ViUInt16 size; VI_ERROR(viGetAttribute(evt, VI_ATTR_USB_RECV_INTR_SIZE, &size)); if (typ != VI_EVENT_USB_INTR) return VI_ERROR_INV_EVENT; if (size > 0) { ViPByte buf = new ViByte[size]; VI_ERROR(viGetAttribute(evt, VI_ATTR_USB_RECV_INTR_DATA, buf)); printf("Interrupt-IN data ="); for (int i=0; i<size; ++i) printf(" %02x", buf[i]); printf("\n"); } else { printf("No Interrupt-IN data!\n"); } SYSERR(SetEvent(interrupt_in_event), FALSE); return VI_SUCCESS; }
with this code
HANDLE interrupt_in_event; SYSERR(interrupt_in_event = CreateEvent(NULL, TRUE, FALSE, NULL), NULL); // Install a handler for USB Interrupt-IN events VI_ERROR(viInstallHandler(instr, VI_EVENT_USB_INTR, interrupt_in_hndlr, interrupt_in_event)); VI_ERROR(viEnableEvent(instr, VI_EVENT_USB_INTR, VI_HNDLR, VI_NULL));
and it never gets called. I tried putting those events on the standard event queue, and the call to viEnableEvent fails. I tried to open the ::RAW device instead of the ::INSTR device, and that fails.
Can anyone lend me a clue?
Solved! Go to Solution.
04-20-2016 05:16 PM - edited 04-20-2016 05:18 PM
I can't say why the VISA commands aren't working, but have you tried using the 488.2 driver functions? They seem to be a bit lower level and may be the better way to try doing this. Here's a link in case you don't have the drivers installed already. http://www.ni.com/download/ni-488.2-15.0/5427/en/
04-21-2016 09:23 PM
I'm not sure why NI-488.2 would help. It looks like that's for GPIB instruments; the one I'm developing is USB (albeit a USB488 test-and-measurement class USB device).
04-25-2016 06:06 PM
I was thinking they might be using the same protocol and one was lower level than the other. Sorry, my mistake.
When you say that the "call to viEnableEvent" and " open ::RAW device instead of ::INSTR device fails" do you get an error of any sort?
I also found this KB that could be hepful. Do you have access to LabVIEW where you could test this method out to see if it works for you?
Can VISA Read be Used to Read USB Interrupt Data?: http://digital.ni.com/public.nsf/allkb/D38E5A65DA54C9A2862571E900810FEA?OpenDocument
04-25-2016 06:23 PM
For standard USB488 subclass interrupts (related to SRQ condition and READ_STATUS_BYTE request), the interrupts are handled by VISA. So, if it is an SRQ interrupt and you have SRQ event enabled, that should be raised (as you see in your example). The only time your USB_INTR event is raised would be for other kinds of interrupts (i.e. vendor-specific interrupts). Is there any particular reason you are trying to get the interrupt data for the standard interrupts? The only data is the the status which you are getting with viReadSTB call anyway, right?
04-26-2016 06:28 AM
The only reason I want to see the Interrupt-IN data (which, indeed only contains 0x81 and the status byte) is to verify correct behavior of the USBTMC firmware I am developing. It's really a matter of putting checks in boxes for test coverage.
04-26-2016 12:09 PM
That's a cute hack (renumbering the endpoints so you can use viRead to get the Interrupt-IN data). I'll try it.