cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 USB as Virtual COM Port Host (CDC Host)

kroesswang_thomas
Associate II
Posted on October 16, 2012 at 13:47

Hello!

I already found a library packet for using the STM32 USB as Virtual COM device. What I need is a library for a Virtual COM host, so I can connect a CDC device to my STM32.

It's just for one specific CDC device (a laserscanner-sensor).

Are such libraries existing?

#thomas
10 REPLIES 10
Posted on October 16, 2012 at 15:56

Are such libraries existing?

 

You have the USB libraries, what you want is a host example. There are other host examples, start by reviewing the mechanics of those.

If the CDC device you want to utilizes it's own driver you'll need to understand the protocol. Suggest you look at it with a USB protocol analyzer, and seek other host examples, and port the ST examples.

Other vendors sell USB stacks, you could perhaps investigate those.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
kroesswang_thomas
Associate II
Posted on October 17, 2012 at 20:18

As far as I understand now, I have to write a CDC usb-class (similar to the existing classes MSC-Host or HID-Host) and could use e.g. the usbh_msc_core.c file as reference. Is that right?

nicolaj
Associate
Posted on January 11, 2013 at 16:20

Hi Thomas

I'm also in need of USB CDC host on STM32. Did you have any luck finding an example or have you implemented it yourself?

If so, would you be willing to share your experience, and possibly source?

kroesswang_thomas
Associate II
Posted on January 14, 2013 at 20:19

Yes, my USB CDC Core is working fine now!

This is the main part, the core handle state machine. Part of the code is specific to my application, but the main routines are Set_Line_Coding, Bulk_Send and Bulk_Receive. This forum post helped me a lot to understand the USB Host Lib: http://www.keil.com/forum/20569/ I'll post some more details tomorrow, when I have access to the software again.

