2010-06-09 10:46 PM
Multiple USB CDC (USB IAD). How?
#iad #cdc #stm32f103 #dual-cdc-with-stm32l152 #usb-cdc-duart2012-07-30 06:39 AM
Hello Tsuneo,
Please call me Michele :) I modified a bit more the code.. 1) I duplicated the EP callbacks and I now have EP2_IN_Callback EP4_IN_Callback EP6_IN_Callback EP2_OUT_Callback EP4_OUT_Callback EP6_OUT_Callback defined like this:void
EP2_IN_Callback (
void
) {
uint16_t USB_Tx_ptr;
uint16_t USB_Tx_length;
if
(CDC1_Tx_State == 1) {
if
(VCP1_Rx_length == 0) {
CDC1_Tx_State = 0;
}
else
{
if
(VCP1_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE) {
USB_Tx_ptr = VCP1_Rx_ptr_out;
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;
VCP1_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;
VCP1_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
USB_Tx_ptr = VCP1_Rx_ptr_out;
USB_Tx_length = VCP1_Rx_length;
VCP1_Rx_ptr_out += VCP1_Rx_length;
VCP1_Rx_length = 0;
}
UserToPMABufferCopy(&VCP1_Rx_Buffer[USB_Tx_ptr], ENDP2_TXADDR, USB_Tx_length);
SetEPTxCount(ENDP2, USB_Tx_length);
SetEPTxValid(ENDP2);
}
}
}
and
void
EP2_OUT_Callback(
void
) {
uint16_t USB_Rx_Cnt;
/* Get the received data buffer and update the counter */
USB_Rx_Cnt = USB_SIL_Read(EP2_OUT, USB_Rx_Buffer);
/* USB data will be immediately processed, this allow next USB traffic being
NAKed till the end of the USART Xfer */
USB_To_VCP1_Send_Data(USB_Rx_Buffer, USB_Rx_Cnt);
/* Enable the receive of data on EP2 */
SetEPRxValid(ENDP2);
}
similarly I modified
Handle_USBAsynchXfer()as follows:
void
Handle_USBAsynchXfer (
void
) {
uint16_t USB_Tx_ptr;
uint16_t USB_Tx_length;
// -------------------- VCP1
if
(CDC1_Tx_State != 1) {
if
(VCP1_Rx_ptr_out == VCP1_Rx_DATA_SIZE) {
VCP1_Rx_ptr_out = 0;
}
if
(VCP1_Rx_ptr_out == VCP1_Rx_ptr_in) {
CDC1_Tx_State = 0;
// return;
}
else
{
if
(VCP1_Rx_ptr_out > VCP1_Rx_ptr_in) {
/* rollback */
VCP1_Rx_length = VCP1_Rx_DATA_SIZE - VCP1_Rx_ptr_out;
}
else
{
VCP1_Rx_length = VCP1_Rx_ptr_in - VCP1_Rx_ptr_out;
}
if
(VCP1_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE) {
USB_Tx_ptr = VCP1_Rx_ptr_out;
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;
VCP1_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;
VCP1_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
USB_Tx_ptr = VCP1_Rx_ptr_out;
USB_Tx_length = VCP1_Rx_length;
VCP1_Rx_ptr_out += VCP1_Rx_length;
VCP1_Rx_length = 0;
}
CDC1_Tx_State = 1;
UserToPMABufferCopy(&VCP1_Rx_Buffer[USB_Tx_ptr], ENDP2_TXADDR, USB_Tx_length);
SetEPTxCount(ENDP2, USB_Tx_length);
SetEPTxValid(ENDP2);
}
}
// -------------------- VCP2
if
(CDC2_Tx_State != 1) {
if
(VCP2_Rx_ptr_out == VCP2_Rx_DATA_SIZE) {
VCP2_Rx_ptr_out = 0;
}
if
(VCP2_Rx_ptr_out == VCP2_Rx_ptr_in) {
CDC2_Tx_State = 0;
// return;
}
else
{
if
(VCP2_Rx_ptr_out > VCP2_Rx_ptr_in) {
/* rollback */
VCP2_Rx_length = VCP2_Rx_DATA_SIZE - VCP2_Rx_ptr_out;
}
else
{
VCP2_Rx_length = VCP2_Rx_ptr_in - VCP2_Rx_ptr_out;
}
if
(VCP2_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE) {
USB_Tx_ptr = VCP2_Rx_ptr_out;
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;
VCP2_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;
VCP2_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
USB_Tx_ptr = VCP2_Rx_ptr_out;
USB_Tx_length = VCP2_Rx_length;
VCP2_Rx_ptr_out += VCP2_Rx_length;
VCP2_Rx_length = 0;
}
CDC2_Tx_State = 1;
UserToPMABufferCopy(&VCP2_Rx_Buffer[USB_Tx_ptr], ENDP4_TXADDR, USB_Tx_length);
SetEPTxCount(ENDP4, USB_Tx_length);
SetEPTxValid(ENDP4);
}
}
// -------------------- VCP3
if
(CDC3_Tx_State != 1) {
if
(VCP3_Rx_ptr_out == VCP3_Rx_DATA_SIZE) {
VCP3_Rx_ptr_out = 0;
}
if
(VCP3_Rx_ptr_out == VCP3_Rx_ptr_in) {
CDC3_Tx_State = 0;
// return;
}
else
{
if
(VCP3_Rx_ptr_out > VCP3_Rx_ptr_in) {
/* rollback */
VCP3_Rx_length = VCP3_Rx_DATA_SIZE - VCP3_Rx_ptr_out;
}
else
{
VCP3_Rx_length = VCP3_Rx_ptr_in - VCP3_Rx_ptr_out;
}
if
(VCP3_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE) {
USB_Tx_ptr = VCP3_Rx_ptr_out;
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;
VCP3_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;
VCP3_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
USB_Tx_ptr = VCP3_Rx_ptr_out;
USB_Tx_length = VCP3_Rx_length;
VCP3_Rx_ptr_out += VCP3_Rx_length;
VCP3_Rx_length = 0;
}
CDC3_Tx_State = 1;
UserToPMABufferCopy(&VCP3_Rx_Buffer[USB_Tx_ptr], ENDP6_TXADDR, USB_Tx_length);
SetEPTxCount(ENDP6, USB_Tx_length);
SetEPTxValid(ENDP6);
}
}
}
There something else to modify I think... in fact I don't see where the interrupt endpoints are handled at all!
It still does not work completely but on Windows7 64bit I can see this:
Please note that I did not install any driver.. this comes up by default.
I tried linking those serial ports to the ST VCP driver with no luck.. I guess Win7 64bit is picky.
On Linux, when plugging my device I have the following:
[ 074217] usb 2-1.2: new full-speed USB device number 3 using ehci_hcd
[ 196449] cdc_acm 2-1.2:1.0: ttyACM0: USB ACM device [ 196945] cdc_acm 2-1.2:1.2: ttyACM1: USB ACM device [ 197586] cdc_acm 2-1.2:1.4: ttyACM2: USB ACM device [ 197992] usbcore: registered new interface driver cdc_acm [ 197997] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters and three virtual COM ports appear at ttyACM0, ttyACM1, ttyACM2. But nothing flows through them. Getting there? Cheers, Michele2012-10-04 06:50 AM
Hi guys,
can you publish ready to use example for IAD ? Thanks in advance2013-01-25 06:11 PM
I publish working example for dual CDC (as composite device).
2013-02-24 08:38 AM
Hello.
As we know,the vcp demo(one cdc) needs three eps,but interrupt IN is declared in the descriptor but the related endpoint is not used. And up to 16 mono-directional or 8 bidirectional endpoints can be used.So if more CDC composite can be implemented,for example 5 cdc to use all uart? Yangfeng2013-02-25 10:10 PM
> but interrupt IN is declared in the descriptor but the related endpoint is not used.
The interrupt IN EP should be enabled, even if the firmware doesn't handle it. Windows CDC driver (usbser.sys) polls the interrupt IN EP repeatedly. When the EP returns no response, usbser.sys stops to read out the bulk IN EP, after a couple of transfers on the bulk EP. Tsuneo2013-02-26 07:40 AM
to be migrated, sourceId: 28478:697285D7-A9CA-445D-B16C-F23BF0E3B1A3
2013-12-22 10:04 AM
I want to thank
Tsuneo for his detailed walk-through on this. I found his notes very helpful in getting a MSC + CDC composite device created on the STM32F4 Discovery.
Cheers!-- Ryan2014-02-09 07:35 PM
Also thanks to Tsuneo and others for sharing valuable info here.
Ryan, any chance of sharing your MSC + CDC example? - I'm sure many in this community including me would greatly appreciate it. Thanks.2014-08-21 03:03 AM
Hello,
I am trying your nice example to run on stm32L152 mcu? is it possible? Will Number of EPs (IN/OUT) be problem for me? thx2015-01-13 09:55 AM
I have made a similar project based on STM32F4.
It works fine on windows XP, it even works with shared interrupt endpoint. However, I cannot install it on Windows 8.1 x64. Have you tried to install your device on Windows 8.1 x64?