0

I am building a USB driver on an ARM Cortex M series MCU, namely the STM32F107VCT. My code is based on the USB CDC library code generated by STM's own code generation software called CubeMX. In CubeMX the MCU is configured to support 64 byte USB messages.

Sending messages from a host computer and parsing them on the MCU works fine when the USB payload is 8 chars (i.e. 8 bytes) or smaller. I can see in Wireshark that such messages are padded out to be 64 bytes on the wire.

When 9 chars are being sent the MCU stops execution (without going to the hardware fault handler) and without hitting any of the breakpoint I inserted in the CDC_Receive_FS function as seen in the code segment below.

I can see the USB message (padded out to 64 bytes, just like when having 8 chars as payload) going out from the PC using Wireshark and the MCU hardware acknowledges the message, but the MCU halts without reaching any breakpoints.

My main questions:

Does anyone know why this would halt? Perhaps some simple setting I am missing? Is there any lower level code I can place breakpoints in to really try and figure out what is going on? To me it is not clear what function actually calls CDC_Receive_FS

My implementation of CDC_Receive_FS:

    static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */

  // Test breakpoint 1 set here

   //My custom parser
  USBDRIVER_receive(&(project.usbDriver), Buf, Len);

  // Test breakpoint 2 set here

  //CubeMX Generated functions
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);

  // Test breakpoint 3 set here

  return (USBD_OK);
  /* USER CODE END 6 */ 
}

Please let me know if some additional information is needed in order to solve the issue.

The USB driver is initialized by the following CubeMX auto-generated code:

void MX_USB_DEVICE_Init(void)
{
  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */

  /* USER CODE END USB_DEVICE_Init_PreTreatment */

  /* Init Device Library, add supported class and start the library. */
  USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);

  USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);

  USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);

  USBD_Start(&hUsbDeviceFS);

  /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */

  /* USER CODE END USB_DEVICE_Init_PostTreatment */
}
Mike
  • 4,041
  • 6
  • 20
  • 37
dman
  • 11
  • 2
  • How do you call `CDC_Receive_FS` what is the `USBDRIVER_receive` prototype? – Mathieu Sep 11 '18 at 14:46
  • I never call CDC_Receive_FS from any of my code. I think it is called by an interrupt in FreeRTOS. I'd like to point out that the code never reaches that far, it seems to halt before entering the CDC_Receive_FS function. The USBDRIVER_receive function is my own function which copies the data in the Buf buffer to a local buffer, i.e. not doing anything complicated. – dman Sep 11 '18 at 14:55
  • @purplepsycho you do not call it. It is static for the reason!! I think you have no experience with this library. – 0___________ Sep 11 '18 at 17:38
  • @dman I afraid HAL USB implementation is full of bugs. Check buffer sizes if they are not 4 bytes for example as in some versions of HAL. Check if there are not dynamic allocations in the interrupt routine + many other known glitches. – 0___________ Sep 11 '18 at 17:41
  • @dman - CDC payload is max 64 bytes / packet - so it should not make any difference if it is 8 or 9. Check the buffer sizes. – 0___________ Sep 11 '18 at 17:43
  • Hi. I haven't tested Wireshark, I used USBlyzer to debug, you will be able to see all the USB packets. How do you start the USB to receive? – JMA Sep 12 '18 at 08:43
  • @JMA the routine for starting USB is defined by CubeMX auto-generated code. I added the code to the initial question for clarity. – dman Sep 12 '18 at 09:13
  • @P__J__ Thanks for your answers! USB implementation being "full of bugs" doesn't sound too good. Do you know of any place where the information about the bugs and possible remedies are collected? – dman Sep 12 '18 at 09:21
  • @dman I don't remember very well how does it work, I started with this library but I've modified it to be similar to a UART and I have a start receive function now. Do you call `USBD_CDC_SetRxBuffer` or `USBD_CDC_ReceivePacket`? – JMA Sep 12 '18 at 09:29
  • @JMA I use USBD_CDC_ReceivePacket. But I never call that function. It gets called by an interrupt or similar. But I figured out that it is that function that gets called when I send a USB message from a PC. – dman Sep 12 '18 at 09:50
  • @dman Search in the code where `USBD_CDC_SetRxBuffer`is called. May be in `CDC_Init_FS`, and check the buffer size. – JMA Sep 12 '18 at 13:43
  • @JMA I looked around and found `#define CDC_CMD_PACKET_SIZE 8 /* Control Endpoint Packet size */` located in `usbd_cdc.h` which seemed **really** promising, but changing that to 64 did not change the behaviour. Any other ideas? – dman Sep 21 '18 at 13:24
  • @dman `CDC_CMD_PACKET_SIZE` is for command packets, I also have value 8. In file `usb_cdc_if.c` check the value of `APP_RX_DATA_SIZE`. You also can check it in the Cube, parameter "USB CDC Rx Buffer Size" – JMA Sep 21 '18 at 15:28
  • @JMA Thanks for the tip, In the file "`usbd_cdc_if.c`" I have that constant `APP_RX_DATA_SIZE` set to `4` (unit is bits I assume?). Although I struggle to understand the relation between this constant and the length of the message on the wire. As I can see when tracing with wireshark the message is 64 bytes (payload is padded with zeroes). To add to the confusion the parameter "USB CDC Rx Buffer Size" in CubeMX is set to 1000 Bytes (which doesn't correlate with the 4 in the c file in any way I can understand. I would really appreciate it if you could provide some clarity to this? – dman Sep 25 '18 at 07:15
  • @dman I don't have much more info. `APP_RX_DATA_SIZE` is used to define the RX buffer: `uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];` and this buffer is set as receive buffer with the function `USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);` that is called in the `static int8_t CDC_Init_FS(void)` function. The parameter `*Buff` in the `static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)` function is pointing to that buffer. If this buffer is smaller that the frame you send you will provoke a out of bound error. – JMA Sep 25 '18 at 08:35
  • @JMA, alright! Thanks for that information. Is there any way I can track if there is an "out of bound error" that is occuring? Because all the information I have now is that the MCU execution proceeds to the Hardware fault handler and halts (on incoming messages). – dman Oct 08 '18 at 13:19

0 Answers0