Resolving AG532XX IVI Driver OPC Timeout Bug in VISA Layer

Brian Holt7 min read
Data AcquisitionOther ManufacturerTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview

The host-side IVI-C driver family shipped for the Keysight 53210A, 53220A, and 53230A RF frequency counters (driver family name ag532xx) contains a defect in the internal callback ag532xx_WaitForOPCCallback. The user-facing attribute AG532XX_ATTR_OPC_TIMEOUT is read from the IVI attribute store, but its millisecond value is never pushed into the underlying VISA session as VI_ATTR_TMO_VALUE before the *OPC? query is transmitted. The Operation Complete poll therefore always races against the default VISA I/O timeout (typically 2000 ms) regardless of how the caller has configured AG532XX_ATTR_OPC_TIMEOUT.

Observable symptoms:

  • *OPC? returns VI_ERROR_TMO (0xBFFF0015) on long acquisitions even when AG532XX_ATTR_OPC_TIMEOUT is set to 30 s or higher.
  • Intermittent IVI_ERROR_CANNOT_RECOVER (0xBFFA4000) errors during burst or continuous measurement modes.
  • Inconsistent behavior across GPIB, USB, and LAN sessions that share the same driver instance, because the underlying VISA timeout differs by transport.
  • False-positive success returns where viQueryf times out but the calling wrapper ignores the failure.
Affected layer: host-side IVI driver source (ag532xx.c). The defect is independent of instrument firmware revision; rebuilding the driver is sufficient.

Affected Hardware and Driver Builds

Instrument Model Driver Builds Affected Resolution
53210A All builds prior to the OPC-timeout patch release Rebuild from patched source or upgrade to the post-patch installer
53220A All builds prior to the OPC-timeout patch release Rebuild from patched source or upgrade to the post-patch installer
53230A All builds prior to the OPC-timeout patch release Rebuild from patched source or upgrade to the post-patch installer

The 53200A and 53200B entry-level counters use a separate driver family (ag53200) and are not affected by this defect.

Root Cause Analysis

The IVI driver architecture separates two distinct timeout domains that the buggy callback fails to bridge:

  1. IVI attribute layer: AG532XX_ATTR_OPC_TIMEOUT is the user-facing knob expressed in milliseconds. It is stored in the driver's per-session attribute table and accessible through Ivi_GetAttributeViInt32.
  2. VISA I/O layer: VI_ATTR_TMO_VALUE controls how long viRead, viQueryf, and viScanf block before returning VI_ERROR_TMO.

In the buggy implementation, only the IVI attribute is consulted. The VISA session timeout is left at its default (2000 ms, or whatever the application set during session init). When the instrument takes longer than the VISA timeout to assert the Operation Complete bit, viQueryf aborts before opcDone is populated. The function then returns success by coincidence because opcDone retains its stack-initialized value of VI_FALSE, masking the failure downstream in the calling IviWaitForOperationComplete wrapper.

The IVI specification requires that wrapper functions interacting with the instrument respect attribute-based timeout overrides. WaitForOPCCallback is registered during Ivi_Init and invoked by IviWaitForOperationComplete whenever the application calls any of the synchronization primitives such as ag532xx_Abort, ag532xx_Initiate, or ag532xx_MeasureFrequency.

Technical Background: IVI, VISA, and SCPI

The driver stack follows the standard IVI-C specification layered atop NI-VISA or compatible VISA implementations such as Keysight IO Libraries. The *OPC? query is defined in section 4.1.1 of the SCPI 1999 standard: it returns 1 to the output queue only after all pending operations have completed. Because the response travels through the same I/O path as ordinary instrument commands, *OPC? inherits the VISA I/O timeout unless the driver explicitly overrides it for the duration of the poll.

The reference VISA tree used for development is the Keysight IO Libraries Suite, which exposes VI_ATTR_TMO_VALUE through both the 32-bit and 64-bit session interfaces.

The Fix

Replace the body of ag532xx_WaitForOPCCallback in ag532xx.c with the following source. The change saves the active VISA timeout, applies the OPC timeout for the duration of the *OPC? query, and restores the original value to avoid side effects on subsequent VISA calls.

