Skip to main content
Visitor II
December 6, 2023
Solved

Strange USB Behaviors

  • December 6, 2023
  • 8 replies
  • 3621 views

Greetings,

 

Sorry if I am posting in the wrong place.  Maybe someone can point to the correct forum for me.

Problem: USB HID 04 Joystick intermittently sends incorrect 12-bit analog data.

Micro: STM32F103R8T6

Details: A 1/2 Hz signal applied to analog inputs that vacillates above below an 8-bit boundary (i.e., 2047 to 2048) I sometimes get a value of 1792 or 2303 decimal sent.  It appears as if the upper 4 bits of the 12-bit word is out of sync with the lower 8 bits and subsequently sends 0x700 instead of 0x800 or 0x8FF instead of 0x7FF.

The problem was first discovered using a Microchip 8-Bit microcontroller.  No one could solve the puzzle, se we went with an NXP MK20DX256VLH7 32-bit processor and the problem went away.  NXP has a 1-year lead time, so we switched to ST Micro.  Now the problem has returned with the F103 part.

To eliminate the possibility of data corruption of the USB structure we put in a trap just before the call to: 

USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*) &gameHID, sizeof(struct gameHID_t));

To test for something wrong with the analog DMA data we parsed that data for out-of-bounds conditions, then set a fault flag.  The flag never got set, but the USB data continued to post intermittent erroneous values of 1792 and 2303 on one of the five analog channels.  This issue was confirmed on multiple host PCs using different capture software.

It gets stranger yet.  We complied the same code for an STM32F722 and an STM32F730 micro and the problem disappeared,

I can't believe this is a problem with the chip (or HAL library), so there must be something we are doing wrong with the way we have the USB configured as a Full-Speed USB (both for the F103 and F7xx).

The only thing different between the F103 and the NXP and F7xx chips is the F103 is not USB OTG.

 

Sorry for the long post, but I want to frame the problem as best I can.  Thanks in advance.

    This topic has been closed for replies.
    Best answer by Loren

    Ran without error last night.  I'm going to call this thread as resolved for now.

    I'll run the suggested test of 0x0101...0x0202... tonight as a second verification.

    Thank you for all your help!

    8 replies

    Super User
    December 6, 2023

    Doesn't sound like a USB configuration issue. Sounds like you are overwriting the data before it's actually sent out. Note that USB happens in the background and needs to be valid/unchanged until the sending operation is complete.

    LorenAuthor
    Visitor II
    December 6, 2023

    Thanks for the quick reply!

    The structure that is sent to the HAL USB handler is sent once at the end of the main loop (about 4 mS).

    So, there might be an issue with overwriting data while the USB handler is still sending data. 

    I'll look into a mechanism to determine the last transfer was complete before modifying that data structure and see if that fixes the issue.

    Might there be something with USB OTG that is a factor here?  All the chips that do not have the problem are USB OTG.  Just a thought.

    Super User
    December 6, 2023

    > Might there be something with USB OTG that is a factor here?

    I doubt it.

    You can test the above theory easily. Instead of sending data, send 0x0101, then 0x0202, etc... This is easy and will tell you if you are mixing data between different sends. It will also let you know how often sends fail.

    LorenAuthor
    Visitor II
    December 6, 2023

    Is there a function call that can determine the state of the USB transfer (in-progress vs complete) for this?

    Super User
    December 7, 2023

    Not sure if there's a function, but you can dig into the structure to find it. Look at how the USBD_HID_SendReport determines if it's busy or not and duplicate that check.

    https://github.com/STMicroelectronics/STM32CubeF7/blob/7f25a108012707cc7a643a6bee79947bd068e0ab/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c#L506

    LorenAuthor
    Visitor II
    December 7, 2023

    Perfect, thank you.  I'll try that in the morning.

     

    LorenAuthor
    Visitor II
    December 7, 2023

    This is what I did to quickly test this idea. I added some code to the USBD_HID_SendReport function.

    A local array that is used to transmit the USB data was created.  That local array only gets updated when hhid->state is idle.  The function call USBD_LL_Transmit() now sends the local copy instead of the original array, which should decouple any changes made in main from the USB transfer process... 

    The results are unchanged.  We still get erroneous values of 1792 and 2303.  Something else must be happening.

    uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
    {
    	uint16_t i;
    	uint8_t data [len];
    
     USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
    #endif /* USE_USBD_COMPOSITE */
    
     if (hhid == NULL)
     {
     return (uint8_t)USBD_FAIL;
     }
    
    #ifdef USE_USBD_COMPOSITE
     /* Get the Endpoints addresses allocated for this class instance */
     HIDInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR, ClassId);
    #endif /* USE_USBD_COMPOSITE */
    
     if (pdev->dev_state == USBD_STATE_CONFIGURED)
     {
     if (hhid->state == USBD_HID_IDLE)
     {
     	for (i = 0; i < len; i++)
     	{
     		data [i] = report [i];
     	}
    
     hhid->state = USBD_HID_BUSY;
     (void)USBD_LL_Transmit(pdev, HIDInEpAdd, data, len);
     }
     }
    
     return (uint8_t)USBD_OK;
    }

     

    Super User
    December 7, 2023

    That's worse. Now you're sending a variable on the stack which immediately goes out of scope when this function returns. Same core issue.

    Right idea, bad implementation. You could make data static and size it according to the max possible size to fix these issues.

    static uint8_t data[MAX_LEN];
    LorenAuthor
    Visitor II
    December 7, 2023

    Oh, my!  I see that now.  Thanks.

    LorenAuthor
    Visitor II
    December 7, 2023

    Arg!  Still did not work.  Well, my fault there...

    I found out that I was accidentally modifying the wrong file from a different project.  Not good to be doing two things at once in this IDE.

    So, letting the this run overnight and see what tomorrow brings.

    Thanks for your help.  I really appreciate it.

    Super User
    December 7, 2023

    If you can, I would consider instead sending 0x0101, 0x0202, etc... And if you can capture the sent values on the other side and post them here, that might give you better insight into specifically what can be going wrong, rather than just a general "something isn't quite right".

    LorenAuthor
    Visitor II
    December 7, 2023

    Yeah, that might be a good final check.

     

    Right now it has been running for over an hour with triangle waves from my signal generator with no faults.

    Before it would *** out within 60 seconds. 

    So, at least I understand the why I had the fault.  I would expect there is a "better" way to manage this without modifying the library function.  You would think that this is a common issue, so there is probably a more eloquent way to slay this dragon.  :)

    LorenAuthorAnswer
    Visitor II
    December 8, 2023

    Ran without error last night.  I'm going to call this thread as resolved for now.

    I'll run the suggested test of 0x0101...0x0202... tonight as a second verification.

    Thank you for all your help!