Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 26 to 50 of 60

Thread: RawHID.recv() hangs after updating to Teensyduino 1.4.9 or higher for Teensy 4.0

  1. #26
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,506
    Moved to Serial1 for debug_tt rather than out Serial and it is showing ... three blinking T_4.0's on my desk.

    Opps - wondered why USB hub lights were blinking ... 5V pin of a T4 was hitting the USB hood of another ... back to blinking ... until the code hangs ...

    The _isr() is no longer triggering - seems the extra USB messages were keeping it 'more' alive. <edit>: Also hang is after way fewer RawHID.recv message again : "R:21: V:21"

    But indications are the code is not faulting. And loop() has stopped running because I have a print there after some entries - but use/print of "elapsedMicros time;" is funky - just noticed that is us not ms!

    Not sure where my debug TTL to Serial sketch was so I wrote this:
    Code:
    #define LOOP_BAUD   115200
    
    void setup() {
    	Serial.begin(115200);
    	while (!Serial && millis() < 4000 );
    	pinMode( LED_BUILTIN, OUTPUT );
    	digitalWrite(LED_BUILTIN, 1);
    	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
    	Serial1.begin( LOOP_BAUD );
    	Serial2.begin( LOOP_BAUD );
    	Serial.print("\n Serial 1 or 2 USE BAUD::");
    	Serial.println(LOOP_BAUD);
    }
    
    char rdBuff[1025];
    void loop() {
    	if ( Serial.available() ) {
    		int ii;
    		someBlink();
    		while ( (ii = Serial.available()) ) {
    			if ( ii > 1024 )ii = 1024;
    			Serial.readBytes( rdBuff, ii);
    			rdBuff[ii] = 0;
    			Serial.write( rdBuff, ii );
    		}
    	}
    	if ( Serial1.available() ) {
    		int ii;
    		someBlink();
    		while ( (ii = Serial1.available()) ) {
    			if ( ii > 1024 )ii = 1024;
    			Serial1.readBytes( rdBuff, ii);
    			rdBuff[ii] = 0;
    			Serial.write( rdBuff, ii );
    		}
    	}
    	if ( Serial2.available() ) {
    		int ii;
    		someBlink();
    		while ( (ii = Serial2.available()) ) {
    			if ( ii > 1024 )ii = 1024;
    			Serial2.readBytes( rdBuff, ii);
    			rdBuff[ii] = 0;
    			Serial.write( rdBuff, ii );
    		}
    	}
    
    }
    
    uint32_t LastB=0;
    void someBlink() {
    	if ( millis() -LastB > 100) {
    		LastB = millis();
    		digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    	}
    }
    Last edited by defragster; 03-14-2020 at 09:08 PM.

  2. #27
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    @defragster and @Paul - I am trying to localize down. My gut tells me, that here is a clue:
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	3 
Size:	8.8 KB 
ID:	19364

    Now the first three lines are from the ISR:
    Code:
    static void isr(void)
    {
    	//printf("*");
    	digitalWriteFast(0, HIGH);
    
    	//  Port control in device mode is only used for
    	//  status port reset, suspend, and current connect status.
    	uint32_t status = USB1_USBSTS;
    	USB1_USBSTS = status;
    
    	// USB_USBSTS_SLI - set to 1 when enters a suspend state from an active state
    	// USB_USBSTS_SRI - set at start of frame
    	// USB_USBSTS_SRI - set when USB reset detected
    
    	if (status & USB_USBSTS_UI) {
    		digitalWriteFast(1, HIGH);
    		//printf("data\n");
    		uint32_t setupstatus = USB1_ENDPTSETUPSTAT;
    		//printf("USB1_ENDPTSETUPSTAT=%X\n", setupstatus);
    		digitalWriteFast(2, HIGH);
    		while (setupstatus) {
    			USB1_ENDPTSETUPSTAT = setupstatus;
    			setup_t s;
    			do {
    				USB1_USBCMD |= USB_USBCMD_SUTW;
    				s.word1 = endpoint_queue_head[0].setup0;
    				s.word2 = endpoint_queue_head[0].setup1;
    			} while (!(USB1_USBCMD & USB_USBCMD_SUTW));
    			USB1_USBCMD &= ~USB_USBCMD_SUTW;
    			//printf("setup %08lX %08lX\n", s.word1, s.word2);
    			USB1_ENDPTFLUSH = (1<<16) | (1<<0); // page 3174
    			while (USB1_ENDPTFLUSH & ((1<<16) | (1<<0))) ;
    			endpoint0_notify_mask = 0;
    			endpoint0_setup(s.bothwords);
    			setupstatus = USB1_ENDPTSETUPSTAT; // page 3175
    		}
    		digitalWriteFast(2, LOW);
    		uint32_t completestatus = USB1_ENDPTCOMPLETE;
    The last line is from the rawhid receive.
    Code:
    int usb_rawhid_recv(void *buffer, uint32_t timeout)
    {
    	uint32_t wait_begin_at = systick_millis_count;
    //	digitalWriteFast(0, HIGH);
    	while (1) {
    		if (!usb_configuration) return -1; // usb not enumerated by host
    		uint32_t status = usb_transfer_status(rx_transfer);
    		if (!(status & 0x80)) break; // transfer descriptor ready
    		if (systick_millis_count - wait_begin_at > timeout)  {
    //			digitalWriteFast(0, LOW);
    			return 0;
    		}
    		yield();
    	}
    //	digitalWriteFast(0, LOW);
    	memcpy(buffer, rx_buffer, RAWHID_RX_SIZE);
    	memset(rx_transfer, 0, sizeof(rx_transfer));
    	digitalWriteFast(3, HIGH);
    	usb_prepare_transfer(rx_transfer + 0, rx_buffer, RAWHID_RX_SIZE, 0);
    	usb_receive(RAWHID_RX_ENDPOINT, rx_transfer + 0);
    	digitalWriteFast(3, LOW);
    	return RAWHID_RX_SIZE;
    }
    So you will see we are in the code that is adding the rx_transfer to the receive, when we process the ISR... Again wondering if some timing window issue.

    As the next stuff that goes to Logic analyzer is the hang with the first 2 lines high...

    EDIT: It is hung in run_callbacks, my guess is list is corrupt.
    Last edited by KurtE; 03-14-2020 at 09:54 PM.

  3. #28
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,506
    Good discovery work Kurt.

    I put in an interval timer and it stops too. With just Blink it dies more quickly than with println("."); that triggers more USB activity.

  4. #29
    Junior Member prnthp's Avatar
    Join Date
    Oct 2019
    Posts
    16
    Quote Originally Posted by KurtE View Post
    EDIT: It is hung in run_callbacks, my guess is list is corrupt.
    I had the same hunch and reverted the code in that function back to 1.48. However, it didn't seem to help for me. It seems to hang much later than normally though, after possibly thousands of packets sent.

    From TD 1.48:
    Code:
    static void run_callbacks(endpoint_t *ep)
    {
    	transfer_t *t, *next;
    
    	//printf("run_callbacks\n");
    	t = ep->first_transfer;
    	while (t && (uint32_t)t != 1) {
    		if (!(t->status & (1<<7))) {
    			// transfer not active anymore
    			next = (transfer_t *)t->next;
    			ep->callback_function(t);
    		} else {
    			// transfer still active
    			ep->first_transfer = t;
    			return;
    		}
    		if (next == ep->last_transfer) break;
    		t = next;
    	}
    	// all transfers completed
    	ep->first_transfer = NULL;
    	ep->last_transfer = NULL;
    }
    Last edited by prnthp; 03-14-2020 at 10:25 PM.

  5. #30
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    I know that the code is hung in the usb.c function run_callbacks,
    I am suspecting the list is getting corrupted. probably entry point to itself.
    Again on the previous grouping/nested outputs to Logic Analyzer
    I have the main thread; in the call to schedule_transfer
    Code:
    static void schedule_transfer(endpoint_t *endpoint, uint32_t epmask, transfer_t *transfer)
    {
    	// when we stop at 6, why is the last transfer missing from the USB output?
    	//if (transfer_log_count >= 6) return;
    	digitalWriteFast(3, HIGH);
    
    	//uint32_t ret = (*(const uint8_t *)transfer->pointer0) << 8;
    	if (endpoint->callback_function) {
    		transfer->status |= (1<<15);
    	}
    	__disable_irq();
    	//digitalWriteFast(1, HIGH);
    	// Executing A Transfer Descriptor, page 2468 (RT1060 manual, Rev 1, 12/2018)
    	transfer_t *last = endpoint->last_transfer;
    	if (last) {
    		last->next = (uint32_t)transfer;
    		if (USB1_ENDPTPRIME & epmask) goto end;
    		//digitalWriteFast(2, HIGH);
    		//ret |= 0x01;
    		uint32_t status, cyccnt=ARM_DWT_CYCCNT;
    		do {
    			USB1_USBCMD |= USB_USBCMD_ATDTW;
    			status = USB1_ENDPTSTATUS;
    		} while (!(USB1_USBCMD & USB_USBCMD_ATDTW) && (ARM_DWT_CYCCNT - cyccnt < 2400));
    		//USB1_USBCMD &= ~USB_USBCMD_ATDTW;
    		if (status & epmask) goto end;
    		//ret |= 0x02;
    	}
    	//digitalWriteFast(4, HIGH);
    	endpoint->next = (uint32_t)transfer;
    	endpoint->status = 0;
    	USB1_ENDPTPRIME |= epmask;
    	endpoint->first_transfer = transfer;
    end:
    	endpoint->last_transfer = transfer;
    	__enable_irq();
    	digitalWriteFast(3, LOW);
    }
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	3 
Size:	11.0 KB 
ID:	19366
    That is shown in the second to bottom line. I am guessing that the ISR happens just as we are processing it. and is delayed while we are doing this code and adding it back in while the system is trying to take it out... Or some such thing. Next up will move these digitalWrites within the disable/enable ISRs to verify.

    Edit: Forbot to mention that the last line is the run_callbacks which in the next grouping is left high

  6. #31
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Is it OK that it does the callback for a still active transfer?

  7. #32
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Not sure how this all works, and if it's needed to run all callbacks (and at the moment I have not test setup.)
    But try to replace this
    Code:
            if (t->status & (1<<7)) {
                // found a still-active transfer, new list begins here
                //printf(" still active\n");
                ep->first_transfer = t;
                break;
    with this:
    Code:
            if (t->status & (1<<7)) {
                return;
            }
    This would be a dirty hack that does not call _any_ calback if one transfer is active - but if this helps, we found the reason. But, as said - i don't know if it is allowed not to call the callbacks here.

  8. #33
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,825
    Sorry I'm late to this party. Could someone please point me to the best / latest code to reproduce the problem. I'll set it up here and start digging....

  9. #34
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,506
    What I used was post #18 2nd code block for USB Host Teensyduino-1-4-9-or-higher-for-Teensy-4-0

    And post #19 code for HID Device : hangs-after-updating-to-Teensyduino-1-4-9-or-higher-for-Teensy-4-0

  10. #35
    Junior Member prnthp's Avatar
    Join Date
    Oct 2019
    Posts
    16
    @Paul

    I whipped up a super simple program that just writes a 64 byte HID packet with 0xAB in the first byte every 100 ms to the device with VID: 0x16C0 PID: 0x0486 and usage page 0xFFAB. Unfortunately I only have macOS w/ Xcode at hand so this probably only runs on macOS 10.15. It's using a slightly modified version of hidapi from libusb, since they haven't implemented usage page during connection for some reason.

    https://github.com/prnthp/FloodHID/releases/tag/0.1

    Using post #19 on the T4 w/ TD1.51 like what @defragster suggested, it hangs after just 4-8 writes.
    Click image for larger version. 

Name:	Screen Shot 2020-03-14 at 10.27.18 PM.png 
Views:	1 
Size:	66.2 KB 
ID:	19374

    On TD 1.48, it just goes on forever.
    Click image for larger version. 

Name:	Screen Shot 2020-03-14 at 10.27.59 PM.png 
Views:	1 
Size:	158.4 KB 
ID:	19375

  11. #36
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,506
    That was KurtE's code - it is T_4 Host from T_4 HID device - Breaks in 234 or fewer messages it seems.
    <edit>: Since I had a Teensy on Serial1 I changed line #40 in first HID code to Serial1.printf - and it quit twice in the same :: L:24320 R:234: V:234


    USB RAWHid - cleaned out my edits:
    Code:
    #include <Arduino.h>
    
    void blink(int num);
    void setup()
    {
      Serial.begin(115200);
      Serial1.begin(115200);
      while (!Serial && millis() < 3000) ;
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      delay(500); // Simulate initialization
      pinMode(13, OUTPUT);
      blink(1);
    }
    
    char rx_buffer[64];
    
    elapsedMicros time;
    uint32_t loop_count = 0;
    uint32_t receive_count = 0;
    uint32_t valid_count = 0;
    
    void loop()
    {
      if (time < 100)
      {
        return;
      }
      loop_count++;
      int n = RawHID.recv(rx_buffer, 1);
      if (n > 0)
      {
        receive_count++;
        if (rx_buffer[0] == 0xAB) // Signature
        {
          valid_count++;
          blink(2);
        }
      }
      time = 0;
      if ((loop_count & 0x7f) == 0) Serial.printf("L:%u R:%u: V:%d\n", loop_count, receive_count, valid_count);
    }
    
    void blink(int num)
    {
      for (int i = 0; i < num; i++)
      {
        digitalWrite(13, HIGH);
        delay(10);
        digitalWrite(13, LOW);
        delay(10);
      }
    }

    And the RAWHid USBHost mouse code:
    Code:
    // Simple test of USB Host Mouse/Keyboard
    //
    // This example is in the public domain
    
    #include "USBHost_t36.h"
    
    USBHost myusb;
    USBHub hub1(myusb);
    USBHIDParser hid1(myusb);
    USBHIDParser hid2(myusb);
    USBHIDParser hid3(myusb);
    RawHIDController rawhid1(myusb);
    RawHIDController rawhid2(myusb, 0xffc90004);
    
    USBDriver *drivers[] = {&hub1, &hid1, &hid2, &hid3};
    #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
    const char * driver_names[CNT_DEVICES] = {"Hub1", "HID1" , "HID2", "HID3"};
    bool driver_active[CNT_DEVICES] = {false, false, false, false};
    
    // Lets also look at HID Input devices
    USBHIDInput *hiddrivers[] = {&rawhid1, &rawhid2};
    #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0]))
    const char * hid_driver_names[CNT_DEVICES] = {"RawHid1", "RawHid2"};
    bool hid_driver_active[CNT_DEVICES] = {false, false};
    bool show_changed_only = false;
    
    
    void setup()
    {
      Serial.begin(115200);
      while (!Serial) ; // wait for Arduino Serial Monitor
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      Serial.println("\n\nUSB Host Testing");
      Serial.println(sizeof(USBHub), DEC);
      myusb.begin();
      rawhid1.attachReceive(OnReceiveHidData);
      rawhid2.attachReceive(OnReceiveHidData);
      pinMode(13, OUTPUT);
    }
    
    
    void loop()
    {
      myusb.Task();
    
      if (Serial.available()) {
        int ch = Serial.read(); // get the first char.
        while (Serial.read() != -1) ;
        if (show_changed_only) {
          show_changed_only = false;
          Serial.println("\n*** Show All fields mode ***");
        } else {
          show_changed_only = true;
          Serial.println("\n*** Show only changed fields mode ***");
        }
      }
    
      for (uint8_t i = 0; i < CNT_DEVICES; i++) {
        if (*drivers[i] != driver_active[i]) {
          if (driver_active[i]) {
            Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
            driver_active[i] = false;
          } else {
            Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
            driver_active[i] = true;
    
            const uint8_t *psz = drivers[i]->manufacturer();
            if (psz && *psz) Serial.printf("  manufacturer: %s\n", psz);
            psz = drivers[i]->product();
            if (psz && *psz) Serial.printf("  product: %s\n", psz);
            psz = drivers[i]->serialNumber();
            if (psz && *psz) Serial.printf("  Serial: %s\n", psz);
          }
        }
      }
    
      for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) {
        if (*hiddrivers[i] != hid_driver_active[i]) {
          if (hid_driver_active[i]) {
            Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]);
            hid_driver_active[i] = false;
          } else {
            Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());
            hid_driver_active[i] = true;
    
            const uint8_t *psz = hiddrivers[i]->manufacturer();
            if (psz && *psz) Serial.printf("  manufacturer: %s\n", psz);
            psz = hiddrivers[i]->product();
            if (psz && *psz) Serial.printf("  product: %s\n", psz);
            psz = hiddrivers[i]->serialNumber();
            if (psz && *psz) Serial.printf("  Serial: %s\n", psz);
          }
        }
      }
      // See if we have some RAW data
      if (rawhid1) {
        uint8_t buffer[64];
        digitalWriteFast(13, !digitalReadFast(13));
        memset(buffer, 0, sizeof(buffer));
        buffer[0] = 0xab;
        rawhid1.sendPacket(buffer);
        delay(250);
      }
    
    }
    bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) {
      // Called for maybe both HIDS for rawhid basic test.  One is for the Teensy
      // to output to Serial. while still having Raw Hid...
      if (usage == 0xffc90004) {
        // Lets trim off trailing null characters.
        while ((len > 0) && (data[len - 1] == 0)) {
          len--;
        }
        if (len) {
          Serial.print("RawHid Serial: ");
          Serial.write(data, len);
        }
      } else {
        Serial.print("RawHID data: ");
        Serial.println(usage, HEX);
        while (len) {
          uint8_t cb = (len > 16) ? 16 : len;
          const uint8_t *p = data;
          uint8_t i;
          for (i = 0; i < cb; i++) {
            Serial.printf("%02x ", *p++);
          }
          Serial.print(": ");
          for (i = 0; i < cb; i++) {
            Serial.write(((*data >= ' ') && (*data <= '~')) ? *data : '.');
            data++;
          }
          len -= cb;
          Serial.println();
        }
      }
    
      return true;
    }

  12. #37
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    Good Morning Paul and Defragster and ...

    As mentioned, I decided not to get the headache of figuring out best way to get rawhid program to run on PC and besides was curious about if it would be repeatable with Teensy to Teensy, so did it with the two Teensy sketches mentioned.

    As mentioned it is hanging in the run_callbacks function. My assumption is probably a circular loop.

    I am guessing either there is a timing issue, where some small window of time where we are inserting a new item at the exact time we are removing the previous one.... And/or issue of how does the code handle if there are multiple receives received from the host when the client tries to extract one...

    I thought about trying a band-aid and see if it recovers...
    Code:
    static void run_callbacks(endpoint_t *ep)
    {
    	//printf("run_callbacks\n");
    	transfer_t *first = ep->first_transfer;
    	if (first == NULL) return;
    	digitalWriteFast(4, HIGH);
    
    	// count how many transfers are completed, then remove them from the endpoint's list
    	uint32_t count = 0;
    	transfer_t *t = first;
    	while (1) {
    		if (t->status & (1<<7)) {
    			// found a still-active transfer, new list begins here
    			//printf(" still active\n");
    			ep->first_transfer = t;
    			break;
    		}
    		count++;
    		if ((t == t->next) || ((uint32_t)t->next == 1)) {
    			// reached end of list, all need callbacks, new list is empty
    			//printf(" end of list\n");
    			ep->first_transfer = NULL;
    			ep->last_transfer = NULL;
    			break;
    		}
    		t = (transfer_t *)t->next;
    	}
    	// do all the callbacks
    	while (count) {
    		transfer_t *next = (transfer_t *)first->next;
    		ep->callback_function(first);
    		first = next;
    		count--;
    	}
    	digitalWriteFast(4, LOW);
    }
    Which would only catch a circular loop of one item... By checking it's next pointer to itself...

    But again only a band-aid probably should find where it sets up the condition to begin with.

  13. #38
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    Paul, for what it is worth, my Band-aid can help it to keep running, at least for awhile...
    Code:
    static void run_callbacks(endpoint_t *ep)
    {
    	//printf("run_callbacks\n");
    	transfer_t *first = ep->first_transfer;
    	if (first == NULL) return;
    	digitalWriteFast(4, HIGH);
    
    	// count how many transfers are completed, then remove them from the endpoint's list
    	uint32_t count = 0;
    	transfer_t *t = first;
    	transfer_t *tprev;
    	while (1) {
    		if (t->status & (1<<7)) {
    			// found a still-active transfer, new list begins here
    			//printf(" still active\n");
    			ep->first_transfer = t;
    			break;
    		}
    		count++;
    		tprev = t;
    		t = (transfer_t *)t->next;
    		if ((uint32_t)t == 1) {
    			// reached end of list, all need callbacks, new list is empty
    			//printf(" end of list\n");
    			ep->first_transfer = NULL;
    			ep->last_transfer = NULL;
    			break;
    		}
    		if (t == tprev) {
    			// bandaid
    			digitalWriteFast(5, !digitalReadFast(5));
    			ep->first_transfer = NULL;
    			ep->last_transfer = NULL;
    			break;
    		}
    	}
    	// do all the callbacks
    	while (count) {
    		transfer_t *next = (transfer_t *)first->next;
    		ep->callback_function(first);
    		first = next;
    		count--;
    	}
    	digitalWriteFast(4, LOW);
    }
    It still crashed later, much later.

    Code:
    RawHid Serial: L:114816 R:3724: V:3724  Heap: 20200460
    RawHid Serial: L:114944 R:3728: V:3728  Heap: 20200460
    RawHid Serial: L:115072 R:3732: V:3732  Heap: 20200460
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	4 
Size:	57.6 KB 
ID:	19378
    The last line of the Logic Analyzer output is each transition, is a place where it found a circular loop t == t->next, which it recovered from, but it finally hung a different way.

  14. #39
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    consider the following scenario:

    1st loop is not a active transfer.
    -> count is 1
    2nd loop is active transfer
    -> break
    ->callback gets called for "first"

    that looks suspicious? Or am I wrong?


    Edit: forget that...

  15. #40
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    @PaulStoffregen - What I am wondering is if maybe usb_rawhid should be updated to be closer to usb_seremu

    First things I am wondering about is, the definitions of the transfers and buffers.

    That is with seremu you have:
    Code:
    #define TX_NUM   12
    static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32)));
    DMAMEM static uint8_t txbuffer[SEREMU_TX_SIZE * TX_NUM] __attribute__ ((aligned(32)));
    static uint8_t tx_head=0;
    static uint16_t tx_available=0;
    
    #define RX_NUM  8
    static transfer_t rx_transfer[RX_NUM] __attribute__ ((used, aligned(32)));
    DMAMEM static uint8_t rx_buffer[SEREMU_RX_SIZE * RX_NUM] __attribute__ ((aligned(32)));
    static uint16_t rx_index[RX_NUM];
    static volatile uint8_t rx_head;
    static volatile uint8_t rx_tail;
    and rawhid:
    Code:
    #define TX_NUM   4
    static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32)));
    static uint8_t txbuffer[RAWHID_TX_SIZE * TX_NUM];
    static uint8_t tx_head=0;
    
    static transfer_t rx_transfer[1] __attribute__ ((used, aligned(32)));
    static uint8_t rx_buffer[RAWHID_RX_SIZE];
    So on USB Serial receive you have 8 transfers setup, but for rawhid only 1... Wonder if it would make sense to define multiple?
    and have them queue up?

  16. #41
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Issue can be seen most easy by using Teensy_gateway and putty.

    Use a simple program:
    Code:
    void setup() {}
    void loop() {
     static int i;
     Serial.println(i++);
     delay(500);
    }
    Putty will print the numbers, stops after sending some text.

    Or use this slightly longer sketch (modified from above)
    Code:
    #include <Arduino.h>
    
    void blink(int num);
    void setup()
    {
      Serial.begin(115200);
      Serial1.begin(115200);
      while (!Serial && millis() < 3000) ;
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      delay(500); // Simulate initialization
      pinMode(13, OUTPUT);
      blink(1);
    }
    
    char rx_buffer[64];
    
    elapsedMicros time;
    uint32_t loop_count = 0;
    uint32_t receive_count = 0;
    uint32_t valid_count = 0;
    
    void loop()
    {
      if (time < 100)
      {
        return;
      }
      loop_count++;
      int n = RawHID.recv(rx_buffer, 1);
      if (n > 0)
      {
        receive_count++;
        if (rx_buffer[0] == '\n') // Signature
        {
          rx_buffer[0] = 0;
          valid_count++;
          blink(2);
        }
      }
      time = 0;
      if ((loop_count & 0x7f) == 0) Serial.printf("L:%u R:%u: V:%d\r\n", loop_count, receive_count, valid_count);
    }
    
    void blink(int num)
    {
      for (int i = 0; i < num; i++)
      {
        digitalWrite(13, HIGH);
        delay(50);
        digitalWrite(13, LOW);
        delay(50);
      }
    }
    Press enter until the key-repeat kicks in, and the printing stops.
    Click image for larger version. 