static ViStatus _VI_FUNC ag532xx_WaitForOPCCallback (ViSession vi, ViSession io)
{
    ViStatus error = VI_SUCCESS;
    ViInt32 opcTimeout, oldVISATimeout;
    ViBoolean opcDone = VI_FALSE;

    checkErr( Ivi_GetAttributeViInt32 (vi, VI_NULL,
                                       AG532XX_ATTR_OPC_TIMEOUT,
                                       0, &opcTimeout) );
    viCheckErr( viGetAttribute (io, VI_ATTR_TMO_VALUE, &oldVISATimeout) );
    viCheckErr( viSetAttribute (io, VI_ATTR_TMO_VALUE, opcTimeout) );
    viCheckErr( viQueryf(io, "*OPC?", "%hd", &opcDone) );
    viCheckErr( viSetAttribute (io, VI_ATTR_TMO_VALUE, oldVISATimeout) );

Error:
    viDiscardEvents (io, VI_EVENT_SERVICE_REQ, VI_QUEUE);
    return error;
}

The local oldVISATimeout capture is critical. Without it, a user-supplied session timeout configured by viSetAttribute(io, VI_ATTR_TMO_VALUE, ...) prior to ag532xx_init would be silently overwritten on every synchronization call, breaking subsequent application-level reads.

Step-by-Step Application

  1. Locate the IVI driver source tree. The default Windows install path for the Keysight 53200 series driver is C:\Program Files\IVI Foundation\IVI\Drivers\ag532xx\ag532xx.c.
  2. Back up the original ag532xx.c file.
  3. Apply the code change shown above using a patch utility or manual edit.
  4. Recompile the driver using the IVI-C reference compiler distributed with the Keysight IO Libraries Suite or the open IVI-C build environment.
  5. Regenerate the installer with the supplied build_installer.bat or equivalent packaging script.
  6. Distribute the updated .msi (or deploy the rebuilt .dll and its 64-bit companion) to the target system.
  7. Reboot any host application that statically loaded the old driver.

Verification

Execute the following programmatic check after installing the patched driver. The probe confirms that VI_ATTR_TMO_VALUE is temporarily overridden inside the callback while the underlying session retains its configured value across normal calls.

ViSession vi, io;
ViInt32 appliedTimeout;
ViReal64 measuredFreq;
const ViInt32 opcTimeoutMs = 30000;

ag532xx_InitWithOptions ("53230A",
                         VI_FALSE, VI_FALSE,
                         "Simulate=0,RangeCheck=1,QueryInstrStatus=1,Cache=1",
                         &vi);

io = Ivi_IOSession (vi);
ag532xx_SetAttributeViInt32 (vi, "",
                             AG532XX_ATTR_OPC_TIMEOUT,
                             opcTimeoutMs);

ag532xx_Initiate (vi);
ag532xx_MeasureFrequency (vi, 100000, &measuredFreq);
/* Inside WaitForOPCCallback the VISA timeout is now 30000 ms */

viGetAttribute (io, VI_ATTR_TMO_VALUE, &appliedTimeout);
/* appliedTimeout reflects the post-restore value, not opcTimeoutMs */

ag532xx_close (vi);

For manual confirmation, open Keysight Connection Expert, navigate to the 53230A instrument, and issue *OPC? interactively with the patched driver loaded. Requests exceeding 2 s but within the configured AG532XX_ATTR_OPC_TIMEOUT must no longer return VI_ERROR_TMO.

Verification Matrix

Test Expected Result Pass Criterion
Long measurement with OPC timeout = 30 s Driver returns success No VI_ERROR_TMO logged
Pre-set VISA timeout = 5000 ms preserved across calls Session timeout unchanged after *OPC? Post-restore read equals 5000 ms
Forced instrument hang (clear status, no OPC) Driver returns IVI_ERROR_OPERATION_NOT_COMPLETE Caller sees error, not silent success
GPIB, USB, and LAN sessions in same process Each session uses its own timeout No cross-session leakage of VI_ATTR_TMO_VALUE

VISA and IVI Error Code Reference

