MK22 USB HID transfer packet speed

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MK22 USB HID transfer packet speed

2,545 Views
balbet
Contributor II

Hi,

I imported the generic HID example using MCUXpresso IDE, and changed the interval time to get the maximum theoretical transfer speed of 1000packets/s:

#define HS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE (64U)
#define FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE (64U)
#define HS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x01U)
#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x01U)

#define HS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE (64U)
#define FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE (64U)
#define HS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x01U)
#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x01U)

But I'm stuck at 500 packets/seconds no matter what I do. The main CPU is working at 80MHz, although the 500 packets/seconds are consistent in time, and no packets are lost, so it seems a configuration issue. As you can see I also changed the packet size (as well as the report count size of the report descriptor and the data buffer size) to 64 bytes, but the data is transferred up and down correctly with no difference vs the 1 byte of the imported example. What am I missing?

Off the topic and just to know, is there any plan to integrate some kind of tool in the MCUXpresso to configure the USB peripheral like we had in Processor Expert?

Thanks!

Labels (2)
Tags (3)
7 Replies

2,260 Views
wallacewebster6
Contributor I

What you need to do is use a USB analyser (you can also try Wireshark and its USB plug-in if you are not equiped for USB developements) to verify that the host is really sending the IN token at official site 1ms (which I expect to be the case as long as you have configured the interrupt endpoint to correctly request this).

 

If you see that it sends the IN token at 1000Hz rate and each second one is NAK-ed by the device (which I expect to be the be the case) and only each second one is responed to with data it would confirm that the problem is at the software level since it is hasn't prepared the data in time or because it only prepares the data at 500Hz rate. 

2,260 Views
balbet
Contributor II

Hi Clay,

Can you please check my last reply mjbcswitzerland (06-abr-2020 1:58), I posted the results of the USB analyser.

Thank you,

0 Kudos

2,260 Views
mjbcswitzerland
Specialist V

Hi

If the USB host is polling an interrupt endpoint set to 1ms rate it is "guaranteed" to poll at that rate.

If the throughput is less that the rate it means that the software preparing the buffer is not keeping up with that rate.

1ms rate is normally simple for a Kinetis to keep up with - including the slowest KL parts - so you will need to review the overall software design (and USB driver design) to understand the issue.

See
https://www.utasker.com/kinetis/USB_Device.html
and https://www.utasker.com/kinetis/FRDM-K22F.html
for a K22 HID keyboard reference which demonstrate 1000 key strokes a second.

