Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add usbtmc class driver (READY FOR TESTING) #160

Merged
merged 51 commits into from
Sep 25, 2019
Merged

Conversation

pigrew
Copy link
Collaborator

@pigrew pigrew commented Sep 14, 2019

Here is an initial revision of a USBTMC class driver.

It has most of the features I need, but not all of the features that exist in USBTMC. I added some comments on what's lacking in the headers of src/class/usbtmc/usbtmc_device.c. It's missing many of the "required" specifications, but is implemented enough to meet most needs.

The example application does not have any message/passing or multi-thread capability at the moment. I'm not planning to use a usbtmc task in the example, but I will in my more final project.

I don't intend on this being accepted right away, as I'm likely to create some breaking changes in the interface, but I want to get feedback on what I have now.

Note that it's against the "develop" branch because it requires the class-type EP-recipient patch to work.

This has been tested with NI MAX's visa control panel on Windows 10. Send, receive, query, and read STB all work (or at least with very short messages which won't overflow buffers).

(I fear I'm created this PR too soon; can delete if I'm committing to it too much, or can just start pushing once a day or something. I also understand why I see so many incomplete USBTMC implementations in commercial hardware.)

Some other implementations:

karlp/discotmc
FTDI FT51A
Linux USBTMC host class

examples/device/usbtmc/src/usb_descriptors.c Show resolved Hide resolved
src/device/usbd.c Outdated Show resolved Hide resolved
src/device/usbd.c Show resolved Hide resolved
case USBTMC_MSGID_VENDOR_SPECIFIC_IN:
case USBTMC_MSGID_USB488_TRIGGER:
default:
TU_VERIFY(false);
Copy link
Collaborator Author

@pigrew pigrew Sep 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To NAK (stall?), should it TU_VERIFY(false) or return false?

…rts makes

sense. Probably adding too many concurance issues; need to figure out
semaphores.
src/class/usbtmc/usbtmc.h Outdated Show resolved Hide resolved
@ladyada
Copy link
Collaborator

ladyada commented Sep 15, 2019

neat! ive never heard of this

@pigrew
Copy link
Collaborator Author

pigrew commented Sep 16, 2019

neat! ive never heard of this

@ladyada: Yeah, it's a quite powerful protocol. Most "test instruments" like DMM or oscilloscopes speak it over USB. It's designed to replace GPIB (and have all of its features, where ever possible). I've been wanting to use it it in personal projects for a while, but have not found any complete open-source implementations. My feeling is that each company (Keysight, Tek, LeCroy, etc likely have their own implementations, and these days all of those would be on an embedded Linux or Windows SoC).

This USBTMC spec is much more complicated to implement than I had anticipated. My code in this request (at the moment) is a bit too simplistic (and the number of lines will probably double or triple :/). I've finished up implemented the "indicator pulse" LED flash, but the transaction aborts and device clears are needing a lot of planning (due to the asynchronous nature of them).

I'm still aiming to have minimal locking, and such. I don't want it to implement its own task, so some locking will be necessary as it can be called both from the USBD core and application code.

I also ran into a few implementation problems with my stm32 fsdev driver which I'm also fixing (it didn't properly support endpoints != 64 bytes, and had a typo-bugs, and had 400 B of type conversions going into its flash). Those should be put together into a PR early this week.

I'll update this PR in a day or once I figure out how to cope with concurrency and aborting transactions. Some progress (both USBTMC and stm fsdev driver) are my fork.

Copy link
Owner

@hathach hathach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for yet another great PR. It is never be too soon to submit PR, you can constantly push the new code to update the PR. Even after merged, I did constantly changing the stack all around.

There is only API naming changes to keep thing consistency for now, though I will read some docs and try to get familiar with this class later on. Meanwhile, would you mind give me a bit of instruction on how to test this class: e.g application link, or simple instructions to use those app to test with.

examples/device/usbtmc/src/tusb_config.h Outdated Show resolved Hide resolved
examples/device/usbtmc/src/usbtmc_app.c Outdated Show resolved Hide resolved
src/class/usbtmc/usbtmc_device.h Outdated Show resolved Hide resolved
src/device/usbd.c Show resolved Hide resolved
src/device/usbd.c Outdated Show resolved Hide resolved
src/class/usbtmc/usbtmc_device.h Show resolved Hide resolved
};