Name:	2020-03-15 20_05_45-Start.png 
Views:	5 
Size:	7.7 KB 
ID:	19379

  17. #42
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    I just pushed up a branch: https://github.com/KurtE/cores/tree/t4_rawhid

    That uses 4 transfers... So far working pretty good up to almost 4000 transfers so far

  18. #43
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Kurt, no change with teensy_gateway & putty.

  19. #44
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    Thanks @Frank B - I did not change the Serial emulation stuff only the RawHID stuff.

    Just got back form getting some sunshine and it still running with count of about 25000.

    My guess is it is still possible to overrun some of these. But the main changes I did was to increase count of RX Transfers to 4.

    And I think probably the most important thing is that I don't look at the transfers to know that they completed, instead I wait for the RX_Event to be called, and then I mark them as available and then process from there. My guess is the current released code hit a specific spot where it caught that the transfer was ready but before the system decided to do the callback... SO I think the ordering things gets done is probably more consistent.

    Next up, is to change the code to instead of look at some fixed one byte, probably keep sequence number and verify getting proper data.

  20. #45
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Yes, i'm speaking of RawHID.
    I've a test-setup now, even connected a serial-debug on Pin17.

    It still stops after exactly 6 packets - with your code, or without. Teenay-usb mode "rawhid".
    Code:
    ***********IMXRT Startup**********
    test 1 -1234567 3
    CCM_ANALOG_PLL_USB1=80003000
      enable USB clocks
    CCM_ANALOG_PLL_USB1=80003040
    need to switch to alternate clock during reconfigure of ARM PLL
    USB PLL is running, so we can use 120 MHz
    Freq: 12 MHz * 88 / 2 / 1
    ARM PLL=80002042
    ARM PLL needs reconfigure
    ARM PLL=80002058
    New Frequency: ARM=528000000, IPG=132000000
    usb_rawhid_configure
    run_callbacks
    rx event, len=32, i=0
    rx event, len=32, i=1
    run_callbacks
    run_callbacks
    rx event, len=32, i=2
    run_callbacks
    rx event, len=32, i=3
    run_callbacks
    rx event, len=32, i=4
    run_callbacks
    rx event, len=32, i=5
    run_callbacks
    rx event, len=32, i=6
    run_callbacks
    rx event, len=32, i=7
    
    ---stop

  21. #46
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    ..ok, looks like it hangs somewere else now.
    you're right

  22. #47
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    Hi Frank,

    Looks like you may have a bunch of debug code turned on in USB? I also ran into issues where the code would not run with some of the debug stuff turned on.
    You might try turning that off and see if it runs then.

    When I last tried it with it outputting to Serial4 it never got the first output.
    Note: I did not go through and figure out why those Serial prints hung the code, but that is when I converted over to using lots of digitalWriteFast and watching with Logic Analyzer

  23. #48
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Good work
    No, please fix ser_emu, too :-)

  24. #49
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    ...okay, that works if you call usb_seremu_flush_input();
    Then you can call it a day

    Good work.

  25. #50
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    @Paul - I put in a PR for you to look at. The PR shows my current two test apps running on two T4 processors
    Current ones send a sequence number for first 4 bytes and compare to the previous number and if different prints that one out.

    https://github.com/PaulStoffregen/cores/pull/455

Posting Permissions

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