/**
* @brief USBH_MSC_Handle 
* MSC state machine handler 
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_CDC_Handle(USB_OTG_CORE_HANDLE *pdev ,
void *phost)
{
USBH_Status status = USBH_BUSY;
uint8_t baud19200 [7] = {0x00,0x4B,0x00,0x00,0x00,0x00,0x08}; //19200baud, 8bits, 1stop-bit, no parity-bit
uint8_t scip20 [8] = {'S','C','I','P','2','.','0',0x0A};
uint8_t scip20_length = 8;
uint8_t scip_BM [3] = {'B','M',0x0A};
uint8_t scip_BM_length = 3;
uint8_t scip_QT [3] = {'Q','T',0x0A};
uint8_t scip_QT_length = 3;
uint8_t scip_GD [13] = {'G','D','0','0','4','4','0','7','2','5','0','1',0x0A};
uint8_t scip_GD_length = 13;
static uint8_t raw_data [NUM_RAW_BYTES];
static uint16_t datapointer;
static uint8_t urb_status;
if(HCD_IsDeviceConnected(pdev))
{ 
switch(cdc_state)
{
//Set the line coding structure for communication with the LRF
case CDC_STATE_SET_LINE_CODING:
status = USBH_SET_LINE_CODING(pdev, phost, &baud19200[0]);
if(status == USBH_OK)
{
cdc_state = CDC_STATE_SEND_BM;
USB_OTG_BSP_mDelay(100);
xprintf(''Switch on LRF!'');
}
break;
//Switch ON the LRF
case CDC_STATE_SEND_BM:
if(HCD_GetURB_State(pdev , CDC_Machine.hc_num_out) != URB_NOTREADY)
{
USBH_BulkSendData (pdev,
&scip_BM[0],
scip_BM_length ,
CDC_Machine.hc_num_out);
cdc_state = CDC_STATE_RECEIVE_BM;
xprintf(''Wait for LRF!'');
}
break;
//Wait for the echo of the LRF
case CDC_STATE_RECEIVE_BM:
urb_status = HCD_GetURB_State(pdev , CDC_Machine.hc_num_out);
if(urb_status == URB_DONE)
{
USBH_BulkReceiveData (pdev,
raw_data,
USBH_CDC_MPS_SIZE ,
CDC_Machine.hc_num_in);
xprintf(''LRF activated!'');
cdc_state = CDC_STATE_SEND_GD;
}
break;
//Send a scan request
case CDC_STATE_SEND_GD:
urb_status = HCD_GetURB_State(pdev , CDC_Machine.hc_num_in);
if(urb_status == URB_DONE)
{
USBH_BulkSendData (pdev,
&scip_GD[0],
scip_GD_length ,
CDC_Machine.hc_num_out);
datapointer = 0;
cdc_state = CDC_STATE_RECEIVE_LRF_DATA;
//xprintf(''Get Data!'');
}
break;
//Receive LRF raw data
case CDC_STATE_RECEIVE_LRF_DATA:
urb_status = HCD_GetURB_State(pdev , CDC_Machine.hc_num_out);
if((urb_status == URB_DONE) && (HCD_GetURB_State(pdev , CDC_Machine.hc_num_in) == URB_DONE))
{
//Receive a packet of raw-data-bytes from LRF (packet size = USBH_CDC_MPS_SIZE)
USBH_BulkReceiveData (pdev,
&raw_data[datapointer],
USBH_CDC_MPS_SIZE,
CDC_Machine.hc_num_in);
datapointer += USBH_CDC_MPS_SIZE;
}
//When all bytes have been received
if(datapointer >= NUM_RAW_BYTES)
{
cdc_state = CDC_STATE_PROCESS_DATA;
//xprintf(''Process Data!'');
}
break;
//Extract the coordinates of the robots from the raw data and display them
case CDC_STATE_PROCESS_DATA:
//xprintf(''Process Data!'');
urb_status = HCD_GetURB_State(pdev , CDC_Machine.hc_num_in);
if(urb_status == URB_DONE)
{
Process_LRF_Data(&raw_data[0]);
//USB_OTG_BSP_mDelay(50);
cdc_state = CDC_STATE_SEND_GD;
}
break;
default:
break;
}
}
return status;
}
static USBH_Status USBH_SET_LINE_CODING(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t *buffer)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = 0x20;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0x88; 
return USBH_CtlReq(pdev, phost, buffer , 7 ); 
}

kroesswang_thomas
Associate II
Posted on January 15, 2013 at 14:35

The other function you have to change is the USBH_MSC_INTERFACE_INIT. You have to change MSC_CLASS and MSC_PROTOCOL.

CDC_CLASS = 0x02 CDC_PROTOCOL (for my device) = 0x01 The rest stays the same.

/**
* @brief USBH_MSC_InterfaceInit 
* Interface initialization for MSC class.
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status : Status of class request handled.
*/
static USBH_Status USBH_CDC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev,
void *phost)
{ 
USBH_HOST *pphost = phost;
if((pphost->device_prop.Itf_Desc[0].bInterfaceClass == CDC_CLASS) && \
(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == CDC_PROTOCOL))
{
if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80)
{
CDC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress);
CDC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize;
}
else
{
CDC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress);
CDC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0] [0].wMaxPacketSize;
}
if(pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80)
{
CDC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
CDC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize;
}
else
{
CDC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
CDC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize;
}
CDC_Machine.hc_num_out = USBH_Alloc_Channel(pdev,
CDC_Machine.MSBulkOutEp);
CDC_Machine.hc_num_in = USBH_Alloc_Channel(pdev,
CDC_Machine.MSBulkInEp);
/* Open the new channels */
USBH_Open_Channel (pdev,
CDC_Machine.hc_num_out,
pphost->device_prop.address,
pphost->device_prop.speed,
EP_TYPE_BULK,
CDC_Machine.MSBulkOutEpSize);
USBH_Open_Channel (pdev,
CDC_Machine.hc_num_in,
pphost->device_prop.address,
pphost->device_prop.speed,
EP_TYPE_BULK,
CDC_Machine.MSBulkInEpSize);
}
else
{
pphost->usr_cb->USBH_USR_DeviceNotSupported(); 
}
return USBH_OK ;
}

kubelek1
Associate
Posted on October 07, 2013 at 19:36

Hello Thomas

I tried to use Your code for USB CDC host with STM32F4. Unfortunately I have problems with it. Could You send me some example project using Your CDC host library? My E-mail address is: kubelek1@o2.pl

Thank You very much.

kqian
Associate II
Posted on January 27, 2014 at 21:22

Hey Thomas.

I am trying to program USB cdc host too, Could you please share your working code to me? My email is

mailto:keny_qian@yahoo.com

. Thanks for that.

kqian
Associate II
Posted on January 27, 2014 at 23:37

Hey,

I am trying to edit my cdc host code following the example , but no idea what is ''

cdc_state
'' and where to defineit.Any one canhelp me?

if(HCD_IsDeviceConnected(pdev))
{ 
switch(cdc_state)
{
//Set the line coding structure for communication with the LRF
case CDC_STATE_SET_LINE_CODING:
status = USBH_SET_LINE_CODING(pdev, phost, &baud19200[0]);
if(status == USBH_OK)
{
cdc_state = CDC_STATE_SEND_BM;
USB_OTG_BSP_mDelay(100);
xprintf(''Switch on LRF!'');
}
break;

regards
yaknafo
Associate
Posted on March 08, 2014 at 17:39