Problems implementing USB composite device

I'm trying to create a composite device with a CDC-ACM stack and a USBX Mass Storage stack.  I've have gotten each to work individually, but when I try to use both in same thread, I get compilation warnings about #defines in the common_data file being redfined, and the unit does not show as a USB device when plugged in while running this code.  I ran into a run-time problem with the memory pool size being insufficient initially, but I doubled the size of the pool and I am not getting any run time errors that I've caught.  The Mass Storage area is a RAM disk located in external SDRAM, if it matters.

Are there any examples of creating a composite CDC-ACM/Mass Storage stack?  I'm using SSP 1.4.0 on a custom board with a S5D9 processor.

Thanks,

-paul

  • pfvogel,

    Here is an example configuration of a compound device using the CDC class and the MSC class.   You might have to change the string tables for your application as well as the  VID and PID.  Please note that the USB pool size should be around 0x10000 bytes to accommodate both devices.

    Module Stacks:

    USB Device Config:

    MSC Interface descriptor

    CDC interface desc

     

    String descriptor framework

    const UCHAR g_usb_string_framework[] =
    {
    /* Index #1 (this example shows manufacturer information) */
    (uint8_t) (0x0409), /* Byte0 Language Code, US English */
    (uint8_t) (0x0409 >> 8), /* Byte1 Language Code */
    0x01, /* Byte2 Index */
    7, /* Byte3 Length */
    'R', 'E', 'N', 'E', 'S', 'A', 'S',

    /* Index #2 (this example shows product information) */
    (uint8_t) (0x0409), /* Byte0 Language Code, US English */
    (uint8_t) (0x0409 >> 8), /* Byte1 Language Code */
    0x02, /* Byte2 Index */
    31, /* Byte3 Length */
    'R','e','n','a','s','a','s',' ',
    'S','y','n','e','r','g','y','®',' ',
    'Y', 'I', 'O', 'T', 'S', '5', 'D', '9', 'P', 'I', 'L', 'L', 'A', 'R',

    /* Index #3 (this example shows MSC Class string) */
    (uint8_t) (0x0409), /* Byte0 Language Code, US English */
    (uint8_t) (0x0409 >> 8), /* Byte1 Language Code */
    0x03, /* Byte2 Index */
    10, /* Byte3 Length */
    'M', 'S', 'C', ' ', 'D', 'E', 'V', 'I', 'C', 'E',

    /* Index #4 (this example shows Device Serial Number information) */
    (uint8_t) (0x0409), /* Byte0 Language Code, US English */
    (uint8_t) (0x0409 >> 8), /* Byte1 Language Code */
    0x04, /* Byte2 Index */
    4, /* Byte3 Length */
    '0', '1', '0', '0',
    /* Index #5 (this example shows Alternate configuration information) */
    (uint8_t) (0x0409), /* Byte0 Language Code, US English */
    (uint8_t) (0x0409 >> 8), /* Byte1 Language Code */
    0x04, /* Byte2 Index */
    14, /* Byte3 Length */
    'S', 'e', 'r', 'i','a','l',' ','C','o','n','s','o','l','e'

    };

     

    Excerpt from synergy_cfg.txt

    Instance "g_ux_device_class_storage USBX Device Class Mass Storage"
    Name: g_ux_device_class_storage
    Mass Storage Class Parameter Setup: Auto (Simple Auto Setup if LUN is 1)
    User Setup Callback (Only valid if Parameter Setup is Auto): ux_device_class_storage_user_setup
    Last LBA of Storage Media (Only valid if Parameter Setup is Auto): 32767
    Bytes Per Sector of Storage Media (Only valid if Parameter Setup is Auto): 512
    Type of Storage Media (Only valid if Parameter Setup is Auto): 0
    Removable Flag of Storage Media (Only valid if Parameter Setup is Auto): 0x80
    Media Read Function Callback (Only valid if Parameter Setup is Auto): usb_media_read
    Media Write Function Callback (Only valid if Parameter Setup is Auto): usb_media_write
    Media Status Function Callback (Only valid if Parameter Setup is Auto): usb_media_status
    USBX Device Storage Instance Activate Callback Function: NULL
    USBX Device Storage Instance Deactivate Callback Function: NULL
    Name of generated initialization function: ux_device_class_storage_init0
    Auto Initialization: Disable

    Instance "USBX Device Configuration"
    Vendor ID: 0x045B
    Product ID: 0x5302
    Device Release Number: 0x0100
    Index of Manufacturer String Descriptor: 0x001
    Index of Product String Descriptor: 0x002
    Index of Serial Number String Descriptor: 0x003
    Class Code: Miscellaneous
    Index of String Descriptor describing this configuration: 0x004
    Size of USB Descriptor in bytes for this configuration (Modify this value only for Vendor-specific Class, otherwise set zero): 0x00
    Number of Interfaces (Modify this value only for Vendor-specific Class, otherwise set zero): 0x00
    Self-Powered: Disable
    Remote Wakeup: Disable
    Maximum Power Consumption (in 2mA units): 250
    Supported Language Code: 0x0409
    Name of USBX String Framework: g_usb_string_framework
    Total index number of USB String Descriptors in USBX String Framework: 5
    Name of USBX Language Framework: NULL
    Number of Languages to support (US English is applied if zero is set): 0
    Name of generated initialization function: ux_device_init0
    Auto Initialization: Enable

    Instance "g_sf_el_ux_dcd_fs_0 USBX Port DCD on sf_el_ux for USBFS"
    Name: g_sf_el_ux_dcd_fs_0
    USB Controller Selection: USBFS

    Instance "USBX on ux"
    USBX Pool Memory Name: g_ux_pool_memory
    USBX Pool Memory Size: 0x10000
    User Callback for Host Event Notification(Only valid for USB Host): NULL
    Name of generated initialization function: ux_common_init0
    Auto Initialization: Enable

    Instance "g_usb_interface_descriptor_storage_0 USBX Interface Configuration Mass Storage Class"
    Name: g_usb_interface_descriptor_storage_0
    Interface Number of Bulk-Only Data Interface: 0x02
    Endpoint Number to be used for Bulk Out transfer: Endpoint 4
    Endpoint Number to be used for Bulk In transfer: Endpoint 5

    Instance "g_sf_comms0 Communications Framework on sf_el_ux_comms"
    Name: g_sf_comms0
    Name of generated initialization function: sf_comms_init0
    Auto Initialization: Enable

    Instance "g_ux_device_class_cdc_acm0 USBX Device Class CDC-ACM"
    Name: g_ux_device_class_cdc_acm0
    USBX CDC-ACM instance_activate Function Callback: ux_cdc_device0_instance_activate
    USBX CDC-ACM instance_deactivate Function Callback: ux_cdc_device0_instance_deactivate
    Name of generated initialization function: ux_device_class_cdc_acm_init0
    Auto Initialization: Enable

    Instance "USBX Device Configuration"
    Vendor ID: 0x045B
    Product ID: 0x5302
    Device Release Number: 0x0100
    Index of Manufacturer String Descriptor: 0x001
    Index of Product String Descriptor: 0x002
    Index of Serial Number String Descriptor: 0x003
    Class Code: Miscellaneous
    Index of String Descriptor describing this configuration: 0x004
    Size of USB Descriptor in bytes for this configuration (Modify this value only for Vendor-specific Class, otherwise set zero): 0x00
    Number of Interfaces (Modify this value only for Vendor-specific Class, otherwise set zero): 0x00
    Self-Powered: Disable
    Remote Wakeup: Disable
    Maximum Power Consumption (in 2mA units): 250
    Supported Language Code: 0x0409
    Name of USBX String Framework: g_usb_string_framework
    Total index number of USB String Descriptors in USBX String Framework: 5
    Name of USBX Language Framework: NULL
    Number of Languages to support (US English is applied if zero is set): 0
    Name of generated initialization function: ux_device_init0
    Auto Initialization: Enable

    Instance "g_sf_el_ux_dcd_fs_0 USBX Port DCD on sf_el_ux for USBFS"
    Name: g_sf_el_ux_dcd_fs_0
    USB Controller Selection: USBFS

    Instance "USBX on ux"
    USBX Pool Memory Name: g_ux_pool_memory
    USBX Pool Memory Size: 0x10000
    User Callback for Host Event Notification(Only valid for USB Host): NULL
    Name of generated initialization function: ux_common_init0
    Auto Initialization: Enable

    Instance "g_usb_interface_desc_cdcacm_0 USBX Interface Configuration CDC-ACM"
    Name: g_usb_interface_desc_cdcacm_0
    Interface Number of Communications Class interface: 0x00
    Interrupt Transfer endpoint to use for Communications Class: Endpoint 3
    Polling period for Interrupt Endpoint (in mS/125us units for FS/HS): 0x0F
    Interface Number of Data Class interface: 0x01
    Bulk In Transfer endpoint to use for Data Class: Endpoint 1
    Bulk Out Transfer endpoint to use for Data Class: Endpoint 2
    Index of String Descriptor Describing Communications Class interface (Interface Descriptor:iInterface).: 0x05
    Index of String Descriptor Describing Data Class interface (Interface Descriptor:iInterface).: 0x00

    -Gary

  • In reply to garyj:

    Dear Gary,
    thank you for your example, but the pictures of module stacks (first two pictures) and interface desc (for MSC and CDc) are the same. Could you please provide us with correct pictures? If you could upload this example project it will be very helpful. Thank you for your support.

    Best Regards, Nikita.
  • In reply to dxwak:

    Nikita,

     

    Sorry about the cut/paste error - here is the module stacks for the CDC class device:

    The project that I have is for an unreleased board - I can't post it yet but you can see how the endpoint numbers are assigned in the prior post.

     

    -Gary

  • In reply to garyj:

    Hello, Gary.
    I can not reproduce this example in IAR. In the "_ux_device_stack_initialize" function, the loop "while (device_framework_length != 0)" is infinitely executed.
  • In reply to Alex:

    Hi Alex,

    In IAR, two interface descriptors are placed in .usb_interface_desc_fs section, but there are some 0's between them due to alignment. The generated code copies the section directly:

    /* Copy Interface Descriptors */
    memcpy (p_device_framework, (uint8_t *)__section_begin(".usb_interface_desc_fs"), USB_TOTAL_LENGTH);

    which introduces 0's in the variable later used by ux_device_stack_initialize. To avoid it, please edit common_data.c (and mark it as read-only after changes). Right before ux_device_stack_initialize is called, instead of:

    /* Copy Interface Descriptors */
    memcpy (p_device_framework, (uint8_t *)__section_begin(".usb_interface_desc_fs"), USB_TOTAL_LENGTH);

    Put:

    /* Copy CDC-ACM Interface descriptor */
    memcpy (p_device_framework, (uint8_t *)g_usb_interface_desc_cdcacm_0_full_speed, sizeof(g_usb_interface_desc_cdcacm_0_full_speed));
    p_device_framework = p_device_framework + sizeof(g_usb_interface_desc_cdcacm_0_full_speed);
    /* Copy MS Interface descriptor */
    memcpy (p_device_framework, (uint8_t *)g_usb_interface_descriptor_storage_0_full_speed, sizeof(g_usb_interface_descriptor_storage_0_full_speed));

    --EDIT--:

    Alternatively --no_const_align option should be added to Extra options in compiler settings (Project > Options... > C/C++ Compiler > Extra Options).

    Regards,
    adboc

  • In reply to garyj:

    Thanks Gary -- I finally got a chance to test this yesterday and everything is working now. BTW, the above picture for the CDC Interface desc is a copy of the Mass Storage picture, but the default values for the CDC worked for me and it's pretty easy to get the values to use from the synergy_cfg.txt excerpt.

    Thanks again,
    -paul