typedef enum {
USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all UPPER case, you can remove the b

src/class/usbtmc/usbtmc.h Outdated Show resolved Hide resolved
@pigrew pigrew changed the title Add usbtmc class driver. Add usbtmc class driver. (IN DEVELOPMENT) Sep 16, 2019
@pigrew pigrew changed the title Add usbtmc class driver. (IN DEVELOPMENT) Add usbtmc class driver (IN DEVELOPMENT) Sep 16, 2019
@pigrew
Copy link
Collaborator Author

pigrew commented Sep 16, 2019

Thank you very much for yet another great PR. It is never be too soon to submit PR, you can constantly push the new code to update the PR. Even after merged, I did constantly changing the stack all around.

There is only API naming changes to keep thing consistency for now, though I will read some docs and try to get familiar with this class later on. Meanwhile, would you mind give me a bit of instruction on how to test this class: e.g application link, or simple instructions to use those app to test with.

Yes, I'l l do that. Which operating system do you use? The drivers are different for different OS. I can add a simple python script to talk to the device once the drivers are installed.

@pigrew pigrew changed the title Add usbtmc class driver (IN DEVELOPMENT) Add usbtmc class driver (READY FOR TESTING) Sep 22, 2019
@pigrew
Copy link
Collaborator Author

pigrew commented Sep 22, 2019

@hathach, With the latest changes, I think the class is ready for testing. The main functionality is working well. I'm worried a little bit about concurrency (I added locking for the state machine variable, but it isn't sufficient).

I added a python test script to the examples folder, which demonstrates the core functionality and some of the error handling.

I'm happy for it to be merged, or sit here in testing for a while. I'm sure that there will be issues that will come up.

@pigrew
Copy link
Collaborator Author

pigrew commented Sep 23, 2019

I seem to have forgotten an important feature. The app layer has to be able to signal that it's busy, and have the class driver NAK the bulk-out endpoint. This will require another function for the app layer to call when it's ready. Delay state are not mentioned in the specification, so I think that a NAK is the proper response when the micro's internal buffers are full.

@pigrew
Copy link
Collaborator Author

pigrew commented Sep 24, 2019

Having the app control the interface flow control is implemented. Also, I removed references to rhport from the application layer, as I think this only applies to host drivers? If anything, interface_id should be added, but for now I'm assuming a single interface.

My python regression testing script is still passing, though only tested with a 64 byte endpoint size on STM32F0.

Copy link
Owner

@hathach hathach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic works on this PR. There is only minor naming convention for the API. If you don't have time, I will merge this first and then rename it later on. Not a big deal at all.

docs/concurrency.md Show resolved Hide resolved
// * (successful) tud_usbtmc_app_check_abort_bulk_in_cb
// * (successful) usmtmcd_app_bulkOut_clearFeature_cb

void tud_usbtmc_app_open_cb(uint8_t interface_id);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we replace tud_usbtmc_app by simply tud_usbtmc_ dropping *app in API

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. I've found it hard to keep track of which functions are for which direction of communication, and keeping app there makes it more clear that certain functions are for implementation by the app, not the class library.

I think other libraries fix this by using structs of function pointers to create a namespace, but the TUSB code at the moment doesn't do that.

I can go either way with this question.

Copy link
Owner

@hathach hathach Sep 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is rather simple, if the API is invoked by the stack and application have to implement that function, it is a callback and must end with _cb() . Otherwise, it doesn't has _cb() e.g

tud_cdc_write() : implemented by stack
tud_cdc_rx_cb(): implemented by application

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to change this to be as you suggested.

I usually read left-to-right, so looking for the _cb is less easy, as I need to read left to right to center.

However, there are more levels of complexity....

  1. app calls class (tud_class_*)
  2. class calls app (tud_class_*_cb)
  3. stack calls class (tud_class_* or tud_class_*_cb); // Sometimes with _cb, other times without _cb?
  4. class calls stack (usbd_*)

Number 1 and 2 and 3 have overlap. This somewhat impacts the app developer since auto-complete will suggest both.

src/class/usbtmc/usbtmc_device.h Outdated Show resolved Hide resolved
examples/device/usbtmc/src/tusb_config.h Outdated Show resolved Hide resolved
@pigrew
Copy link
Collaborator Author

pigrew commented Sep 25, 2019

@hathach Would you mind taking a look at the latest changes?

They are mostly cosmetic, but I did have some small updates to the testing script, and also changed the get_capabilities method to use a callback function instead of an extern struct.

Copy link
Owner

@hathach hathach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect !!! Thank you very much for putting lots of effort into this PR.

@hathach hathach merged commit 9a8d23e into hathach:master Sep 25, 2019
@pigrew pigrew deleted the usbtmc branch September 25, 2019 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants