Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: Teensy 4.0 RawHID.recv() lock up

  1. #1

    Teensy 4.0 RawHID.recv() lock up

    Hi,

    We used Teensy 3.2 for years in our project, and would continue using them, unfortunately, as you know, T3.2s are not possible to get at the moment. So, given that 4.0s are still available, I wanted to try to switch.

    In our sketch, we manually update stepper motors and need the loop() spinning at a high frequency to update our proprietary acceleration logic.
    In the same loop, we also need to receive commands from a PC at fairly high frequency (a few dozens of HZ).

    We do this on T3.2 simply by placing RawHID.recv(readBuffer, 0); in the main loop. Literally:
    Code:
    void loop() 
    {
      
      unsigned char readBuffer[64] = {0};
      RawHID.recv(readBuffer, 0);
    
      // Process buffer, update stepeprs, etc
    }
    This used to work fine on T3.2m where RawHID.recv() takes 3-4 microseconds at 72MHz

    Now, with T4, the RawHID.recv() seems to take a fixed 1000 microseconds. So, we need to figure out the way to
    1. keep the main loop running at high frequency (at least 10,000 Hz)
    2. make sure we do not miss commands from the PC

    I saw the discussion here: https://forum.pjrc.com/threads/59881...ht=RawHID.recv

    Not sure I fully understand what the final resolution was. Is it possible to run RawHID.recv() without that 1000us delay? Even if we throttle calling it to say 50HZ, it would still consume 5% of the entire CPU time, regardless of clock speed, and at least one cycle will be stuck, and we will get errors in other parts of our code.

    I am running TD 1.56, Arduino 1.8.19

    Thanks!

  2. #2
    Any thoughts on this? Are we doing something wrong with how we check for data from PC?

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,516
    Sorry, I was playing with RAWHID awhile ago in To see if I could make it work with 512 byte packets instead of 64 and it was working...

    Might help to know what your host side code is doing.

  4. #4
    The host doing nothing, very occasionally it sends a command that the Teensy reads and interprets, but for the sake of this discussion - we can ignore the host PC. The 1000us delay inside RawHID.recv() is always there.

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,516
    Understood:

    I see the difference between the T3.x version of code and T4.x version of code:

    In the 3.x we have:
    Code:
    int usb_rawhid_recv(void *buffer, uint32_t timeout)
    {
    	usb_packet_t *rx_packet;
    	uint32_t begin = millis();
    
    	while (1) {
    		if (!usb_configuration) return -1;
    		rx_packet = usb_rx(RAWHID_RX_ENDPOINT);
    		if (rx_packet) break;
    		if (millis() - begin > timeout || !timeout) return 0;
    		yield();
    	}
    	memcpy(buffer, rx_packet->buf, RAWHID_RX_SIZE);
    	usb_free(rx_packet);
    	return RAWHID_RX_SIZE;
    }
    Where in the T4.x we have:
    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;
    }
    Notice the lines:
    3x: if (millis() - begin > timeout || !timeout) return 0;
    4x: if (systick_millis_count - wait_begin_at > timeout) {

    try changing the 4x code like:
    if ((systick_millis_count - wait_begin_at > timeout) || !timeout) {

    And see if works better for you

  6. #6
    That's it! Thank you so much!!! Quick tests show that small buffers are getting through, and that the 1000us delay is gone.

    I only hope this does not break something else. Looks like this may have been done on purpose ? Otherwise why would this code be changed like that?

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,516
    Something simple that was probably overlook or someone fixed for one but not other

  8. #8
    I am not involved at all in the development cycle of this code at all, so apologies for a dumb question - how do we normally handle stuff like this? Can we file it as an issue to be solved with the next TD release? Happy to file a bug on github, just dont know where.

  9. #9
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,516
    I will probably make fix as mentioned against GitHub paulstoffregen cores and hopefully get it pulled in for next beta

  10. #10
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,516
    Paul issue PR. Only did rudimentary testing.
    https://github.com/PaulStoffregen/cores/pull/647

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •