2017-05-13 03:43 PM
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 placedif(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-mx2018-05-15 05:22 AM
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