This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Trouble with usbd_hid_get_report_trigger on STM32F4

Hello
I am having some issues with usbd_hid_get_report_trigger on a STM3241G-EVAL board. If I write too much too fast it ends up looping in a hidden function inside USB_CM3.lib.

I have done some software usb tracing in Windows, and it looks that this happens when Windows encounter a USBD_STATUS_XACT_ERROR on the interrupt transfer, and Windows then issues an ABORT PIPE and then a RESET PIPE_AND_CLEAR STALL. USB_CM3 doesnt recover from this it seems.

My Endpoint and Report size is 64 bytes, and I have set polling to 1ms. This is the only adjustments I have made to the standard HID-example, and this results in the error. I dont encounter this error using reportsize of 1 byte and polling every ms.

Does anyone have a clue how to handle this? It is a bit hard to debug without USB_CM3 lib sources.

This is the function that keeps on looping in USB_CM3.lib
0x08002696 B198 CBZ r0,0x080026C0
0x08002698 8862 LDRH r2,[r4,#0x02]
0x0800269A 2A00 CMP r2,#0x00memcpy (0x08001874)
0x0800269C D1FB BNE 0x0800269614]

Call stack shows main and 0x08002698 from above.

  • That assembly dump got wrong, it looks like this:
    0x0800269A B198 CBZ r0,0x080026C4
    0x0800269C 8862 LDRH r2,[r4,#0x02]
    0x0800269E 2A00 CMP r2,#0x00
    0x080026A0 D1FB BNE 0x0800269A

  • I'm not using Keil RL-USB lib, so, this is just my impression.

    > If I write too much too fast
    > it looks that this happens when Windows encounter a USBD_STATUS_XACT_ERROR on the interrupt transfer

    Sound like usbd_hid_get_report_trigger() overwrites the interrupt IN endpoint, before the last transaction completes on this EP. And then, corrupted packet has sent to host. It results in USBD_STATUS_XACT_ERROR (transaction error) on host.

    You would be better to contact with Keil support on this issue, to let them know usbd_hid_get_report_trigger() implementation requires to see transaction completion.

    Temporarily, try this workaround.

    usbd_hid_get_report() raise a flag, which means the interrupt endpoint is available.

    volatile U8 hid_int_ep_available = TRUE;
    
    int usbd_hid_get_report (U8 rtype, U8 rid, U8 *buf, U8 req) {
    
      switch (rtype) {
        case HID_REPORT_INPUT:
          switch (rid) {
             case 0:
              switch (req) {
                ...
                case USBD_HID_REQ_EP_INT:
                  hid_int_ep_available = TRUE;   // transaction completes on the interrupt IN EP
                  break;
              }
               break;
          }
          break;
      }
      return (0);
    }
    

    Before usbd_hid_get_report_trigger() call, refer to this flag.

    if ( hid_int_ep_available ) {
      hid_int_ep_available = FALSE;
      usbd_hid_get_report_trigger( ... );        // put another report to the IN EP
    }
    

    Tsuneo

  • Thanks for your comment. I actually had this in mind and tested this, but for some reason usbd_hid_get_report only gets called after many many calls to usbd_hid_get_report_trigger(). From then on it is called after every usbd_hid_get_report_trigger(). I find this a bit strange, and dont see any reasonable explaination for this.

    Anyways, I am just evaluating the Professional license including RL-USB, but my first impression is not that well, and it turns out the sourcecode isnt even included in the Pro license.

    I'll probably go on and evaluate other USB stacks for my project. I'll be happy to receive comments on this if anyone has good experience with USB drivers for the STM32F4. Next out is USBX from rtos.com I think.

  • usbd_hid_get_report only gets called after many many calls to usbd_hid_get_report_trigger(). From then on it is called after every usbd_hid_get_report_trigger().

    While enumeration of the device is going on, no transaction occurs on the HID interrupt IN endpoint. Maybe, you are seeing this period.

    RL-ARM User's Guide tells about usbd_hid_get_report_trigger(),
    www.keil.com/.../rlarm_usbd_hid_get_report_trigger.htm
    BOOL usbd_hid_get_report_trigger(...)

    Return Value: A boolean value indicating whether the trigger function executed successfully.

    It means that this function fails until the last transaction finishes.
    But your finding suggests that overwrite to the endpoint buffer occurs on STM32 implementation. Most likely, it's a bug of the library.
    No one can fix it without library source code.
    Contact to Keil support.

    Tsuneo