From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

USB Interrupt-IN endpoint data

Solved!
Go to solution

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?

 

0 Kudos
Message 1 of 7
(5,552 Views)

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/

Daniel Parrott
Software Product Marketing - Data Management & LabVIEW
National Instruments
0 Kudos
Message 2 of 7
(5,513 Views)

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).

 

0 Kudos
Message 3 of 7
(5,497 Views)

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

 

 

Daniel Parrott
Software Product Marketing - Data Management & LabVIEW
National Instruments
0 Kudos
Message 4 of 7
(5,457 Views)
Solution
Accepted by topic author Bitdiddle

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?

Message 5 of 7
(5,456 Views)

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.

 

0 Kudos
Message 6 of 7
(5,437 Views)

That's a cute hack (renumbering the endpoints so you can use viRead to get the Interrupt-IN data).  I'll try it.

0 Kudos
Message 7 of 7
(5,411 Views)