cancel
Showing results for 
Search instead for 
Did you mean: 

Why doesn't receive callback get called CubeMX 4.20.1

Denny Smith
Associate II
Posted on May 14, 2017 at 00:43

Hi All,

I am new to this community so please bare with me.  I am developing a USB GPS application using STM32F4, CubeMX (4.20.1) and Keil uVison 5.  Using CubeMX I created a USB Host skeleton and succeeded in getting the device to enumerate as a CDC device.  After many hours I came up with a solution that works (sort of) but would like to ask if this is the correct way to acheive the desired result.

First I had to expose

Appli_state flag

(extern  ApplicationTypeDef Appli_state) in main.c in order to determine that enumeration had completed. In the while() loop following MX_USB_HOST_Process() I placed

        if(Appli_state == APPLICATION_READY) {

          USBH_CDC_Receive(&hUsbHostFS, UsbRxBuf, 64);

         

printf('%s', UsbRxBuf);

   

        }

This resulted in data coming through, however, the USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost) did not fire to tell me that data transfer had completed and allow me to put the printf() elsewhere.  Without putting delays in the call to USBH_CDC_Receive() I am getting duplicated data, i.e. old data still in the buffer.

The reason for the callback NOT being fired is in usbh_cdc.c:

static void CDC_ProcessReception(USBH_HandleTypeDef *phost)

...

  switch(CDC_Handle->data_rx_state)

  {

    case CDC_RECEIVE_DATA:

        USBH_BulkReceiveData (phost,

                          CDC_Handle->pRxData,

                          CDC_Handle->DataItf.InEpSize,

                          CDC_Handle->DataItf.InPipe);

    CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;

    break;

At the completion of the CDC_RECEIVE_DATA case the state machines next intended destination was CDC_RECEIVE_DATA_WAIT: as below but it

never got there

.

    

  case CDC_RECEIVE_DATA_WAIT:

    

    URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe);

    

    /*Check the status done for reception*/

    if(URB_Status == USBH_URB_DONE )

    {  

      length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);

        

      if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize))

      {

        CDC_Handle->RxDataLength -= length ;

        CDC_Handle->pRxData += length;

        CDC_Handle->data_rx_state = CDC_RECEIVE_DATA;

      }

      else

      {

        CDC_Handle->data_rx_state = CDC_IDLE;

        USBH_CDC_ReceiveCallback(phost);

      }

...

I suspect the problem may be related to the nature of the GPS device sending a continuous stream of characters but can anyone explain or suggest a better (proper) method.  I should note that all searching I have done on the web mentions a source file (usb_cdc_if.c) which does not get generated by the current version of CubeMX.

Any help would be greatly appreciated.

#stm32-cube-mx
1 REPLY 1
shin park
Associate
Posted on May 15, 2018 at 14:22

Hi, I also had same problem and couldn't solve it clearly, but I at least enabled callback function by forcing the CDC Handle. For example, I initialized

int rx_check

as global variable inside the main.c, and then used extern in usbh_cdc.c

Inside the CDC_ProcessReception function in usbh_cdc.c, I inserted this to enforce CDC Handle

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

if(rx_check==6)

CDC_Handle->data_rx_state=CDC_RECEIVE_DATA_WAIT;

else

CDC_Handle->data_rx_state=CDC_RECEIVE_DATA;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

and used rx_check as a flag like below

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

switch(CDC_Handle->data_rx_state)

{

case CDC_RECEIVE_DATA:

USBH_BulkReceiveData (phost,

CDC_Handle->pRxData,

CDC_Handle->DataItf.InEpSize,

CDC_Handle->DataItf.InPipe);

CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;

rx_check = 6;

break;

case CDC_RECEIVE_DATA_WAIT:

rx_check = 7;

URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Then, inside the callback function, I defined rx_check as

void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)

{

rx_check = 8;

}

so, in the main function, I am able to send my uart whenever the callback function is called like this

if(rx_check ==8){

HAL_USART_Transmit(&husart3, test_buff, 49, 10);

}

Hope this helps you.

Shin