BrunoB81HK
Member
I did a post on this subject a while back, this is the updated/revised suggestion.
I'm using RawHID with a Teensy 4.1 in my project and I need a control loop that run at at least 1kHz. The code looks a bit like this :
I set the send and receive timeout to 0 and measured the computing time. To my surprise, the computing time is around 300 us (0,3 ms), but the loop frequency is at almost exactly 500 Hz (2000 us). I dug a little bit in the teensy4 core source code and I realized that the timeout is only compared with > instead of >=. Here is the said code from cores/teensy4/usb_rawhid.c :
To solve this problem, I have 2 suggestions:
I think suggestion #1 is especially the best since it solve the issue that cause the timeout to always be at least 1 ms to long.
Request: Implement those changes or something similar in the source code.
I'm using RawHID with a Teensy 4.1 in my project and I need a control loop that run at at least 1kHz. The code looks a bit like this :
Code:
int main(int argc, char *argv[])
{
/// Setup Code
while(true)
{
RawHID.recv(buffer, 0);
/// Some computing...
RawHID.send(buffer, 0);
}
}
I set the send and receive timeout to 0 and measured the computing time. To my surprise, the computing time is around 300 us (0,3 ms), but the loop frequency is at almost exactly 500 Hz (2000 us). I dug a little bit in the teensy4 core source code and I realized that the timeout is only compared with > instead of >=. Here is the said code from cores/teensy4/usb_rawhid.c :
Code:
int usb_rawhid_recv(void *buffer, uint32_t timeout)
{
uint32_t wait_begin_at = systick_millis_count;
uint32_t tail = rx_tail;
while (1) {
if (!usb_configuration) return -1; // usb not enumerated by host
if (tail != rx_head) break;
if (systick_millis_count - wait_begin_at > timeout) {
return 0;
}
yield();
}
// digitalWriteFast(0, LOW);
if (++tail > RX_NUM) tail = 0;
uint32_t i = rx_list[tail];
rx_tail = tail;
memcpy(buffer, rx_buffer + i * RAWHID_RX_SIZE, RAWHID_RX_SIZE);
rx_queue_transfer(i);
//memset(rx_transfer, 0, sizeof(rx_transfer));
//usb_prepare_transfer(rx_transfer + 0, rx_buffer, RAWHID_RX_SIZE, 0);
//usb_receive(RAWHID_RX_ENDPOINT, rx_transfer + 0);
return RAWHID_RX_SIZE;
}
int usb_rawhid_send(const void *buffer, uint32_t timeout)
{
transfer_t *xfer = tx_transfer + tx_head;
uint32_t wait_begin_at = systick_millis_count;
while (1) {
if (!usb_configuration) return -1; // usb not enumerated by host
uint32_t status = usb_transfer_status(xfer);
if (!(status & 0x80)) break; // transfer descriptor ready
if (systick_millis_count - wait_begin_at > timeout) return 0;
yield();
}
uint8_t *txdata = txbuffer + (tx_head * RAWHID_TX_SIZE);
memcpy(txdata, buffer, RAWHID_TX_SIZE);
arm_dcache_flush_delete(txdata, RAWHID_TX_SIZE );
usb_prepare_transfer(xfer, txdata, RAWHID_TX_SIZE, 0);
usb_transmit(RAWHID_TX_ENDPOINT, xfer);
if (++tx_head >= TX_NUM) tx_head = 0;
return RAWHID_TX_SIZE;
}
To solve this problem, I have 2 suggestions:
- Change the timeout compare (line 107 and line 134) from:
Code:if (systick_millis_count - wait_begin_at > timeout) return 0;
Code:if (systick_millis_count - wait_begin_at >= timeout) return 0;
- Change the timeout compare (line 107 and line 134) from:
Code:if (systick_millis_count - wait_begin_at > timeout) return 0;
Code:if (systick_millis_count - wait_begin_at > timeout || !timeout) return 0;
I think suggestion #1 is especially the best since it solve the issue that cause the timeout to always be at least 1 ms to long.
Request: Implement those changes or something similar in the source code.