Get notification on usb poll

Status
Not open for further replies.

Maziac

Member
Hi,

I would like to use a Teensy LC to check the polling rate of the USB Host (i.e. PC).
Therefore I would like to toggle a digital out pin everytime that the PC polls the teensy device.

Is this possible?
What API can I use for it?
 
I now found that 'usb_joystick_send' does wait until the next poll. But I haven't yet understood how the wait does work.

For me it seems that it waits at this location in usb_tx:
b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0);

Is this correct? Does anybody know?

And if so: what actually makes the code wait for the usb poll?
 
I have not worked on this part of the USB Code at all, only some on the USB Host code for T3.6 and T4, so take this with a grain of salt...
There is some information up in the PDF associated with the LC in Chapter 35. Also there is lots more information up in the official USB documents...


There are lots of things going that go on behind the scenes with USB stuff.

First off the usb_joystick_send does NOT wait for the send to complete. That is the code does:
Code:
int usb_joystick_send(void)
{
        uint32_t wait_count=0;
        usb_packet_t *tx_packet;

	//serial_print("send");
	//serial_print("\n");
        while (1) {
                if (!usb_configuration) {
			//serial_print("error1\n");
                        return -1;
                }
                if (usb_tx_packet_count(JOYSTICK_ENDPOINT) < TX_PACKET_LIMIT) {
                        tx_packet = usb_malloc();
                        if (tx_packet) break;
                }
                if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
                        transmit_previous_timeout = 1;
			//serial_print("error2\n");
                        return -1;
                }
                yield();
        }
	transmit_previous_timeout = 0;
	memcpy(tx_packet->buf, usb_joystick_data, JOYSTICK_SIZE);
        tx_packet->len = JOYSTICK_SIZE;
        usb_tx(JOYSTICK_ENDPOINT, tx_packet);
	//serial_print("ok\n");
        return 0;
}
The wait here is not for this send to complete, but if necessary it will wait to allocate a logical tx_packet out of a pool of packets. The code is setup to not allow more than a maximum number of Joystick messages to be pending. In this case I believe TX_PACKET_LIMIT is 3... So only 3 outstanding joystick messages will be pending in thte output queue.

The USB hardware when it is polled for the next packet to output, it will retrieve the next packet from the list to send. If the USB system properly sends out that packet, it will release that sent packet from the list, which if it was associated with our end point will decrement the count of pending messages, which should then allow this usb_joystick_send, to allocate a new tx_buffer, and exit the loop, and then copy the data in and call usb_tx to queue it up...

Again there is a lot more going on.
 
I would like to use a Teensy LC to check the polling rate of the USB Host (i.e. PC).
Therefore I would like to toggle a digital out pin everytime that the PC polls the teensy device.

Is this possible?

It's probably not possible, at least in a highly reliable way.

What API can I use for it?

There's certainly no API for this. You'll need to hack the low-level USB code in usb_dev.c.

Maybe you'd try adding code into the usb_isr() function. You can see there's several cases for the types of interrrupt events, and whether the event is on endpoint 0 or a non-zero endpoint. Maybe you could check the 4 bit endpoint number there and toggle the pin if needed?

But this will only tell you when a packet you previously prepared has actually been transmitted.

The difficult part is when the host polls Teensy and you've not prepared any packet to transmit. As far as I know, there isn't any way for the USB hardware (running in device mode) to notify you that the host polled an endpoint and Teensy's hardware automatically transmitted a NAK.
 
Thanks very much for the answers.

@KurtE
If I understand correct the send routine does not directly wait on a usb poll but writes into a queue.
So as long as there are packets available it will not wait.
But as soon as the queue is filled it waits until a packet from the queue (usb) is read by the usb poll.

This would also mean that if a joystick has a 3 packets queue and is polled with 1ms it will always have a 3 ms delay:
At startup the queue is immediately filled with packets 0, 1 and 2.
Then the SW waits to write the next packet (3).
As soon as the usb is polled the usb will read packet 0 and packet 3 is put in the queue by the SW.
Is this assumption correct?

@PaulStoffregen
The difficult part is when the host polls Teensy and you've not prepared any packet to transmit. As far as I know, there isn't any way for the USB hardware (running in device mode) to notify you that the host polled an endpoint and Teensy's hardware automatically transmitted a NAK.
That's a pity. But if I understand correct, if I would always transmit a (dummy) packet I could get this info.
 
Yes - if I understand what you are saying. If you are just hanging there queuing messages and always spining on that wait, then yes each message will go out about 3ms after you queued it... Assuming there is not other USB activity going on.

As for detecting more USB stuff, there appears to also be an interrupt that can be triggered for Start of Frame messages... Not sure if that is often enough for you.
 
Status
Not open for further replies.
Back
Top