Constant Hex Meaning
VI_SUCCESS 0x00000000 Operation completed without error
VI_ERROR_TMO 0xBFFF0015 Timeout expired before operation completed
VI_ERROR_INV_SESSION 0xBFFF000E Given session handle is not valid
IVI_ERROR_CANNOT_RECOVER 0xBFFA4000 Driver could not recover from a fatal error
IVI_ERROR_INVALID_VALUE 0xBFFA4001 Attribute value is out of the supported range
IVI_ERROR_OPERATION_NOT_COMPLETE 0xBFFA400F OPC query returned before completion flag

Related Considerations

  • Session sharing: When two threads share a single VISA session and call ag532xx_WaitForOPCCallback concurrently, the save/override/restore pattern is not atomic. Wrap the callback registration in an external mutex if your application uses multiple worker threads.
  • Range checking: The default range for AG532XX_ATTR_OPC_TIMEOUT is 1 ms to 60000 ms. Values outside this range must be rejected when RangeCheck=1 is set in the driver session options.
  • Simulate mode: When Simulate=1 is passed to ag532xx_InitWithOptions, the callback is bypassed entirely; the patch has no effect in simulation.
  • GPIB vs LAN latency: LAN-connected instruments can exhibit 5–20 ms of TCP round-trip overhead per poll iteration. Configure AG532XX_ATTR_OPC_TIMEOUT to at least 5× the expected worst-case single-shot measurement time to avoid spurious timeouts on burst measurements.
  • Event queue discipline: The trailing viDiscardEvents(io, VI_EVENT_SERVICE_REQ, VI_QUEUE) clears any pending IEEE 488.2 service request events so that subsequent status byte polling does not observe stale notifications.

Alternative Workarounds

If rebuilding the driver is not feasible, two application-level patterns restore correct behavior without touching the source:

  1. Pre-set VISA timeout before IVI init:
viSetAttribute(io, VI_ATTR_TMO_VALUE, opcTimeoutMs);
ag532xx_SetAttributeViInt32(vi, "",
                             AG532XX_ATTR_OPC_TIMEOUT,
                             opcTimeoutMs);
  1. Disable QueryInstrStatus in the session options string: The driver skips the WaitForOPCCallback path entirely and relies on synchronous command execution. This removes the asynchronous polling benefit but eliminates the timeout race.

Adjacent Driver Audit Template

Use the following checklist to inspect other IVI drivers in the same family or from the same vendor for the same defect pattern:

  • Does <prefix>_WaitForOPCCallback read an OPC timeout attribute?
  • Does it call viSetAttribute(io, VI_ATTR_TMO_VALUE, ...) with that value before *OPC??
  • Does it save and restore the original VI_ATTR_TMO_VALUE?
  • Does it call viDiscardEvents on the IEEE 488.2 service request queue?

If any check fails, apply the same save/override/restore template demonstrated in the fix section above.

What does AG532XX_ATTR_OPC_TIMEOUT control?

It defines the maximum time in milliseconds that the driver waits for the instrument to assert the Operation Complete bit after a command is issued. The value must be applied to the VISA I/O timeout before any *OPC? query, otherwise the default 2000 ms VISA timeout overrides the user setting.

Why does *OPC? appear to succeed even when it times out?

The callback allocates opcDone on the stack and initializes it to VI_FALSE. If viQueryf aborts with VI_ERROR_TMO, the function returns the error but opcDone retains its initialized value. Downstream wrappers may interpret the absent success signal incorrectly and retry silently.

Does this affect Keysight 53200A or 53200B models?

No. The 53200A and 53200B entry-level counters use a different driver family (ag53200). The defect is confined to the 53210A, 53220A, and 53230A driver family (ag532xx).

Can this patch template be applied to other IVI drivers?

Yes. The save/override/restore pattern is broadly applicable to any IVI driver whose OPC callback reads an attribute timeout but fails to push it into the VISA layer. Auditing other driver callbacks against this template is recommended for fleet-wide reliability.

Will the fix change behavior when Simulate=1 is set?

No. In simulation mode the callback path is bypassed and *OPC? is handled entirely by the simulation engine. The patched code is inert in that mode and introduces no behavioral change.

Back to blog