Multiple CDC's with USB and ASF4/START (ie. two virtual comm ports over USB)

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using ASF4/START with a current project that includes USB and the CDC class setup as a single virtual comm port.  All is well.

 

I'd like to modify my project by dumping the separate old school RS-232 serial debug port and create a second virtual comm port over the existing USB connection as the new debug port.  This way there is a single cable from my equipment to the PC, with the application talking on one USB virtual comm port, and debug messages going out to a second virtual comm port.

 

Long story short, I can't seem to select two CDC's with ASF4/START.  Am I missing something?  Or is it not supported under ASF4/START?  I've seen references in other posts with presumably ASF3 and multiple CDC's so I know it's possible with the hardware. 

 

Can one of you gurus help me out and point me in the right direction?  What's the easiest way to move up to two or more CDC's with ASF4?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know if this will help.

 

I don't use START.  I've done multiple (7) CDCs on an Xmega using ASF3.  To make that work you simply #define UDI_CDC_PORT_NB for the number of ports you want.  This is done in <project>/src/config/conf_usb.h:

//! Number of communication port used (1 to 3)
#define  UDI_CDC_PORT_NB 7    // this is line 123

//! Interface callback definition
#define  UDI_CDC_ENABLE_EXT(port)				cdc_enable_cb(port)
#define  UDI_CDC_DISABLE_EXT(port)				cdc_disable_cb(port)

 

And the code that makes all 7 ports echo what they receive:

do {
    sleepmgr_enter_sleep();
    for (int port = 1; port < UDI_CDC_PORT_NB; port++) {
        int chr;
        if (udi_cdc_multi_is_rx_ready(port)) {
            udi_cdc_multi_putc(port, chr = udi_cdc_multi_getc(port));
            if (chr == '\r')	// expand \r to \r\n
                udi_cdc_multi_putc(port, '\n');
        }
    }
} while (true);

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, that's the type of stuff I mentioned seeing for ASF3 in other posts here on AVRFreaks.  It looks straight forward with ASF3.

 

Unfortunately with ASF4 there is no #define UDI_CDC_PORT_NB anywhere in the code.  And the <project>/src/config/conf_usb.h doesn't exist.  The closest is <project>/Config/hpl_usb_config.h and <project>/Config/usbd_cdc_acm_config.h.  I can defined the maximum number of endpoints in hpl_usb_config.h but not the number of CDC ports.  And usbd_cdc_acm_config.h seems to define the descriptors for the single CDC (endpoint numbers, vendor ID, etc.).  As best as I can tell with ASF4 only one CDC USB descriptor gets setup.

 

I'm thinking maybe create an ASF3 example project and pull over the descriptors.  But I'm worried the ASF4 driver only supports one CDC.

 

Does anyone with ASF4 experience know the answer?  I'd hate to have to gut my project of ASF4's USB driver and go with something else simply because ASF4 lacks capability that ASF3 already has.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not sure at all if I'm on the right track here. I'm just tinkering and dabbling around with/in Atmel Start. Anyway, I found this (given you can re/up-load your project to the Start web application/site):

 

- Select Clock Configurator

- On the right, to the right of the "COMPONENTS" heading, click the + sign

- Expand the Middleware section

- Expand USB Stack (not "USB Device Stack", everything there seems to be marked deprecated)

There is a list entry for USB Class CDC.

 

I'm not experienced enough with ASF/Start yet so have no clue at if this is actually what you want, but since I stumbled upon it I thought I'd mention it..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah that sets up the single virtual comm port.  There are no settings anywhere in those middleware components to enable more than one CDC.  Even the composite device shows multiple USB devices (Vendor, Hub, MSC, HID, CDC, etc) all enabled at once, but it looks like only one instance of a CDC device is supported under ASF4.  Unless I'm doing something wrong?

 

I think it's time to call Atmel support for confirmation...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@ScottMN,

 

Any answer from Atmochip?  I thought I found a parameter or two yesterday that appear to set the number of instances of the CDC, but changing either or both of these made no change to the START project that I could see.

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Been trying to submit a case since late Fri.  This every time, of course much longer than 30 mins ...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the meantime I did some digging in ASF3.  The cdc/acm usb driver supports multiple virtual comm ports quite simply just like Greg_Muth pointed out in post #2.  For my project I'm thinking of adding a statically linked library to the solution that is just the acm usb driver from ASF3.  Then I'll dump the ASF4 code from the core project and link in the "new" library.  Theoretically it should work.  It will probably take me all day to get it implemented and tested though.

 

Other food for thought with ASF4's cdc/acm usb driver:
1.  The driver code does not protect it's RX ring buffer with CRITICAL_SECTION_ENTER()/CRITICAL_SECTION_LEAVE().  This means the ISR can move the ring buffer indexes in the middle of an application access causing corruption.  Any decent embedded software engineer knows better - always protect the application from an interrupt accessing the same data.

2. The TX side does not have a ring buffer - why would it be crippled like this?  So the application either needs to build that layer or block on all transmissions otherwise the TX buffers get corrupted.

3. Enumeration will fail often when unplugging/plugging in the cable on the windows side with a Code 10 driver error (via the standard usbser.sys).  Seems to be less frequent with full speed mode.  Looking at the usb descriptors high speed mode is not implemented properly in the earlier START generated code.  The latest START generated code sets up the descriptors properly (i.e. 512 byte buffers), but it still generates a Code 10 driver error.  So yes the latest START has fixed some of the driver bugs but many remain.

 