For a complete solution (including general high speed HID operation on any Kinetis part (using a dedicated HID interrupt pipeline for the application) you can download the open source uTasker project from Git Hub. It has been proven for years in industrial applications and so is generally more sensible that trying to fix examples that were possibly never tested for real production work.

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

2,260 Views
balbet
Contributor II

Hi,

Thanks Mark. Actually, bpaddock‌, I know the #define is working fine because if I change the value, the polling interval is responding. Results:

#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x08U)

#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x08U)

Gives a polling of 62 packets/second -> 16ms

#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x04U)

#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x04U)

Gives a polling of 125 packets/second -> 8ms

#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x02U)

#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x02U)

Gives a polling of 250 packets/second -> 4ms

#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x01U)

#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x01U)

Gives a polling of 500 packets/second -> 2ms

So, mjbcswitzerland, it doesn't seem an issue with the speed of my software (I'm using HIDSharp with C#). Actually, to make sure this wasn't a software issue, I've placed a packet counter in USB_DeviceHidGenericCallback function, which is incremented by 1 every time a kUSB_DeviceHidEventRecvResponse is received. Then, I reset this packet counter once per second in the main loop. This packet counter is sent as data into the HID data buffer, and my program reads it back, and I'm getting the same 500 packets per second.

Watching the sequence, the next logical step was decreasing the FS_HID_GENERIC_INTERRUPT_IN_INTERVAL to 0, but I'm still getting 500 packets per second.

Any other ideas?

Thank you!

0 Kudos

2,260 Views
mjbcswitzerland
Specialist V

Bernat

I don't know how relevant your call-back function countin is since it will be called supposedly each time an IN token was responded to (or sent) and not necessarily each time an IN token is received from the host.

What you need to do is use a USB analyser (you can also try Wireshark and its USB plug-in if you are not equiped for USB developements) to verify that the host is really sending the IN token at 1ms (which I expect to be the case as long as you have configured the interrupt endpoint to correctly request this).

If you see that it sends the IN token at 1000Hz rate and each second one is NAK-ed by the device (which I expect to be the be the case) and only each second one is responed to with data it would confirm that the problem is at the software level since it is hasn't prepared the data in time or because it only prepares the data at 500Hz rate.

You need to understand how the software is working (maybe it is designed to only send at half the rate(?)) and maybe it doesn't use double-buffering technques to ensure no race states can occur. As noted I don't think that the callback test is that meaningful since it only confirms the rate the software is sending the data at and matches the measured rate - this simply proves that it is working at half the hoped rate (which is kown) and doesn't show why.

A test that you may be able to do (assuming the used USB driver is capable of doing double-buffered operations) is to responds with two data messages at each call-back and if it then goes up to 1000Hz it may be a workaround.

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

0 Kudos

2,260 Views
balbet
Contributor II

Hi Mark,

Well, this was really useful. After watching the packets with USBPcap, I removed the USB_DeviceHidSend function from the USB_DeviceHidGenericCallback, so now I'm not responding any message, just receiving the host packet. Doing so I'm able to receive 1000 packets/s. Here it's shown what happens when I'm also replying the packet to the host using the USB_DeviceHidSend function:

No. Time Source Destination Protocol Length Info
11982 5.990051 host 1.17.1 USB 27 URB_INTERRUPT in
11983 5.990111 host 1.17.2 USB 91 URB_INTERRUPT out
11984 5.991012 1.17.2 host USB 27 URB_INTERRUPT out
11985 5.991999 1.17.1 host USB 91 URB_INTERRUPT in
11986 5.992051 host 1.17.1 USB 27 URB_INTERRUPT in
11987 5.992123 host 1.17.2 USB 91 URB_INTERRUPT out
11988 5.993004 1.17.2 host USB 27 URB_INTERRUPT out
11989 5.993998 1.17.1 host USB 91 URB_INTERRUPT in
11990 5.994049 host 1.17.1 USB 27 URB_INTERRUPT in
11991 5.994126 host 1.17.2 USB 91 URB_INTERRUPT out
11992 5.995001 1.17.2 host USB 27 URB_INTERRUPT out
11993 5.995998 1.17.1 host USB 91 URB_INTERRUPT in
11994 5.996008 host 1.17.1 USB 27 URB_INTERRUPT in
11995 5.996060 host 1.17.2 USB 91 URB_INTERRUPT out
11996 5.996995 1.17.2 host USB 27 URB_INTERRUPT out
11997 5.998000 1.17.1 host USB 91 URB_INTERRUPT in
11998 5.998050 host 1.17.1 USB 27 URB_INTERRUPT in
11999 5.998123 host 1.17.2 USB 91 URB_INTERRUPT out
12000 5.999005 1.17.2 host USB 27 URB_INTERRUPT out
12001 5.999998 1.17.1 host USB 91 URB_INTERRUPT in

Actually, also 1000 packets/s are sent, but the device answer is occupying one time slot. Looking at one back/forth transition with its data:

No. Time Source Destination Protocol Length Info
12003 6.000122 host 1.17.2 USB 91 URB_INTERRUPT out

   0000 1b 00 10 10 ac e5 81 80 ff ff 00 00 00 00 09 00 ................
   0010 00 01 00 11 00 02 01 40 00 00 00 00 00 00 00 00 .......@........
   0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
   0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
   0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
   0050 00 00 00 00 00 00 00 00 00 00 00 ...........

12004 6.001006 1.17.2 host USB 27 URB_INTERRUPT out

   0000 1b 00 10 10 ac e5 81 80 ff ff 00 00 00 00 09 00 ................
   0010 01 01 00 11 00 02 01 00 00 00 00 ...........

12005 6.001999 1.17.1 host USB 91 URB_INTERRUPT in

   0000 1b 00 60 0a a8 e5 81 80 ff ff 00 00 00 00 09 00 ..`.............
   0010 01 01 00 11 00 81 01 40 00 00 00 01 e5 00 00 00 .......@........
   0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
   0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
   0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
   0050 00 00 00 00 00 00 00 00 00 00 00 ...........

12006 6.002009 host 1.17.1 USB 27 URB_INTERRUPT in

   0000 1b 00 60 0a a8 e5 81 80 ff ff 00 00 00 00 09 00 ..`.............
   0010 00 01 00 11 00 81 01 00 00 00 00 ...........

It seems the way to go would be that the 64 bytes HID data was replied at the interrupt OUT in the packet nº 12004 above, but instead it's sent separately. At such a low level point I don't have the knowledge to know if it's a software issue or that I'm not calling correctly the USB_DeviceHidSend function at the kinetis side (although I'm doing it the same way as in the generic example).

Thank you very much!

0 Kudos

2,260 Views
bobpaddock
Senior Contributor III

I ran into a case where there are #defines in the HID code that are never actually used.
There is a very badly worded comment that attempts to explain the issue.
Came across to me as "we don't know how to make this work right so we are doing it this way".


Don't have it at hand at the moment, nor I don't recall the exact #define, sorry.