cancel
Showing results for 
Search instead for 
Did you mean: 

issue with STM32WB55 USB Custom Hid using V1.11.1 firmware pack.

MBuen.1
Senior

Hello guys, how are u? Hope you're all fine =)

I had my application developed using V.10.1 version firmware pack . It was requested to me to update firmware to use V1.11.1 firmware pack. As i upgraded, several things messed up, including CustomHID.

Here's what is happening:

In CUSTOM_HID_OutEvent_FS function, my device acknowlegde the received package using

USBD_CUSTOM_HID_SendReport. This was working perfectly with V1.10.1. Now that i upgraded, my whole USB comm gets messed up after the first sent ACK. After the first sent package, my application can't received neither send data via USB . If i remove the ACK send, i'm able to continuous receiving data.

What i noticed after updating:

PCB and USB LL libraries got changed. After plenty debugging, i notice that this specific function was messing all up: PCD_EP_ISR_Handler.

This function changed from V1.10.1 update to V1.11.1. I studied this function and USB code flow and discovered a change that made my USB comm back to work. This are the last lines of EP_ISR_Handler function:

/* Manage Bulk Single Buffer Transaction */
        if ((ep->type == EP_TYPE_BULK) && ((wEPVal & USB_EP_KIND) == 0U))
        {
          /* 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 */
          }
          else
          {
            /* Transfer is not yet Done */
            ep->xfer_buff += TxByteNbre;
            ep->xfer_count += TxByteNbre;
            (void)USB_EPStartXfer(hpcd->Instance, ep);
          }
        }
        /* Double Buffer Iso/bulk IN (bulk transfer Len > Ep_Mps) */
        else
        {
          (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
        }
      }

What made my USB comm back to work was changing HAL_PCD_EP_DB_Transmit to HAL_PCD_EP_Transmit in line 37 of code snippet above.

I'm far from being a USB expert and being honest, i don't know what are the exactly effects that this function change does to USB flow. What i know is that i shouldn't modified ST Drivers for my application to work.

My custom HID was already working, following tutorial available on ST youtube channel. I'm using usb settings exactly as described in the tutorial for 64 bytes packages receiving/sending.

Things i already tried:

-> Created a project with V1.11.1 only using CUSTOM Hid. Got the same behaviour.

-> Tried to use V1.11.0. Got the same behaviour.

All that explained, does someone could give me a hint of what should i do? I NEED to update the firmware pack to a newest version.

1 ACCEPTED SOLUTION

Accepted Solutions
Amel NASRI
ST Employee

Hi @KYin.2​ ,

You are most welcome!

To completely fix the issue for all families, a sanity check is required.

For STM32WB, the fix is already implemented and is exactly on line 1854 of stm32wbxx_hal_pcd.c as you pointed it.

This was reported with Internal ticket number: 110174 (PS: This is an internal tracking number and is not accessible or usable by customers).

I'll create a new internal ticket related to STM32G4, and I'll keep you informed.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

3 REPLIES 3
Amel NASRI
ST Employee

Hi @MBuen.1​ ,

You are far from being an USB expert, the same for me 🙂 . But I can help you by reporting the issue you highlighted to our experts.

I thank you for sharing the solution you found, I'll share it as well to confirm if it is all you have to do or not.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

KYin.2
Associate II

Hi @MBuen.1

Just wanted to note, I also ran into the exact same issue with my application with STM32G474RE.

Thank you for the fix. I can now continuously receive data after the first send. However, my device does not appear to send anymore data afterwards.

What were the exact arguments that you passed into the HAL_PCD_EP_Transmit function?

It appears that there is not proper management for interrupt endpoint TX requests.

I've found a solution that works to be this (at least for single packet transfers)

It seems that the code labeled "manage bulk single buffer transaction" is really meant for "manage single buffer non-control transaction". (This also implies it does NOT service isochronous transactions as those are always double buffered). The change in question is on line 9 of the code snippet, which is on line 1854 of the stm32g4xx_hal_pcd.c file.

I added a check for interrupt endpoint, as those are never double buffered. It seems when the library was refactored, interrupt endpoints were overlooked as everyone typically uses CDC, Audio, or Mass Storage, which makes use of bulk or isochronous endpoints.

if ((wEPVal & USB_EP_CTR_TX) != 0U)
      {
        ep = &hpcd->IN_ep[epindex];
 
        /* clear int flag */
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
 
        /* Manage Single Buffer Transaction */
        if (((ep->type == EP_TYPE_BULK) && ((wEPVal & USB_EP_KIND) == 0U)) || (ep->type == EP_TYPE_INTR))
        {
          /* 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 */
          }
          else
          {
            /* Transfer is not yet Done */
            ep->xfer_buff += TxByteNbre;
            ep->xfer_count += TxByteNbre;
            (void)USB_EPStartXfer(hpcd->Instance, ep);
          }
        }
        /* Double Buffer Iso/bulk IN (bulk transfer Len > Ep_Mps) */
        else
        {
          (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
        }
      }

If you must use STM32CubeIDE or are constantly regenerating a CubeMX project, a really ugly hack to save yourself trouble is to uncheck "call HAL handler" in the NVIC settings, and copy the existing handler into a user function. Then have the interrupt target your new user handler. In the user handler, instead of calling "PCD_EP_ISR_Handler", copy this into another user function, and make the above change to that user function. Then modify the user copied HAL_PCD_IRQ_Handler to call the new user PCD_EP_ISR_Handler that has the changes. This is really ugly, and it would be much preferred if ST could push a hotfix for this in the firmware packages.

This is what the old HAL code looked like and and it can be seen why it worked, and also why they felt a need to refactor it. It's also clear how such a bug can be made. Overlooked the interrupt endpoint.

Reminder:

  • control endpoint transactions are handled separately in the ISR.
  • interrupt endpoints are never double buffered, due to their (relatively) low frequency, periodic nature.
  • bulk endpoints are the optionally double buffed endpoints in question.
  • isochronous endpoints are always double buffered.
/* Manage all non bulk transaction or Bulk Single Buffer Transaction */
        if ((ep->type != EP_TYPE_BULK) ||
            ((ep->type == EP_TYPE_BULK) && ((wEPVal & USB_EP_KIND) == 0U)))

Hi @Amel NASRI​ ​, if you could, can you add to the issue report that it has been experienced by multiple users? I appreciate the help you are providing.

Thank you.

-Kai Yin

Amel NASRI
ST Employee

Hi @KYin.2​ ,

You are most welcome!

To completely fix the issue for all families, a sanity check is required.

For STM32WB, the fix is already implemented and is exactly on line 1854 of stm32wbxx_hal_pcd.c as you pointed it.

This was reported with Internal ticket number: 110174 (PS: This is an internal tracking number and is not accessible or usable by customers).

I'll create a new internal ticket related to STM32G4, and I'll keep you informed.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.