My conclusion:  ASF4's USB device drivers are not mature enough for a commercial product yet.  If you are starting a new USB project, do not use ASF4's USB stack - find something else.  I haven't test ASF3 yet to confirm driver code stability so unfortunately I don't have an alternate recommendation.  But I have looked at both LUFA and TinyUSB as alternatives - unfortunately ports to my processor do not exist (Cortex-M7/SAME70) so I'd have to do the port myself, and neither support multiple virtual comm ports out of the box.

Last Edited: Mon. Dec 18, 2017 - 02:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you end up managing to make a multiple CDC composite USB? ASF4 is still a mess and from what I tried and saw it needs considerable reworking to work as a multiple CDC composite USB.

I have a SAMD51, so aside from porting ASF3 or LUFA I'm a bit stuck.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nope, gave up trying.  I ran into other problems with START/ASF4's USB driver as well - doesn't work reliably at high speed mode (480Mbps).  Only full speed mode works reliably (12Mbps) on a SAME70 at 300Mhz.  Clearly the new USB drivers suck.

 

My next Atmel project with USB will definitely not be using START/ASF4.  Stick with ASF3 or go third party.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok. I guess I'll have to try to port the ASF3 drivers for the SAMD51.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using ASF with 2 CDC com ports and 1 MSC device in a composite configuration on the ATSAMD21.

 

Snippet from conf_usb.h:

 

//! Endpoint numbers definition
#if SAM3U
#  define  UDI_CDC_COMM_EP_0             (3 | USB_EP_DIR_IN) // Notify endpoint
#  define  UDI_CDC_DATA_EP_IN_0          (6 | USB_EP_DIR_IN) // TX
#  define  UDI_CDC_DATA_EP_OUT_0         (5 | USB_EP_DIR_OUT)// RX
#else
#  define  UDI_CDC_COMM_EP_0             (1 | USB_EP_DIR_IN) // Notify endpoint
#  define  UDI_CDC_DATA_EP_IN_0          (2 | USB_EP_DIR_IN) // TX
#  define  UDI_CDC_DATA_EP_OUT_0         (2 | USB_EP_DIR_OUT)// RX

#  define  UDI_CDC_COMM_EP_1             (3 | USB_EP_DIR_IN) // Notify endpoint
#  define  UDI_CDC_DATA_EP_IN_1          (4 | USB_EP_DIR_IN) // TX
#  define  UDI_CDC_DATA_EP_OUT_1         (4 | USB_EP_DIR_OUT)// RX
#endif

//! Interface numbers
#define  UDI_CDC_COMM_IFACE_NUMBER_0   0
#define  UDI_CDC_DATA_IFACE_NUMBER_0   1
#define  UDI_CDC_COMM_IFACE_NUMBER_1   2
#define  UDI_CDC_DATA_IFACE_NUMBER_1   3

//! Endpoint numbers definition
#define  UDI_MSC_EP_IN                 (7 | USB_EP_DIR_IN)
#define  UDI_MSC_EP_OUT                (7 | USB_EP_DIR_OUT)

//! Interface number
#define  UDI_MSC_IFACE_NUMBER          4

 

//! USB Interfaces descriptor structure

#define UDI_COMPOSITE_DESC_T \

usb_iad_desc_t       udi_cdc_iad0; \

udi_cdc_comm_desc_t  udi_cdc_comm0; \

udi_cdc_data_desc_t  udi_cdc_data0; \

usb_iad_desc_t       udi_cdc_iad1; \

udi_cdc_comm_desc_t  udi_cdc_comm1; \

udi_cdc_data_desc_t  udi_cdc_data1; \

udi_msc_desc_t       udi_msc

 

// .udi_msc       = UDI_MSC_DESC_FS,

//! USB Interfaces descriptor value for Full Speed

#define UDI_COMPOSITE_DESC_FS \

.udi_cdc_iad0   = UDI_CDC_IAD_DESC_0, \

.udi_cdc_comm0  = UDI_CDC_COMM_DESC_0, \

.udi_cdc_data0  = UDI_CDC_DATA_DESC_0_FS, \

.udi_cdc_iad1   = UDI_CDC_IAD_DESC_1, \

.udi_cdc_comm1  = UDI_CDC_COMM_DESC_1, \

.udi_cdc_data1  = UDI_CDC_DATA_DESC_1_FS, \

.udi_msc       = UDI_MSC_DESC_FS

 

//! USB Interfaces descriptor value for High Speed

#define UDI_COMPOSITE_DESC_HS \

.udi_cdc_iad   = UDI_CDC_IAD_DESC_0, \

.udi_cdc_comm  = UDI_CDC_COMM_DESC_0, \

.udi_cdc_data  = UDI_CDC_DATA_DESC_0_HS, \

.udi_msc       = UDI_MSC_DESC_HS

 

//! USB Interface APIs

#define UDI_COMPOSITE_API \

&udi_api_cdc_comm, \

&udi_api_cdc_data, \

&udi_api_cdc_comm, \

&udi_api_cdc_data, \

&udi_api_msc

 

Then in main.c, I had to alter the interrupt priorities:

// Start USB stack to authorize VBus monitoring

udc_start();

NVIC_SetPriority(USB_IRQn, 0x03);

NVIC_SetPriority(SERCOM0_IRQn, 0x02);

NVIC_SetPriority(SERCOM1_IRQn, 0x01);

NVIC_SetPriority(SERCOM2_IRQn, 0x01);