cancel
Showing results for 
Search instead for 
Did you mean: 

What is the issue with the USB Custom HID Low Level Driver?

SPfis.1
Associate II

For a STM32L433CB I generated the Custom HID code using CubeMX version 6.2.1 and the Cube FW_L4 V1.17.0

The CUSTOM_HID_FS_BINTERVAL   is set to 5ms and I placed a Custom HID Descriptor. Also I adjusted USBD_CUSTOMHID_OUTREPORT_BUF_SIZE and USBD_CUSTOM_HID_REPORT_DESC_SIZE  so it fits to my descriptor. After the first Message is transmitted, using the function "USBD_CUSTOM_HID_SendReport" I can see in a USB analyzer an endless stream of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER frames with the expected size. Roughly every 5ms there is a new message.

After searching through the Cube generated HAL code I found that in the file "stm32l4xx_hal_pcd.c" quit at the bottom of the function "PCD_EP_ISR_Handler" the function HAL_PCD_EP_DB_Transmit is called all the time. This function handles Endpoints of the type "interrupt" but is in my opinion designed to handle endpoints which are using doublebuffering. But our HID Endpoint is singlebuffered as we can see in the file "usdb_conf.c".

After I wrote my custom handler for USB_EP_CTR_TX Interrupts I got it to work.

For now I think I fixed the issue.

Did anyone had the same issue? Maybe I can help to fix it...

EDIT:

Since my code works after some tests I post the patch here. Keep in mind that I use it to always transmit 64byte "single" frames and I have a transmission timeout mechanism in my application.

So in the file stm32l4xx_hal_pcd.c in the function " HAL_StatusTypeDef PCD_EP_ISR_Handler" at line number 2500 right after:

          else
          {
            /* Transfer is not yet Done */
            ep->xfer_buff += TxByteNbre;
            ep->xfer_count += TxByteNbre;
            (void)USB_EPStartXfer(hpcd->Instance, ep);
          }
        }

I inserted the following code:

        else if((ep->type == EP_TYPE_INTR) && ep->doublebuffer == 0) {
            /* multi-packet on the NON control IN endpoint */
            TxByteNbre = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
            if (ep->xfer_len > TxByteNbre)
            {
              ep->xfer_len -= TxByteNbre;
            }
            else
            {
              ep->xfer_len = 0U;
            }
 
            /* Zero Length Packet? */
            if (ep->xfer_len == 0U)
            {
              /* TX COMPLETE */
  #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
              hpcd->DataInStageCallback(hpcd, ep->num);
  #else
              HAL_PCD_DataInStageCallback(hpcd, ep->num);
  #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
            }
        }

Here again as an applicable patch:

diff --git a/stm32l4xx_hal_pcd.c b/stm32l4xx_hal_pcd.c
index 3a3d967342b9560ad96b0c19c829dc800c8ee527..68fd199979281a75b840ae095286093895fa01f0 100644
--- a/stm32l4xx_hal_pcd.c
+++ b/stm32l4xx_hal_pcd.c
@@ -2497,6 +2497,29 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
             (void)USB_EPStartXfer(hpcd->Instance, ep);
           }
         }
+        else if((ep->type == EP_TYPE_INTR) && ep->doublebuffer == 0) {
+            /* multi-packet on the NON control IN endpoint */
+            TxByteNbre = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
+            if (ep->xfer_len > TxByteNbre)
+            {
+              ep->xfer_len -= TxByteNbre;
+            }
+            else
+            {
+              ep->xfer_len = 0U;
+            }
+
+            /* Zero Length Packet? */
+            if (ep->xfer_len == 0U)
+            {
+              /* TX COMPLETE */
+  #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+              hpcd->DataInStageCallback(hpcd, ep->num);
+  #else
+              HAL_PCD_DataInStageCallback(hpcd, ep->num);
+  #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+            }
+        }
         /* Double Buffer Iso/bulk IN (bulk transfer Len > Ep_Mps) */
         else
         {

11 REPLIES 11
Legacy member
Not applicable

I have exactly the same problem. I have implement a Custom Hid project, just like yours, and I'm able to send my message only once.

I don't have the knowledge to analyze the usb stack, so I have stalled the project.

I would like to mention that the same project was working correctly with a previous version of the stack (I don't remember the version).

SPfis.1
Associate II

Yes, it was the same for me. With an older Cube Package version it worked. Now a day later and after some more testing, my patch in the low level driver still works fine.

Legacy member
Not applicable

Can you share your patch?​

SPfis.1
Associate II

done. see above.

Legacy member
Not applicable

I will try it on Monday and I will come back with the result. Thank you very much.​

Legacy member
Not applicable

I have applied the patch and everything is working fine :grinning_face::grinning_face::grinning_face:. Thank you very much.

SPere.5
Associate II

Hello friend,

Same problem with uC STM32F072 -> In my case the libraries generated for the F versions are quite different than for the L, I tried your patch but it did not work in my case (I guess for F versions), I tried to modify the STM library but I do not reach this level. In my case I can send DATA2 times then the function stops working a beakpoint in the callback and after 2 send reports, the STM32 does not breaks in the callback anymore. I tried your modification and I feel the problem is there, maybe you can help me!. Two weeks on this I am a bit desperate.

Greetings.

SPere.5
Associate II

I managed to make it work, compiled the same project with previous version of STMCubeMX (now I used latest version from 5.xx release. it is 5.2.0) I generated the code for TrueStudio, the previous than used in CubeIDE and imported the project in CubeIDE, finally it is working. The problem was in the latest release of STM32CubeIDE they are not managing properly HAL libraries. Of course a STMicroelectronics mistake.

PArno.1
Associate

Thank you, this was a life-saver. I ran into the same issue using custom HID on STM32G491 and the above fix worked nicely.