cancel
Showing results for 
Search instead for 
Did you mean: 

USB HOST CDC USBH_CDC_Receive frequent interrupts problem

VitalyTolochanov
Associate II

Hi!

I'm using stm32f105vct6, project generated with CubeMx, Usb Host CDC with FreeRTOS (cmsis v2)

usb_cdc.c

USBH_FindInterface(phost, COMMUNICATION_INTERFACE_CLASS_CODE, ABSTRACT_CONTROL_MODEL, COMMON_AT_COMMAND);

was changed to

USBH_FindInterface(phost, COMMUNICATION_INTERFACE_CLASS_CODE, ABSTRACT_CONTROL_MODEL, NO_CLASS_SPECIFIC_PROTOCOL_CODE);

otherwise there was no enumeration

 

#define CDC_RX_BUFFER_SIZE 512

uint8_t CDC_RxBuffer[CDC_RX_BUFFER_SIZE];

After Appli_state == APPLICATION_READY I set

memset(CDC_RxBuffer, 0, CDC_RX_BUFFER_SIZE);

USBH_CDC_Receive(&hUsbHostFS, CDC_RxBuffer, CDC_RX_BUFFER_SIZE);

 

and USBH_CDC_ReceiveCallback:

// Handles the data recived from the USB CDC host

rx_size = USBH_CDC_GetLastReceivedDataSize(phost);

for (int i = 0; i < rx_size; i++)

{

      pp_circle_buf[pp_iend++] = CDC_RxBuffer[i];

      if(pp_iend >= PP_CIRCLE_BUF_SIZE) pp_iend = 0;

}

USBH_CDC_Receive(phost, CDC_RxBuffer, CDC_RX_BUFFER_SIZE);

osSemaphoreRelease(semUSBDataReadyHandle);

 

Transmission and reception (including packets of several kilobytes) work fine.

But there is a problem. When not issuing USBH_CDC_Receive interrupts are with period ~1ms.

But if prepare receiving buffer with USBH_CDC_Receive interrupts become more frequent, so many tasks in FreeRTOS got freezed (including watchdog task). System almost hang up except USB (all communication with paypass device works fine, USB task has normal priority)

Executing USBH_CDC_Stop(&hUsbHostFS); returns to normal interrupt rate (with no receiving)

PayPass device may transfer at any time, so I need to wait packets all the time while processing transaction

May be I do something wrong in receiving?

Thanks for help

5 REPLIES 5
Ghofrane GSOURI
ST Employee

Hello @VitalyTolochanov 

First let me thank you for posting.

It seems like the issue might be related to the way you are using the semaphore to signal that USB data is ready. It's possible that the semaphore is being released too frequently, causing other tasks to get blocked.

One suggestion would be to use a flag instead of a semaphore to signal that USB data is ready. You can set the flag in the USBH_CDC_ReceiveCallback function, and then check the flag in your main task loop to determine if there is new data to process. This way, you can avoid releasing the semaphore too frequently and potentially causing other tasks to get blocked.

Another suggestion would be to increase the priority of the USB task to ensure that it has enough processing time to handle incoming data. You can do this by setting the priority of the USB task higher than the other tasks in your system.

Finally, you may want to consider using a circular buffer to store incoming data instead of copying it to a fixed-size buffer. This can help to avoid buffer overflows and ensure that incoming data is processed in a timely manner.

Thx

Ghofrane

Thanks for replying
Now I’m just trying to ping paypass device (sending ping and getting answer 6 bytes)

Removed semaphore from USBH_CDC_ReceiveCallback and PayPass task with osDelay(ms_200) -> same situation
I’m already using circular buffer
rx_size = USBH_CDC_GetLastReceivedDataSize(phost);
for (int i = 0; i < rx_size; i++)
{
      pp_circle_buf[pp_iend++] = CDC_RxBuffer[i];
      if(pp_iend >= PP_CIRCLE_BUF_SIZE) pp_iend = 0;
}

As I mentioned above, the problem is in very high rate of interrupts after calling USBH_CDC_Receive

Setting usb task to highest priority leads to all system hang up

Only HAL_HCD_IRQHandler is continious working

Following flags are active

/* Handle Host SOF Interrupt */
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))

/* Handle Rx Queue Level Interrupts */
if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)

/* Handle Host channel Interrupt */
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))

Thanks

VitalyTolochanov
Associate II

Setting usb task to highest priority leads to all system hang up
Interrupt calls USBH_CDC_Process, after processing next USB interrupt is called and so on...
As usb task has highest priority, none of other tasks gets control

Thx

VitalyTolochanov
Associate II

so, what i did up to this moment
this topic makes smth clear for me
https://community.st.com/t5/stm32cubemx-mcu/bug-cubemx-usb-otg-sof-flag-causing-interrupt-flood-fixed/m-p/176647

1. Remove SOF interrupt
2. Set USB task to the lowest priority
3. Increase clk to 72MHz
4. When Paypass device is in idle state, I don't set USBH_CDC_Receive after receiving ping answer
USB_OTG_GINTSTS_RXFLVL is

 

One suggestion would be to use a flag instead of a semaphore to signal that USB data is ready. You can set the flag in the USBH_CDC_ReceiveCallback function, and then check the flag in your main task loop to determine if there is new data to process. This way, you can avoid releasing the semaphore too frequently and potentially causing other tasks to get blocked.


If there is a new data, it needs to be processed. If other tasks are more important, then they must have a higher priority, or, if they are of the same importance level, then they must have the same priority, so that round-robin algorithm schedules them all periodically on each system tick. Polling a flag from a thread without any thread synchronization in multi-thread environment (RTOS) does exactly the opposite of what you are trying to "solve" - it blocks lower priority threads from ever running or, if a delay is introduced, increases the data processing latency and still unnecessarily increases the CPU load. Such a "solution" is on a level of beginners on Arduino, who clearly do not understand how a multi-thread or even event based software must be built.

@VitalyTolochanov , thread flags are more efficient that semaphores.