cancel
Showing results for 
Search instead for 
Did you mean: 

CDC device implementation - problem with set_break & set_control_line_state

sergio
Associate II
Posted on October 03, 2012 at 03:42

Hi All,

I am implementing the CDC device in the STM32F4 series (using the Discovery board and the STM3240G-Eval board).

I made it work but I noticed (at least on Windows XP) that the commands sent to change RTS/DTR and BREAK do not work. Is it a problem with the Windows drivers (not implemented) ?

The calls arrive on VCP_Ctrl routine but Buf is always null (unless the command is to set or get the LINE_CODING. I would like to have a complete implementation (because I need the break signal and DTR/RTS.

Thank you very much.

Sergio P. Sider

PS. Fantastic to find TSUNEO in this forum!!!

#stm32f4-usb-cdc-device
5 REPLIES 5
tsuneo
Senior
Posted on October 03, 2012 at 17:06

The CDC example of STM32_USB-Host-Device_Lib_V2.1.0 doesn't implemment handler of SET_CONTROL_LINE_STATE and SEND_BREAK.

Here is an outline of implementation. 1) Descriptors Enable Send_Break at bmCapabilities field of ACM Functional Descriptors

STM32_USB-Host-Device_Lib_V2.1.0\Libraries\STM32_USB_Device_Library\Class\cdc\src\usbd_cdc_core.c
__ALIGN_BEGIN uint8_t usbd_cdc_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
...
...
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */ // <---- 0x06 (D2:Send_Break
// D1:Set/Get_Line_Coding,
 // Set_Control_Line_State,
 // Serial_State
...
...
__ALIGN_BEGIN uint8_t usbd_cdc_OtherCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{ 
...
...
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */ // <---- 0x06 (D2:Send_Break
// D1:Set/Get_Line_Coding,
 // Set_Control_Line_State,
 // Serial_State

2) CDC device class library Modify usbd_cdc_Setup(), so that ''No Data request'' passes SETUP packet, instead of NULL.

STM32_USB-Host-Device_Lib_V2.1.0\Libraries\STM32_USB_Device_Library\Class\cdc\src\usbd_cdc_core.c
static uint8_t usbd_cdc_Setup (void *pdev, 
USB_SETUP_REQ *req)
{
... 
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
/* CDC Class Requests -------------------------------*/
case USB_REQ_TYPE_CLASS :
/* Check if the request is a data setup packet */
if (req->wLength)
{
...
...
}
else /* No Data request */
{
/* Transfer the command to the interface layer */
// APP_FOPS.pIf_Ctrl(req->bRequest, NULL, 0); // <---- this line is modified
APP_FOPS.pIf_Ctrl(req->bRequest, (uint8_t*)req, 0); // pass SETUP packet
}
return USBD_OK;

3) CDC device example On the VCP_Ctrl() function, fill blank ''case SET_CONTROL_LINE_STATE'' and ''case SEND_BREAK''

STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\VCP\src\usbd_cdc_vcp.c
#include ''usb_core.h'' // to refer USB_SETUP_REQ structure // <---- add this line
#define CDC_RTS_MASK 0x02
#define CDC_DTR_MASK 0x01
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
{ 
USB_SETUP_REQ * req = (USB_SETUP_REQ *)Buf; // for No Data request // <---- add this line
switch (Cmd)
{
...
case SET_CONTROL_LINE_STATE:
/* Not needed for this driver */
if (req->wValue & CDC_RTS_MASK) {
//
// host set RTS to '1' Set RTS port to '1', here
//
} else {
//
// host reset RTS to '0' Reset RTS port to '0', here
//
}
if (req->wValue & CDC_DTR_MASK) {
//
// host set DTR to '1'
//
} else {
//
// host reset DTR to '0'
//
}
break;
case SEND_BREAK:
/* Not needed for this driver */
// req->wValue holds the duration of break in milisecond.
// If req->wValue contains a value of FFFFh,
// then the device will send a break until another SendBreak request is received
// with the req->wValue of 0000h
break; 

4) Windows bug Lastly, Windows CDC driver, usbser.sys, has a bug on RTS signaling. - RTS changes on the device side, when host puts DTR (even the same value of DTR will do) Tsuneo
tsuneo
Senior
Posted on October 03, 2012 at 17:32

These Win32 APIs put 0xFFFF or 0x0000 of req->wValue for SEND_BREAK request

EscapeCommFunction( SETBREAK )   -  SEND_BREAK(0xFFFF)

EscapeCommFunction( CLRBREAK )   -  SEND_BREAK(0x0000)

SetCommBreak   -  SEND_BREAK(0xFFFF)

ClearCommBreak -  SEND_BREAK(0x0000)

That is, on Windows, you'll see just 0x0000 or 0xFFFF at the SEND_BREAK parameter.

Tsuneo

sergio
Associate II
Posted on October 03, 2012 at 23:15

Hi Tsuneo, as always, your answers are always the correct solution. 

I will try and implement it.

While we are at it, I have an additional question:

Do you know if there is another issue with the STM CDC example, regarding the interrupt. 

I am using it with FreeRTOS, but I just added a task to flash a led, and let the USB part outside the tasks. When I plug in the USB cable it works but I noticed it makes the leds stop flashing during a few seconds because the ''USBD_OTG_ISR_Handler'' is being continuously entered. Do you have a tip on what I should look for in the handler?

sergio
Associate II
Posted on October 04, 2012 at 14:00

Hi Tsuneo, just to let you know that your suggestions are working fine (as always).

And, if I need to send RI, DCD and DSR, I would have to create a status packet and send it whenever any of the signals changed, right? Well, I'll try it some day.

I still getting ''frozen'' for a second or two when I plug the cable (the IRQ routine is being called continuously.. like if the source of the previous interrupt was not acknowledge), but couldn't figure it out yet. After the delay, everything goes back to ''normal''. If you have a tip about it, please let me know.

Thanks again!

Sergio.
sergio
Associate II
Posted on October 05, 2012 at 02:36

Hi, 

Just to comment that the IRQ problem was my mistake. There was a task printing debug stuff before the actual connection was made. Now all is working fine.

Tks!

Sergio.