This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM48L952: May I get any reference code for internal DMA of USB for MSC device mode?

Part Number: RM48L952

Dear TI,

I'm developing the USB MSC device class to refer to the CDC example code provided by TI and MSC part of Tivaware code.

I've completed to see "FORMAT popup" without using internal DMA when connect the RM48 to Host PC.

At this point, I guess that the internal DMA  should be implemented because the transfers for BULK may need the DMA interrupt source too.

It seems that Using only USB interrupt has a limitation in order to develop the MSC class in the reference code structure.

Let me attach the USB log which show my current status.

There is no more progress after the device receive the MBR data from the HOST and write them into file system. 

As I analyzed other USB reference stick, IN DATA interrupt should be occurred . 

Anyway, my conclusion is that without using the DMA, code sequence may go wrong. 

The Tivaware reference code also use DMA whether internal or external.

So Could you provide any example code for internal DMA of USB?

Thank you

Best regards.

  • Hi Youngmin,

    The TM4C129 device has OTG, but the USB host on RM48 is based on OHCI spec . They are different. OTG has its DAM integrated. The OHCI on RM48 doesn't have DMA, but the USB1.1 host controller access the data structures without processor direct intervention (acts as DMA). The data structures can be located in internal SRAM or external SDRAM.
  • Dear Wang,

    Thanks for your kindly answers.

    Although my question is so idiot, please take care me. Because it is my first time to handle the USB driver.

    I think your mention is about the USB host on RM48. However I'm developing the MSC class using the "USB device controller". 

    and then there are some DMA configuration as below.

    It seems that I should use the main DMA of rm48 and below DMA configuration in order to develop the device MSC class.

    I found an example named "example_mibspiDma.c". It seems to use both the main DMA of rm48 and DMA configuration of SPI.

    So, May I get this kind of example (mibspiDma) for the USB device controller?

    Thank you

    Best regards.

  • Hello Youngmin,

    Sorry for my later response. My understanding is that you are developing USB MSC driver which makes a USB device (for example USB flash memory) accessible to a host (for example RM48) and enables file transfers between the host and the USB device. If you use RM48 device controller, who is the host?

    If you use RM48 USB device controller, yes you can use DMA to transfer data for IN endpoints and OUT endpoints. I posted my MibSPI + DMA samle code in the following thread:

    e2e.ti.com/.../2753281
  • Dear Wang,

    Thanks for your response.

    First of all, I've done to implement the DMA RX function to refer your guide as below setting.

    So I can see that the data of OUT endpoint are transferred into the SDRAM memory(RAMDISK) from endpoint.

    Endpoint : 0x01

    USB DMA channel : 0

    Main DMA channel : 15

    Function Name : USBDMAChannelRxSet()

    However, the DMA TX function is not still working.

    Although I've tried to enter various parameters for DMA,  the TXN_DONE interrupt has never been asserted.

    The purpose of this function is to transfer the SDRAM memroy data(RAMDISK) to IN endpoint.

    Endpoint : 0x02

    USB DMA channel : 1

    Main DMA channel : 14

    Function Name : USBDMAChannelTxSet()

    For testing, I've added a testBuffer as source.

    Could you check an attached code which I've worked?

    I need your help about USBDMAChannelTxSet() function.

    7065.usb_device_dma.c

  • Dear Wang,

    First of all, thanks for your reply. 

    I'm using the reference code from where you suggested.

    Anyway, I've succeed that the TXn_DONE interrupt is asserted using the TX-DMA.

    However, I've faced an abnormal case which I couldn't understand.

    If TXn_DONE interrupt is asserted, my code will start the Non-ISO TX DMA done handler.

    Assume that EOTn is 0(no more remaining packet for transmit), I progress below two things.

    1. Disable the DMA

    2. Send the SCSI status via IN ENDPOINT

    The purpose of #2 is to send the SCSI status thorough IN packet covered by red circle in attached file.

    But at this time (Send the SCSI status), the ACK for OUT(covered by blue) is also transmitted via OUT endpoint . (abnormal1.png)

    This symptom makes to skip the next IN process because the OUT ACK is transmitted abnormally. (abnormal2.png)

    So I wonder why the ACK for OUT packet is transmitted, even if the EP_NUM.EP_DIR is "1".

    I just used the USBEndpointDataPut() and USBEndpointDataSend() from TI.

    Please refer below my comment for code.

    /* When I send a SCSI status, I use below function */

    static void
    USBDSCSISendStatus(tUSBDMSCDevice *psMSCDevice)
    {
    tMSCInstance *psInst;

    //
    // Get our instance data pointer.
    //
    psInst = &psMSCDevice->sPrivateData;

    //
    // Respond with the requested status.
    //
    USBEndpointDataPut(USB0_BASE, psInst->ui8INEndpoint,
    (UInt8 *)&g_sSCSICSW, 13);
    USBEndpointDataSend(USB0_BASE, psInst->ui8INEndpoint, USB_TRANS_IN);

    //
    // Move the state to status sent so that the next interrupt will move the
    // statue to idle.
    //
    psInst->ui8SCSIState = STATE_SCSI_SENT_STATUS;
    }

    /* USBDSCSISendStatus() is consist of below two functions */

    uint32
    USBEndpointDataPut(uint32 ulBase, uint16 usEndpoint,
    uint8 * pucData, uint32 ulSize)
    {
    uint16 epNum;
    uint32 txSize = ulSize;
    uint32 i;
    uint8 * buff = pucData;

    /* Check the arguments. */
    ASSERT(ulBase == USBD_0_BASE);
    ASSERT((usEndpoint == USB_EP_0) || (usEndpoint == USB_EP_1) ||
    (usEndpoint == USB_EP_2) || (usEndpoint == USB_EP_3) ||
    (usEndpoint == USB_EP_4) || (usEndpoint == USB_EP_5) ||
    (usEndpoint == USB_EP_6) || (usEndpoint == USB_EP_7) ||
    (usEndpoint == USB_EP_8) || (usEndpoint == USB_EP_9) ||
    (usEndpoint == USB_EP_10) || (usEndpoint == USB_EP_11) ||
    (usEndpoint == USB_EP_12) || (usEndpoint == USB_EP_13) ||
    (usEndpoint == USB_EP_14) || (usEndpoint == USB_EP_15));

    usEndpoint = usEndpoint >> 4;

    /* backup the EP number to restore later */
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Statically defined non-null hardware register address" */
    epNum = usbd0Regs->epnum & USBD_EP_NUM_EP_NUM_MASK;

    /* Enable access to endpoint fifo */
    if (txSize > 64u) {
    txSize = 64u;
    }

    /* Setup epnum register for OUT EP */
    usbd0Regs->epnum = USBD_EP_NUM_EP_SEL | USBD_EP_DIR_IN | (usEndpoint & USBD_EP_NUM_EP_NUM_MASK);

    /* Dump the data */
    for (i=0u; i<txSize; i++) {
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Statically defined non-null hardware register address" */
    /*SAFETYMCUSW 95 S MR:11.4 <INSPECTED> "Reason - Acceptable deviation."*/
    /*SAFETYMCUSW 94 S MR:11.4 <INSPECTED> "Reason - Acceptable deviation."*/
    *((volatile uint8 *)(&usbd0Regs->data)) = *buff;
    buff++;
    }

    /* Restore the epnum register */
    /* usbd0Regs->epnum = USBD_EP_NUM_EP_SEL | USBD_EP_DIR_IN | epNum; ### */

    usEndpoint = usEndpoint << 4;

    return(0);
    }

    uint32 USBEndpointDataSend(uint32 ulBase, uint16 usEndpoint, uint32 ulTransType)
    {
    /* Check the arguments. */
    ASSERT(ulBase == USBD_0_BASE);
    ASSERT((usEndpoint == USB_EP_0) || (usEndpoint == USB_EP_1) ||
    (usEndpoint == USB_EP_2) || (usEndpoint == USB_EP_3) ||
    (usEndpoint == USB_EP_4) || (usEndpoint == USB_EP_5) ||
    (usEndpoint == USB_EP_6) || (usEndpoint == USB_EP_7) ||
    (usEndpoint == USB_EP_8) || (usEndpoint == USB_EP_9) ||
    (usEndpoint == USB_EP_10) || (usEndpoint == USB_EP_11) ||
    (usEndpoint == USB_EP_12) || (usEndpoint == USB_EP_13) ||
    (usEndpoint == USB_EP_14) || (usEndpoint == USB_EP_15));

    usEndpoint = usEndpoint >> 4;

    /* Setup the ep fifo */
    usbd0Regs->epnum = USBD_EP_NUM_EP_SEL | USBD_EP_DIR_IN | (usEndpoint & USBD_EP_NUM_EP_NUM_MASK);

    /* Enable the fifo */
    /*SAFETYMCUSW 184 S <INSPECTED> "Reason - LDRA tool issue."*/
    USBD_REG_SET_ONE(usbd0Regs->ctrl, USBD_CTRL_SET_FIFO_EN);

    /* Remove fifo access */
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Statically defined non-null hardware register address" */
    /*SAFETYMCUSW 184 S <INSPECTED> "Reason - LDRA tool issue."*/
    /*SAFETYMCUSW 185 S <INSPECTED> "Reason - LDRA tool issue."*/
    USBD_REG_BIT_CLR(usbd0Regs->epnum, USBD_EP_NUM_EP_SEL); <- At this point, status message (IN packet) and OUT ACK are transmitted simultaneously.

    usEndpoint = usEndpoint << 4;

    return(0);
    }

    /* abnormal1.png */

    /* abnormal2.png */

  • Hi Youngmin,

    You know USB programming more than me. I am not able to debug your code.