AtomicRobot
Member
Hello all,
Hoping someone can shed some light on these questions. I'm creating a USB device with a TeensyLC, and have successfully altered the usb_desc & usb_dev files as well as adding my own USB device specific files. I can compile my device with Teensyduino. I'm currently trying to reduce latency from information gathered from an IMU (ISM330DHCX) over I2C to when the USB packet is collected by the host/computer.
I've read through this thread: https://forum.pjrc.com/threads/58663-Teensy-USB-delay and checked out that persons github repository https://github.com/maziac/fastestjoystick/blob/master/FastestJoystick.ino and from what I can understand, they tried to push data in to the USB hardware buffer every time the number of packets buffered was 0. However, it looks like in between the data being sent to the USB hardware, it is sent to a buffer in memory via the usb_malloc() function in the usb_mem files. That function is called if the TX_PACKET_LIMIT is greater than the amount of packets at the endpoint (I think). They still encountered a delay of USB poll interval, which leads me to believe that because the standard TX_PACKET_LIMIT is set to 3 (at least for Joysticks), the data that needs to be sent over USB will be sent to that buffer first, before being given over to the actual USB hardware in the chip.
If my device only has one endpoint for transmitting, would setting the TX_PACKET_LIMIT to 0 bypass the buffer created by usb_malloc(), and allow for lower latency (if I have my device set to only call my usb send function every poll interval? Would this be a bad idea? From comments in this code, the TX_PACKET_LIMIT is there to prevent starving endpoints for memory.
related code:
Hoping someone can shed some light on these questions. I'm creating a USB device with a TeensyLC, and have successfully altered the usb_desc & usb_dev files as well as adding my own USB device specific files. I can compile my device with Teensyduino. I'm currently trying to reduce latency from information gathered from an IMU (ISM330DHCX) over I2C to when the USB packet is collected by the host/computer.
I've read through this thread: https://forum.pjrc.com/threads/58663-Teensy-USB-delay and checked out that persons github repository https://github.com/maziac/fastestjoystick/blob/master/FastestJoystick.ino and from what I can understand, they tried to push data in to the USB hardware buffer every time the number of packets buffered was 0. However, it looks like in between the data being sent to the USB hardware, it is sent to a buffer in memory via the usb_malloc() function in the usb_mem files. That function is called if the TX_PACKET_LIMIT is greater than the amount of packets at the endpoint (I think). They still encountered a delay of USB poll interval, which leads me to believe that because the standard TX_PACKET_LIMIT is set to 3 (at least for Joysticks), the data that needs to be sent over USB will be sent to that buffer first, before being given over to the actual USB hardware in the chip.
If my device only has one endpoint for transmitting, would setting the TX_PACKET_LIMIT to 0 bypass the buffer created by usb_malloc(), and allow for lower latency (if I have my device set to only call my usb send function every poll interval? Would this be a bad idea? From comments in this code, the TX_PACKET_LIMIT is there to prevent starving endpoints for memory.
related code:
Code:
usb_packet_t * usb_malloc(void)
{
unsigned int n, avail;
uint8_t *p;
__disable_irq();
avail = usb_buffer_available;
n = __builtin_clz(avail); // clz = count leading zeros
if (n >= NUM_USB_BUFFERS) {
__enable_irq();
return NULL;
}
//serial_print("malloc:");
//serial_phex(n);
//serial_print("\n");
usb_buffer_available = avail & ~(0x80000000 >> n);
__enable_irq();
p = usb_buffer_memory + (n * sizeof(usb_packet_t));
//serial_print("malloc:");
//serial_phex32((int)p);
//serial_print("\n");
*(uint32_t *)p = 0;
*(uint32_t *)(p + 4) = 0;
return (usb_packet_t *)p;
}
Code:
int usb_imu_ao_send(void)
{
uint32_t wait_count=0;
usb_packet_t *tx_packet;
while (1) {
if (!usb_configuration) {
return -1;
}
if (usb_tx_packet_count(IMU_AO_ENDPOINT) < TX_PACKET_LIMIT) {
tx_packet = usb_malloc();
if (tx_packet) break;
}
if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
transmit_previous_timeout = 1;
return -1;
}
yield();
}
transmit_previous_timeout = 0;
memcpy(tx_packet->buf, usb_imu_ao_data, IMU_AO_SIZE);
tx_packet->len = IMU_AO_SIZE;
usb_tx(IMU_AO_ENDPOINT, tx_packet);
return 0;
}