EEVblog® Electronics Community Forum

Electronics => Projects, Designs, and Technical Stuff => Topic started by: pigrew on September 22, 2019, 11:55:41 pm

Title: USBTMC/USB488 class implementation for microcontrollers
Post by: pigrew on September 22, 2019, 11:55:41 pm
I have written a USBTMC/USB488 class driver for microcontrollers (https://github.com/hathach/tinyusb/tree/master/src/class/usbtmc) (link updated 2020-07-10), based on the TinyUSB library. I'm hoping it'll be merged into the TinyUSB stack soon.

USBTMC/USB488 (in case you don't know) is the USB protocol used by test and measurement equipment (like oscilloscopes/DMM/etc...). In the market, it's in the process of replacing GPIB (IEEE488) interfaces. In hobby projects, USB CDC is the most common interface, often implemented via FTDI USB interface ICs.

I started writing it after searching for prior art. I was unable to find any open-source implementations which are standards compliant (or every mostly complete). TinyUSB won my vote due to its goal of compatibility with many different MCUs. I didn't want to have to ever port my code between USB stacks when switching MCUs. It also is developing with a goal of thread-safety so it can be used with a RTOS. "Tiny" is a good feature too; I can fit my implementation on a STM32F042 with 6 kB of RAM and 16 kB of flash with enough space left for application code. In the near future, I think the project will be limited to 16/32-bit little-endian MCUs, but this may expand in the future.

The USBTMC class driver implements most of the USB488 protocol (read STB, flash a light, clear, trigger, write, read, abort read or write, etc...), though some optional features are presently missing (like changing between remote/local states). Performance may also be somewhat lacking (I've not been optimizing for throughput), though it can be improved. There's also only a minimal application layer at the moment, it'll be up to you to implement a IEEE 488.2 state machine, SCPI (or perhaps use the scpi-parser (https://github.com/j123b567/scpi-parser) library), and your actual product code.

So, if you are working on a micro-controller project which needs a message-based command interface, you may want to look into using this library.

USBTMC specification download page(zip file) (https://www.usb.org/document-library/test-measurement-class-specification)

-Nathan

PS: This protocol seems difficult enough that many products have non-conforming implementations. (Last time I checked my Siglent SDG2042X, it didn't support CLEAR, as an example.)
Title: Re: USBTMC/USB488 class implementation for microcontrollers
Post by: mTron47 on June 08, 2021, 06:41:20 pm
Hi Nathan
What you wrote seems to be exactly what I have been looking for: a USBTMS device running on e.g. a Atmel SAMD21. Up to now i have fiddled using Atmel Studio 7.0 and ASF. The USB example implementations seem to kind of work for the basic classes such as USB CDC, but not for TMC. The same seems to be true for TinyUSB which supports SAMD21 among many other architectures. Indeed it is my goal to learn more about USB in general, but a working USBTMC implementation seems to be a good starting point.
Problem is that your link to your GitHub runs a 404-error. Coincidence or intent?
Cheers
Peter
Title: Re: USBTMC/USB488 class implementation for microcontrollers
Post by: voltsandjolts on June 08, 2021, 07:06:24 pm
Looks like it managed to swim upstream:
https://github.com/hathach/tinyusb/pull/160 (https://github.com/hathach/tinyusb/pull/160)
So should be part of the tinyusb project now.
Disclaimer: I've never tried it
Title: Re: USBTMC/USB488 class implementation for microcontrollers
Post by: mTron47 on June 08, 2021, 07:50:31 pm
@voltsandjolts
Thank you for your super-quick and helpful response!  :clap:

Peter
Title: Re: USBTMC/USB488 class implementation for microcontrollers
Post by: pigrew on July 07, 2021, 02:29:46 pm
Yes,

The USBTMC code was merged upstream a while ago, as mentioned. My "standard" workflow for GitHub is to delete branches after they are merged, so that's why the link broke.

https://github.com/hathach/tinyusb/tree/master/src/class/usbtmc (https://github.com/hathach/tinyusb/tree/master/src/class/usbtmc) is a working link to the class implementation.

I've not personally used the SAMD21, but it should work and many people use TinyUSB on the SAMD21.
Title: Re: USBTMC/USB488 class implementation for microcontrollers
Post by: jancumps on January 29, 2023, 05:39:07 pm
update: I've tested it for the Raspberry Pico controller and it works there too.
And someone has tested the integration with the scpi-parser (https://github.com/kmatch98/tinyusb/tree/master/examples/device/usbtmc/src) lib that's mentioned in the original post.

edit: I've tested the integration with SCPI-parser too yesterday. I made the integration a bit simpler than the link I gave above. Stayed as close as possible to the example of pigrew, and only adapted the state machine in the place where the SCPI command arrives and when the parser is ready and replies can be sent.
Title: Re: USBTMC/USB488 class implementation for microcontrollers
Post by: gamalot on May 05, 2026, 12:24:34 pm
Hi @pigrew,

Thanks for your amazing work on the USBTMC class for TinyUSB. I've been using it recently to develop a USB/GPIB adapter.

While working on the implementation, I believe I've spotted a small error in usbtmc_device.c (https://github.com/hathach/tinyusb/blob/master/src/class/usbtmc/usbtmc_device.c#L273). It seems that the conditional logic in one of the if statements is inverted.

Current code:
Code: [Select]
TU_VERIFY(usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in));
Suggested fix:
Code: [Select]
TU_VERIFY(!usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in));
Looking forward to your thoughts!