This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB Composite Device for LPC134x

Hi,

I've created a firmware application for USB composite device in LPC1343, I found an example for this Micro controller which is the composite device is composed of CDC and MSC in AN11018 from nxp for my reference. What I did I've created a composite driver using USB HIDROM and USB MSCROM running in Keil, but unfortunately when i run the firmware it didn't enumerate the device. I used both of the on-chip driver of the LPC1343 for this firmware application. It is possible to combine this two?
I combine the code sample of on-chip driver for HID and MSC into one file but different function on each and call in the main function, but unfortunately it didn't worked. When I checked on the Device Manager, I found a "USB Mass Storage" with a warning sign (exclamation point). I think the device doesn't enumerated
properly.Could someone help me about this?

Thanks.

  • > I've created a composite driver using USB HIDROM and USB MSCROM

    The USB stack on the ROM (USBHID_rom and USBMem_rom) doesn't provide enough callbacks for class implementation, which requires for composite device. Start with full USBHID and USBMem source on this sample code, instead of the ROM version.

    Sample Code Bundle for LPC13xx Peripherals using Keil's MDK-ARM V1.05 (Mar 28, 2011)
    ics.nxp.com/.../code.bundle.lpc13xx.keil.zip



    > Suggestion to Keil programmer (if s/he would read this post :-)
    It's the time to re-organize the source code for class implementation.
    #if USB_MSC / #if USB_HID / #if USB_CDC, etc. on the source code indicate the place where callbacks for class implementation are inserted, instead of the #if's. And then, the stack code grows more tight and universal.

    Tsuneo

  • Hi Tsuneo,

    What about combining the HID (not in ROM) and using the ISP programming is it possible to create a composite device with this?

    Could you please elaborate more about the callback for class implementation is it the USB_ENDPOINT?

    thanks.

  • > What about combining the HID (not in ROM) and using the ISP programming is it possible to create a composite device with this?

    The USB ISP described in AN10986 is a stand-alone code in the boot ROM.
    It doesn't expose any callbacks for user's firmware.



    I recommend you to start with USBMem on above code bundle, and append USBHID to it.

    Like class implementation, composite device is made in three steps
    1) Descriptor work
    2) Implement Class request handler
    3) Add endpoint(s) process

    1) Descriptor work
    Device descriptor
    - Change VID/PID (at least PID) to another one, to prevent conflict with the original

    Configuration descriptor
    Append HID interface after MSC (Mass Storage Class) interface.
    Also, tune a couple of fields,

    usbdesc.c
    
    /* USB Configuration Descriptor */
    /*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */
    const uint8_t USB_ConfigDescriptor[] = {
    /* Configuration 1 */
      USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
      USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
      WBVAL(                             /* wTotalLength */
        1*USB_CONFIGUARTION_DESC_SIZE +
        1*USB_INTERFACE_DESC_SIZE     +
        2*USB_ENDPOINT_DESC_SIZE      +
        USB_INTERFACE_DESC_SIZE       +        // <-------------- increase by HID IF
        HID_DESC_SIZE                 +        // <--------------
        USB_ENDPOINT_DESC_SIZE                 // <--------------
      ),
      0x02,                              /* bNumInterfaces */   // <--------------
      0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
      0x00,                              /* iConfiguration: no string to describe this configuration */
      USB_CONFIG_BUS_POWERED /*|*/       /* bmAttributes */
    /*USB_CONFIG_REMOTE_WAKEUP*/,
      USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */
    
    /* Interface 0, Alternate Setting 0, MSC Class */
      USB_INTERFACE_DESC_SIZE,           /* bLength */
      USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
      0x00,                              /* bInterfaceNumber */
      0x00,                              /* bAlternateSetting */
      0x02,                              /* bNumEndpoints */
      USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
      MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
      MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
      0x04,                              /* iInterface */
    
    /* Endpoint, EP2 Bulk IN */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_IN(2),                /* bEndpointAddress */
      USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
      WBVAL(0x0040),                     /* wMaxPacketSize */
      0x00,                              /* bInterval: ignore for Bulk transfer */
    
    /* Endpoint, EP2 Bulk OUT */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_OUT(2),               /* bEndpointAddress */
      USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
      WBVAL(0x0040),                     /* wMaxPacketSize */
      0x00,                              /* bInterval: ignore for Bulk transfer */
                                             //
                                             // <------ append HID interface
                                             //
    /* Interface 1, Alternate Setting 0, HID Class */
      USB_INTERFACE_DESC_SIZE,           /* bLength */
      USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
      0x01,                              /* bInterfaceNumber */   // <--------------
      0x00,                              /* bAlternateSetting */
      0x01,                              /* bNumEndpoints */
      USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
      HID_SUBCLASS_NONE,                 /* bInterfaceSubClass */
      HID_PROTOCOL_NONE,                 /* bInterfaceProtocol */
      0x00,                              /* iInterface */
    /* HID Class Descriptor */
    /* HID_DESC_OFFSET = 0x0012 */
      HID_DESC_SIZE,                     /* bLength */
      HID_HID_DESCRIPTOR_TYPE,           /* bDescriptorType */
      WBVAL(0x0100), /* 1.00 */          /* bcdHID */
      0x00,                              /* bCountryCode */
      0x01,                              /* bNumDescriptors */
      HID_REPORT_DESCRIPTOR_TYPE,        /* bDescriptorType */
      WBVAL(HID_REPORT_DESC_SIZE),       /* wDescriptorLength */
    /* Endpoint, HID Interrupt In */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_IN(1),                /* bEndpointAddress */
      USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
      WBVAL(0x0004),                     /* wMaxPacketSize */
      0x20,          /* 32ms */          /* bInterval */
    
    /* Terminator */
      0                                  /* bLength */
    };
    

    Drag in HID Report Descriptor from USBHID\usbdesc.c to USBMem

    Drag in these definitions

    usbdesc.h
    
    #define HID_DESC_OFFSET              0x0012
    #define HID_DESC_SIZE               (sizeof(HID_DESCRIPTOR))
    #define HID_REPORT_DESC_SIZE        (sizeof(HID_ReportDescriptor))
    
    extern const uint8_t HID_ReportDescriptor[];
    extern const uint16_t HID_ReportDescSize;
    

    2) Class request handler
    Fortunately, Keil has already implemented HID class request handler on all of their examples. To enable it, modify these definitions.

    usbcfg.h
    
    #define USB_EP_EVENT        0x0005 // <---- 0x0007
    
    #define USB_HID             0      // <---- 1
    #define USB_HID_IF_NUM      0      // <---- 1
    

    Drag in these files to the project
    - hid.h
    - hiduser.h
    - hiduser.c

    3) Endpoint(s) process
    Replace these routines for the HID endpoints process
    I don't like this implementation, but it's just for your start point :-)

    usbuser.c
    
    #if USB_CONFIGURE_EVENT
    void USB_Configure_Event (void) {
    
      if (USB_Configuration) {                  /* Check if USB is configured */
        GetInReport();
        USB_WriteEP(0x81, &InReport, sizeof(InReport));
      }
    }
    #endif
    
    void USB_EndPoint1 (uint32_t event) {
    
      switch (event) {
        case USB_EVT_IN:
          GetInReport();
          USB_WriteEP(0x81, &InReport, sizeof(InReport));
          break;
      }
    }
    

    Lastly, finish the mods by merging main() on memory.c and demo.c
    Also, drag in demo.h

    That's all

    Tsuneo

  • Now I can create a composite device with HID and MSC w/o using the on-chip driver.
    My mistake is that I put an IAD in the USB Configuration Descriptor, and yet it is not allowed as you've answered me in the other thread. You're so great.And your replies really help me.
    One more thing,the device has been enumerated but theirs something I want to clarify, why is it that the Mass storage device(USB icon in the left side of my monitor) it seems it is been disable.I mean it can't be ejected, and when I open the enumerated the Removable Disk it can't be opened and Insert disk window will pop up showing that Removable Disk should be inserted.
    Is this about the memory size?

    Thanks.

  • Ummm..
    On my side, it works as we expect;
    It mounts a disk with single file, README.TXT

    On your side, sound like the MSC works, but disk contents are corrupted.
    Did you run it on RAM, instead of FLASH?

    I posted modified source here,

    www.8052.com/.../LPC134x_USBMem_HID.zip

    Compare it with yours.

    Tsuneo

  • Tsuneo,

    Thanks a lot. The only difference is the physicalMemorySize for the MSC.
    Now its working.

  • Hi Tsuneo,

    >>>>The USB ISP described in AN10986 is a stand-alone code in the boot ROM.
    >>>>It doesn't expose any callbacks for user's firmware.

    Could you explain me more about this?
    What are the advantages and disadvantages for ISP?
    Because I want to create an application as described in AN10986 but I want to combined it with another device class(HID or cdc).
    Can I ask a link for the steps on creating a composite device?Coz i didn't found a document for this.

    Thanks.

  • > Because I want to create an application as described in AN10986 but I want to combined it with another device class(HID or cdc).

    You should not "combine" USB ISP code with your USB application.
    Bootloader should be independent from your application code, to guarantee recovery from failed firmware update.

    Tsuneo

  • Hi,
    is there any documentation for Sample Code Bundle for LPC13xx that you mentioned?

    Tnx in advance.

    I

  • Maybe none.
    Change part number at the end of this URL, and you'll see documents for your target MCU on NXP web site.

    ics.nxp.com/.../

    Tsuneo

  • Tsuneo

    Thanks for the code. I tried porting it to the LPCxpresso environment and it almost works. The only change was to use the CodeRed header files (with GCC conventions for packed data).

    The MSD part seems to work 100%.

    For the HID part I updated the definition of HID_DESC_OFFSET:

    /*
    #define HID_DESC_OFFSET              0x0012
    */
    #define HID_DESC_OFFSET             ( 1 * USB_CONFIGUARTION_DESC_SIZE +  \ 
                                          1 * USB_INTERFACE_DESC_SIZE     +  \ 
                                          2 * USB_ENDPOINT_DESC_SIZE      +  \ 
                                          1 * USB_INTERFACE_DESC_SIZE        )
    
    

    There is still something wrong. Running the usbhid example code we see these transactions on USBlyzer:

    Select Configuration - Success
    Class Interface/Set Idle - Success
    Get Descriptor From Interface - Success
    

    Running the composite device code we see (after a bunch of successful MSD transactions):

    Select Configuration - Success
    Class Interface/Set Idle - Fail (Invalid Parameter) Status = 8000_0300h
    Get Descriptor From Interface - Fail (Invalid Parameter)
    

    I am debugging right now, but any hints as to where the problem might lie would be appreciated - the Keil code isn't the easiest to read.

    Tim