AnsweredAssumed Answered

USB device control transfer + bulk transfer bare-metal example - No RTOS

Question asked by penguin007 on Sep 28, 2015
Latest reply on Mar 7, 2016 by tcmichals

Hi,

 

 

the reason I write this post is that, currently ADI doen's provide any example not requiring RTOS.RTOS license and usb-device license are just too expensive and not necessary. I've spent much time on it and finally it works. This source code is about USB2.0, high speed, device control transfer + bulk transfer. Just for reference only. Here is the source file USB_TEST.c:

 

 

/*****************************************************************************

 

* USB_TEST.c

 

*****************************************************************************/

 

//IDE: CCES2.0.0.0

 

//Hardware: ADI Blackfin 527

 

/*Description:

 

USB as a device communicates with host. Control and Bulk transfer. In this program 4 endpoints(except EP0) are defined, only two of them are used:

 

EpInfo[4] as Rx and EpInfo[1] as Tx. The physical numbers are 0x06 and 0x05 respectively. Unlike in VisualDSP, in CCES all the descriptors(except endpoint descriptor)

 

are not given in the code, thus must be defined by user. Three callback functions, especially EP0 Callback and EP Data Callback functions must be defined by user.

 

One modification in ADI's original API is required, they are in the adi_usbh_dev_musbmhdrc_intrpt.c file:

 

insert

 

pEpInfo->pEpCurURB->pData = pEpInfo->pEpBufferdata;

 

after

 

line 734: pRegs->INDEX = SavedEpNum;

 

*/

 

#include "USB_TEST.h"

 

#include "stdio.h"

 

/**

 

* global variable(s)

 

*/

 

ADI_USB_HANDLE hUsbDevice;

 

ADI_MUSBMHDRC_DATA *pUsbData;

 

//ADI_USB_URB* pUsbUrbEPData;

 

ADI_USB_URB UsbUrbEPData[5];

 

uint32_t result;

 

uint8_t* pTxOfflineBuffer;

 

uint8_t* pRxOfflineBuffer;

 

uint8_t* pTxOnlineBuffer;

 

uint8_t* pRxOnlineBuffer;

 

//Set default device descriptor, configuration descriptor, interface descriptor

 

DEVICE_DESCRIPTOR         DeviceDescriptor;

 

CONFIGURATION_DESCRIPTOR     ConfigDescriptor;

 

CONFIGURATION_FULL_DESCRIPTOR    ConfigFullDescriptor;

 

STRING_DESCRIPTOR         StringDescriptor[3];

 

ADI_USB_EP_DESC         EP0Descriptor;

 

bool epConfig = false;

 

bool epBulk = false;

 

//Initialize Endpoint descriptors except EP0. EP0 is initialized in Init_Descriptor()

 

void Init_EPx(ADI_USB_EP_DESC* EPDescriptor)

 

{

 

    //Endpoint Descriptor 7 bytes

 

    EPDescriptor[0].Length = 7;

 

    EPDescriptor[0].DescriptorType = 5;

 

    EPDescriptor[0].EndpointAddress = 0x85; //Input

 

    EPDescriptor[0].Attributes = 0x02;    //Bulk | No sync | Data

 

    EPDescriptor[0].MaxPacketSize = 512; //1 Transaction / µFrame

 

    EPDescriptor[0].Interval = 0;

 

    //Endpoint Descriptor 7 bytes

 

    EPDescriptor[1].Length = 7;

 

    EPDescriptor[1].DescriptorType = 5;

 

    EPDescriptor[1].EndpointAddress = 0x06; //Output

 

    EPDescriptor[1].Attributes = 0x02;    //Bulk | No sync | Data

 

    EPDescriptor[1].MaxPacketSize = 512; //1 Transaction / µFrame

 

    EPDescriptor[1].Interval = 0;

 

    //Endpoint Descriptor 7 bytes

 

    EPDescriptor[2].Length = 7;

 

    EPDescriptor[2].DescriptorType = 5;

 

    EPDescriptor[2].EndpointAddress = 0x87; //Input

 

    EPDescriptor[2].Attributes = 0x02;    //Bulk | No sync | Data

 

    EPDescriptor[2].MaxPacketSize = 512; //1 Transaction / µFrame

 

    EPDescriptor[2].Interval = 0;

 

    //Endpoint Descriptor 7 bytes

 

    EPDescriptor[3].Length = 7;

 

    EPDescriptor[3].DescriptorType = 5;

 

    EPDescriptor[3].EndpointAddress = 0x08; //Output

 

    EPDescriptor[3].Attributes = 0x02;    //Bulk | No sync | Data

 

    EPDescriptor[3].MaxPacketSize = 512; //1 Transaction / µFrame

 

    EPDescriptor[3].Interval = 0;

 

}

 

/**

 

* Set default device descriptor, configuration descriptor, interface descriptor, string descriptors

 

*/

 

void Init_Descriptor(    PDEVICE_DESCRIPTOR pDeviceDescriptor,

 

                 PCONFIGURATION_DESCRIPTOR pConfigDescriptor,

 

            PCONFIGURATION_FULL_DESCRIPTOR pConfigFullDescriptor,

 

            PSTRING_DESCRIPTOR pStringDescriptorLang,

 

            PSTRING_DESCRIPTOR pStringDescriptor0,

 

            PSTRING_DESCRIPTOR pStringDescriptor1,

 

            ADI_USB_EP_DESC* pEP0Descriptor

 

            )

 

{

 

/*

 

*  Descriptors Initalization here!!!!!!

 

*/

 

}

 

/*

 

* Initialize the User Request Block

 

*/

 

void Init_Urb(ADI_USB_URB* pUsbUrb)

 

{

 

    uint8_t i;

 

    for(i= 0; i<5; i++)

 

    {

 

        pUsbUrb[i].EpAddr = 0;                  /*!< URB's Logical Endpoint Address      */

 

        pUsbUrb[i].EpType = ADI_USB_EP_TYPE_BULK;    /*!< URB's Logical Endpoint type         */

 

        pUsbUrb[i].EpDir = ADI_USB_EP_DIR_NONE;     /*!< URB's Logical Endpoint Address      */

 

        pUsbUrb[i].TransferLen = 0;              /*!< Transfer length                     */

 

        pUsbUrb[i].ProcessedBytes = 0;                /*!< Total number of Processed bytes     */

 

        pUsbUrb[i].pData = NULL;                  /*!< Buffer pointer                      */

 

        pUsbUrb[i].DevAddr = 0;                 /*!< Device address                      */

 

        pUsbUrb[i].pHostSubmitURB = NULL;          /*!< URB submitted by USB Stack          */

 

           pUsbUrb[i].EpResult = ADI_USB_RESULT_SUCCESS;    /*!< URB Result                          */

 

         //ADI_USB_URB_DATAUNIT UrbUnits[ADI_USB_CFG_MAX_NUM_QUEUED_BUFS];

 

          pUsbUrb[i].CurWriteIdx = 0;           

 

            pUsbUrb[i].CurReadIdx = 0;

 

            pUsbUrb[i].CurUrbCount = 0;           

 

    }

 

}

 

//Set device speed to High Speed -- Not necessary, since high speed detection is done by hardware.

 

//void adi_musbmhdrc_SpdSet(ADI_USB_HANDLE const hDevice, ADI_USB_SPEED DevSpd)

 

//{

 

//    ADI_MUSBMHDRC_DATA *pUsbDrvData = (ADI_MUSBMHDRC_DATA *)hDevice;

 

//    pUsbDrvData->DevSpd = DevSpd;

 

//}

 

//reload/fill FIFO, set direction, set state to IDLE. Finally set TxPktRdy and DataEnd bit for transfer.

 

void EP0CmdHandler(USB_SETUP_REQ UsbSetupPacket)

 

{

 

    switch(UsbSetupPacket.bRequest)

 

    {

 

    case GET_DESCRIPTOR:

 

        switch((UsbSetupPacket.wValue)>>8)

 

        {

 

        case DEVICE:

 

            UsbUrbEPData[0].EpType = ADI_USB_EP_TYPE_CONTROL;

 

            UsbUrbEPData[0].EpDir = ADI_USB_EP_DIR_TX;

 

            UsbUrbEPData[0].TransferLen = 18u;

 

            UsbUrbEPData[0].pData = (uint8_t *)&DeviceDescriptor;

 

            pUsbData->EpInfo[0].EpUrbState = ADI_USB_URB_STATE_FREE;

 

            //Use adi_musbmhdrc_SubmitURB(). There is an alternative way, reference other cases such as CONFIGURATION.

 

            adi_musbmhdrc_SubmitURB ((ADI_USB_HANDLE)pUsbData, &UsbUrbEPData[0]);

 

            pUsbData->pRegs->EP0_CSR0 |= (ENUM_USB_EP0I_CSR_P_TXPKTRDY | ENUM_USB_EP0I_CSR_P_DATAEND);

 

            pUsbData->EpZeroSetupState = ADI_USB_SETUP_IDLE;

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_RX;

 

            break;

 

        case CONFIGURATION:

 

            if(UsbSetupPacket.wLength == 9)

 

            {

 

                //reload FIFO

 

                pUsbData->EpInfo[0].pEpBufferdata = (uint8_t *)&ConfigDescriptor;

 

                pUsbData->EpInfo[0].EpProcBytesThisPass = 9u;

 

            }

 

            else if(UsbSetupPacket.wLength >= 46)

 

            {

 

                //reload FIFO

 

                pUsbData->EpInfo[0].pEpBufferdata = (uint8_t *)&ConfigFullDescriptor;

 

                pUsbData->EpInfo[0].EpProcBytesThisPass = 46u;

 

            }

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_TX;

 

            adi_usbdrv_ScheduleDma(pUsbData, &pUsbData->EpInfo[0]);

 

            //wait a little bit until transfer complete

 

            adi_usbdrv_WaitMilliSec(1u);

 

            //Set TxPktRdy and DataEnd

 

            pUsbData->pRegs->EP0_CSR0 |= (ENUM_USB_EP0I_CSR_P_TXPKTRDY | ENUM_USB_EP0I_CSR_P_DATAEND);

 

            //switch state

 

            pUsbData->EpZeroSetupState = ADI_USB_SETUP_IDLE;

 

            //prepare for the next transition

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_RX;

 

            break;

 

        case INTERFACE:

 

            break;

 

        case ENDPOINT:

 

            break;

 

        case STRING:

 

            if(((UsbSetupPacket.wValue)&0x000f) == 0) //Descriptor Index = 0: language ID

 

            {

 

                pUsbData->EpInfo[0].pEpBufferdata = (uint8_t *)&StringDescriptor[0];

 

                pUsbData->EpInfo[0].EpProcBytesThisPass = 4u;

 

            }

 

            else if(((UsbSetupPacket.wValue)&0x000f) == 1) //Descriptor Index = 1: iProduct

 

            {

 

                pUsbData->EpInfo[0].pEpBufferdata = (uint8_t *)&StringDescriptor[1];

 

                pUsbData->EpInfo[0].EpProcBytesThisPass = 42u;

 

            }

 

            else if(((UsbSetupPacket.wValue)&0x000f) == 2) //Descriptor Index = 2: iProduct

 

            {

 

                pUsbData->EpInfo[0].pEpBufferdata = (uint8_t *)&StringDescriptor[2];

 

                pUsbData->EpInfo[0].EpProcBytesThisPass = 40u;

 

            }

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_TX;

 

            adi_usbdrv_ScheduleDma(pUsbData, &pUsbData->EpInfo[0]);

 

            //wait a little bit until transfer complete

 

            adi_usbdrv_WaitMilliSec(1u);

 

            //Set TxPktRdy and DataEnd

 

            pUsbData->pRegs->EP0_CSR0 |= (ENUM_USB_EP0I_CSR_P_TXPKTRDY | ENUM_USB_EP0I_CSR_P_DATAEND);

 

            //switch state

 

            pUsbData->EpZeroSetupState = ADI_USB_SETUP_IDLE;

 

            //prepare for the next transition

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_RX;

 

            break;

 

        default:

 

            break;

 

        }

 

        break;

 

        case GET_CONFIGURATION:

 

            break;

 

        case GET_INTERFACE:

 

            break;

 

        case CLEAR_FEATURE:

 

            //wValue and wIndex validation necessary?

 

            //clear PktRdy and set DataEnd bit

 

            pUsbData->pRegs->EP0_CSR0 |= (ENUM_USB_EP0I_CSR_P_SPKTRDY | ENUM_USB_EP0I_CSR_P_DATAEND);

 

            //wait a little bit until transfer complete

 

            adi_usbdrv_WaitMilliSec(1u);

 

            //switch state

 

            pUsbData->EpZeroSetupState = ADI_USB_SETUP_IDLE;

 

            //prepare for the next transition

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_RX;

 

            break;

 

        case SET_ADDRESS:

 

            result = adi_musbmhdrc_SetDevAddress(pUsbData, (uint8_t)UsbSetupPacket.wValue);

 

            CheckResult("adi_musbmhdrc_SetDevAddress",result);

 

            //switch state

 

            pUsbData->EpZeroSetupState = ADI_USB_SETUP_IDLE;

 

            //prepare for the next transition

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_RX;

 

            break;

 

        case SET_CONFIGURATION:

 

            if((UsbSetupPacket.wValue & 0xff) == ConfigDescriptor.bConfigurationValue)

 

            {

 

                pUsbData->DevState = ADI_USB_DEV_STATE_CONFIGURED;

 

            }

 

            else

 

            {

 

                pUsbData->DevState = ADI_USB_DEV_STATE_ADDRESSED;

 

            }

 

            //clear PktRdy and set DataEnd bit

 

            pUsbData->pRegs->EP0_CSR0 |= (ENUM_USB_EP0I_CSR_P_SPKTRDY | ENUM_USB_EP0I_CSR_P_DATAEND);

 

            //wait a little bit until transfer complete

 

            adi_usbdrv_WaitMilliSec(1u);

 

            //switch state

 

            pUsbData->EpZeroSetupState = ADI_USB_SETUP_IDLE;

 

            //prepare for the next transition

 

            pUsbData->EpInfo[0].EpDir = ADI_USB_EP_DIR_RX;

 

            break;

 

        default:

 

            break;

 

    }

 

}

 

/**

 

* @brief       Data stage in control transfer

 

*

 

* @details     This callback is called within the adi_usbdrv_Ep0DmaHandler function. Descriptors are sent back to host according

 

*         to specific commands.

 

*

 

*        This is a brief description about the control transfer:

 

*        1. If a setup packet (8 bytes) received by device in the FIFO, program jumps to adi_usbdrv_USBInterruptHandler().

 

*            ACK is sent by hardware.

 

*        2. Then FIFO is unloaded via adi_usbdrv_RcvDataFromFifo() within the adi_usbdrv_HandleSetupPacket().

 

*        3. DMA interrupt is trigger and this callback function is called. EP0 state transition, RxPktRdy bit is cleared

 

*           within adi_usbdrv_Ep0DmaHandler().

 

*        4. If there is a data phase, FIFO should be filled. Use adi_usbdrv_ScheduleDma() to fill FIFO.

 

*        5. Set TxPktRdy and DataEnd.

 

*

 

*        All the tokens, ACKs, CRC are handled by the USB hardware automatically. The major work need be to done is the

 

*        filling FIFO with descriptors (if there is a data phase) and set/clear several bits in the CSR0 register.

 

*

 

* @param [in]  pCBParam            Client supplied callback parameter

 

*

 

* @param [in]  Event               Event ID specific to the Driver/Service

 

*

 

* @param [in]  pArg                8 bytes setup packet

 

*

 

* @return      none

 

*

 

* @note

 

*        Reference 1: usb_2.0(Revision 2.0) PDF

 

*                 chapter 9: USB Device Framework

 

*              2: ADSP-Bf52x Blackfin Processor hardware Reference (Revision 1.2)

 

*                 chapter 26: USB OTG Controller

 

*                 appendix A: System MMR Assignments

 

*

 

* @sa          adi_usbdrvd_EpDataCallback()

 

* @sa          adi_usbdrvd_BusEventCallback()

 

*/

 

void adi_usbdrvd_EpZeroCallback(void *pCBParam, uint32_t Event, void *pArg)

 

{

 

    if(Event == ADI_USB_RESULT_URB_COMPLETE)

 

    {

 

        USB_SETUP_REQ UsbSetupPacket;

 

        //Get 8 bytes setup data

 

        UsbSetupPacket = *(USB_SETUP_REQ*)pArg;

 

        EP0CmdHandler(UsbSetupPacket);

 

    }

 

}

 

void adi_usbdrvd_EpDataCallback(void *pCBParam, uint32_t Event, void *pArg)

 

{

 

    uint8_t *pData;

 

    pData = ((ADI_USB_URB*)pCBParam)->pData;

 

 

    if(Event == ADI_USB_RESULT_URB_COMPLETE)

 

    {

 

      /*

 

     User should reload FIFO by:

 

     define pUsbData->EpInfo[x].EpProcBytesThisPass =?;

 

     set pUsbData->EpInfo[x].EpDir = ?;

 

     reload FIFO adi_usbdrv_ScheduleDma(pUsbData, &pUsbData->EpInfo[x]);

 

     epBulk = true;

 

     pUsbData->EpInfo[x].pEpBufferdata = NULL;  //Necessary!!! Otherwise packets containing wrong data will be sent.

 

     */

 

    }

 

}//void

 

void adi_usbdrvd_BusEventCallback(void *pCBParam, uint32_t Event, void *pArg)

 

{

 

}

 

//EndpointX Information Configuration

 

void EPx_Config(void)

 

{

 

    uint8_t DevAddr;

 

    DevAddr = (uint8_t)pUsbData->pRegs->FADDR; //get the assigned device number

 

    ADI_USB_EP_DESC    EPDescriptor[4];

 

    Init_EPx(EPDescriptor);

 

    UsbUrbEPData[1].EpDir = ADI_USB_EP_DIR_TX;

 

    UsbUrbEPData[1].EpAddr = EPDescriptor[2].EndpointAddress;

 

    UsbUrbEPData[1].DevAddr = DevAddr;

 

    UsbUrbEPData[1].pData = pTxOfflineBuffer;

 

    //Config EpInfo[1]

 

    result = adi_musbmhdrc_EP_Open (hUsbDevice, &EPDescriptor[2], DevAddr);

 

    CheckResult("adi_musbmhdrc_EP_Open",result);

 

    pUsbData->EpInfo[1].EpTransferMode = ADI_USB_EP_MODE_DMA_0;

 

    pUsbData->EpInfo[1].pEpCurURB = &UsbUrbEPData[1];

 

   

 

    UsbUrbEPData[2].EpDir = ADI_USB_EP_DIR_RX;

 

    UsbUrbEPData[2].EpAddr = EPDescriptor[3].EndpointAddress;

 

    UsbUrbEPData[2].DevAddr = DevAddr;

 

    UsbUrbEPData[2].pData = pRxOnlineBuffer;

 

    //Config EpInfo[2]

 

    result = adi_musbmhdrc_EP_Open (hUsbDevice, &EPDescriptor[3], DevAddr);

 

    CheckResult("adi_musbmhdrc_EP_Open",result);

 

    pUsbData->EpInfo[2].EpTransferMode = ADI_USB_EP_MODE_DMA_0;

 

    pUsbData->EpInfo[2].pEpCurURB = &UsbUrbEPData[2];

 

    UsbUrbEPData[3].EpDir = ADI_USB_EP_DIR_TX;

 

    UsbUrbEPData[3].EpAddr = EPDescriptor[0].EndpointAddress;

 

    UsbUrbEPData[3].DevAddr = DevAddr;

 

    UsbUrbEPData[3].pData = pTxOnlineBuffer;

 

    //Config EpInfo[3]

 

    result = adi_musbmhdrc_EP_Open (hUsbDevice, &EPDescriptor[0], DevAddr);

 

    CheckResult("adi_musbmhdrc_EP_Open",result);

 

    pUsbData->EpInfo[3].EpTransferMode = ADI_USB_EP_MODE_DMA_0;

 

    pUsbData->EpInfo[3].pEpCurURB = &UsbUrbEPData[3];   

 

    UsbUrbEPData[4].EpDir = ADI_USB_EP_DIR_RX;

 

    UsbUrbEPData[4].EpAddr = EPDescriptor[1].EndpointAddress;

 

    UsbUrbEPData[4].DevAddr = DevAddr;

 

    UsbUrbEPData[4].pData = pRxOfflineBuffer;

 

    //Config EpInfo[4]

 

    result = adi_musbmhdrc_EP_Open (hUsbDevice, &EPDescriptor[1], DevAddr);

 

    CheckResult("adi_musbmhdrc_EP_Open",result);

 

    pUsbData->EpInfo[4].EpTransferMode = ADI_USB_EP_MODE_DMA_0;

 

    pUsbData->EpInfo[4].pEpCurURB = &UsbUrbEPData[4];

 

    //enable Rx Interrupt. Otherwise Rx interrupt will not be triggered and packet will not unloaded. See line 550, adi_usbh_dev_musbmhdrc_intrpt.c

 

    pUsbData->pRegs->INTRRXE |= (1<<BITP_USB_INTRRXE_EP6);

 

}

 

void main(void)

 

{

 

    ADI_USB_INIT_DATA InitData = {

 

            0,            //Device number

 

            ADI_USB_MODE_DEVICE,    //Driver mode

 

            {0,0,0,0,0,0,0,0},

 

    };

 

    Init_Descriptor(&DeviceDescriptor,

 

            &ConfigDescriptor,

 

            &ConfigFullDescriptor,

 

            &StringDescriptor[0],

 

            &StringDescriptor[1],

 

            &StringDescriptor[2],

 

            &EP0Descriptor

 

            );

 

    //Initialize User Request Blocks

 

    Init_Urb(UsbUrbEPData);

 

    result = adi_musbmhdrc_Init(&hUsbDevice, &InitData);

 

    CheckResult("adi_musbmhdrc_Init",result);

 

    pUsbData = hUsbDevice;

 

    //register callback functions

 

    adi_musbmhdrc_RegisterEpZeroCallback(hUsbDevice, adi_usbdrvd_EpZeroCallback);

 

    adi_musbmhdrc_RegisterEpDataCallback(hUsbDevice, adi_usbdrvd_EpDataCallback);

 

    adi_musbmhdrc_RegisterBusEventCallback(hUsbDevice, adi_usbdrvd_BusEventCallback);

 

    result = adi_musbmhdrc_EP_Open (hUsbDevice, &EP0Descriptor, 0);

 

    CheckResult("adi_musbmhdrc_EP_Open",result);

 

    result = adi_musbmhdrc_Start((ADI_USB_HANDLE)pUsbData);

 

    CheckResult("adi_musbmhdrc_Start",result);

 

    while(1)

 

    {

 

        //Device in configured state, bulk transfer beginns.

 

        if (pUsbData->DevState == ADI_USB_DEV_STATE_CONFIGURED)

 

        {

 

            //execute only once

 

            if(epConfig == false)

 

            {

 

                epConfig = true;

 

                //Configure Endpoint for Bulk Transfer

 

                EPx_Config();

 

                //Flush the descriptors to save more memory. Necessary???

 

                /*

 

                FlushArea((uint8_t*)&DeviceDescriptor, (uint8_t*)&DeviceDescriptor + 18);

 

                FlushArea((uint8_t*)&ConfigDescriptor, (uint8_t*)&ConfigDescriptor + 9);

 

                FlushArea((uint8_t*)&ConfigFullDescriptor, (uint8_t*)&ConfigFullDescriptor + 46);

 

                FlushArea((uint8_t*)&StringDescriptor[0], (uint8_t*)&StringDescriptor[0] + 4);

 

                FlushArea((uint8_t*)&StringDescriptor[1], (uint8_t*)&StringDescriptor[1] + 42);

 

                FlushArea((uint8_t*)&StringDescriptor[2], (uint8_t*)&StringDescriptor[2] + 40);

 

                */

 

            }

 

            //DataCallback function executed. Now Prepare for the next transaction

 

            if(epBulk == true)

 

            {

 

                epBulk = false;

 

                UsbUrbEPData[4].EpDir = ADI_USB_EP_DIR_RX;

 

                UsbUrbEPData[4].EpAddr = 0x06;

 

                UsbUrbEPData[4].DevAddr = (uint8_t)pUsbData->pRegs->FADDR;

 

                UsbUrbEPData[4].pData = pRxOfflineBuffer;

 

                pUsbData->EpInfo[4].pEpCurURB = &UsbUrbEPData[4];

 

                pUsbData->pRegs->INTRRXE |= 0x40; //enable physical endpoint 6

 

            }

 

        }

 

    }

 

}

 

//Function for Debug.

 

void CheckResult(char *operation, uint32_t result){

 

    if (result != 0) {

 

        printf("%s Failed with error: %x\r\n", operation, result);

 

    }

 

}

 

 

In the following is the USB_TEST.h:

 

 

/* Add your custom header content here */

 

#include <defBF52x_base.h>

 

#include <cdefBF52x_base.h>

 

#include "adi_usbd_musbmhdrc.c"

 

/**

 

*  Device, Configuration, Interface Descriptor

 

*/

 

/* Device Descriptor -Size 18 Bytes - 14 fields */

 

typedef struct UsbDeviceDescriptor

 

{

 

    unsigned char   bLength;          /* Descriptor size in bytes */

 

    unsigned char   bDescriptorType;  /* Descriptor type DEVICE 01h  */

 

    unsigned short int  wBcdUSB;          /* USB Specification Release Number (BCD) */

 

    unsigned char   bDeviceClass;     /* Class code */

 

    unsigned char   bDeviceSubClass;  /* Subclass code */

 

    unsigned char   bDeviceProtocol;  /* Protocol code */

 

    unsigned char   bMaxPacketSize0;  /* Maximum packet size for Endpoint 0 */

 

    unsigned short int  wIdVendor;        /* Vendor ID */

 

    unsigned short int  wIdProduct;       /* Product ID */

 

    unsigned short int  wBcdDevice;       /* Device release number */

 

    unsigned char   bIManufacturer;   /* Index of string descriptor for manufacturer */

 

    unsigned char   bIProduct;        /* Index of string descriptor for product */

 

    unsigned char   bISerialNumber;   /* Index of string descriptor contains serial no# */

 

    unsigned char   bNumConfigurations; /* Number of possible configurations */

 

}DEVICE_DESCRIPTOR, *PDEVICE_DESCRIPTOR;

 

/* Configuration Descriptor -Size 9 bytes - 8 fields */

 

typedef struct ConfigurationDescriptor

 

{

 

    unsigned char  bLength;          /* Descriptor size in bytes */

 

    unsigned char  bDescriptorType;  /* Descriptor type CONFIGURATION 02h */

 

    unsigned short int wTotalLength;     /* Total Length of configuration descriptor and all of its subordinate descriptors */

 

    unsigned char  bNumInterfaces;   /* Number of interfaces in the configuration */

 

    unsigned char  bConfigurationValue; /* Identifier for Set/Get configuration requests */

 

    unsigned char  bIConfiguration;  /* Index of string descriptor for the configuration */

 

    unsigned char  bAttributes;      /* Self/bus power and remote wakeup settings */

 

    unsigned char  bMaxPower;        /* Bus power required,expressed as max-miili-amps/2 */

 

}CONFIGURATION_DESCRIPTOR,*PCONFIGURATION_DESCRIPTOR;

 

/* Configuration Descriptor -Total Size 46 bytes - 8 fields */

 

typedef struct ConfigurationFullDescriptor

 

{

 

    //Configuration Descriptor 9 bytes

 

    unsigned char  bConfigLength;          /* Descriptor size in bytes */

 

    unsigned char  bConfigDescriptorType;  /* Descriptor type CONFIGURATION 02h */

 

    unsigned short int wConfigTotalLength;     /* Total Length of configuration descriptor and all of its subordinate descriptors */

 

    unsigned char  bConfigNumInterfaces;   /* Number of interfaces in the configuration */

 

    unsigned char  bConfigConfigurationValue; /* Identifier for Set/Get configuration requests */

 

    unsigned char  bConfigIConfiguration;  /* Index of string descriptor for the configuration */

 

    unsigned char  bConfigAttributes;      /* Self/bus power and remote wakeup settings */

 

    unsigned char  bConfigMaxPower;        /* Bus power required,expressed as max-miili-amps/2 */

 

    //Interface Descriptor 9 bytes

 

    unsigned char  bIFLength;            /* Descriptor size in bytes */

 

    unsigned char  bIFDescriptorType;    /* Descriptor type INTERFACE 04h */

 

    unsigned char  bIFInterfaceNumber;   /* Number identifying this interface */

 

    unsigned char  bIFAlternateSetting;  /* Value used to select Alternate setting */

 

    unsigned char  bIFNumEndpoints;      /* Identifier for Set/Get configuration requests */

 

    unsigned char  bIFInterfaceClass;    /* Class code */

 

    unsigned char  bIFInterfaceSubClass; /* Subclass code */

 

    unsigned char  bIFInterfaceProtocol; /* Protocol code */

 

    unsigned char  bIFIInterface;        /* Index of string descriptor for the interface */

 

    //Endpoint Descriptor 7 bytes

 

    unsigned char    bDesp1Length;

 

    unsigned char    bDesp1DescriptorType;

 

    unsigned char    bDesp1EndpointAddress;

 

    unsigned char    bDesp1Attributes;

 

    unsigned short int wDesp1MaxPacketSize;

 

    unsigned char    bDesp1Interval;

 

    //Endpoint Descriptor 7 bytes

 

    unsigned char  bDesp2Length;

 

    unsigned char  bDesp2DescriptorType;

 

    unsigned char  bDesp2EndpointAddress;

 

    unsigned char  bDesp2Attributes;

 

    unsigned short int wDesp2MaxPacketSize;

 

    unsigned char  bDesp2Interval;

 

    //Endpoint Descriptor 7 bytes

 

    unsigned char  bDesp3Length;

 

    unsigned char  bDesp3DescriptorType;

 

    unsigned char  bDesp3EndpointAddress;

 

    unsigned char  bDesp3Attributes;

 

    unsigned short int wDesp3MaxPacketSize;

 

    unsigned char  bDesp3Interval;

 

    //Endpoint Descriptor 7 bytes

 

    unsigned char  bDesp4Length;

 

    unsigned char  bDesp4DescriptorType;

 

    unsigned char  bDesp4EndpointAddress;

 

    unsigned char  bDesp4Attributes;

 

    unsigned short int wDesp4MaxPacketSize;

 

    unsigned char  bDesp4Interval;

 

}CONFIGURATION_FULL_DESCRIPTOR,*PCONFIGURATION_FULL_DESCRIPTOR;

 

/* Interface Descriptor -Size 9 bytes - 9 fields */

 

typedef struct InterfaceDescriptor

 

{

 

    unsigned char  bLength;            /* Descriptor size in bytes */

 

    unsigned char  bDescriptorType;    /* Descriptor type INTERFACE 04h */

 

    unsigned char  bInterfaceNumber;   /* Number identifying this interface */

 

    unsigned char  bAlternateSetting;  /* Value used to select Alternate setting */

 

    unsigned char  bNumEndpoints;      /* Identifier for Set/Get configuration requests */

 

    unsigned char  bInterfaceClass;    /* Class code */

 

    unsigned char  bInterfaceSubClass; /* Subclass code */

 

    unsigned char  bInterfaceProtocol; /* Protocol code */

 

    unsigned char  bIInterface;        /* Index of string descriptor for the interface */

 

}INTERFACE_DESCRIPTOR,*PINTERFACE_DESCRIPTOR;

 

/* String Descriptor */

 

typedef struct StringDescriptor

 

{

 

    unsigned char bLength;           /* Descriptor size in bytes */

 

    unsigned char bDescriptorType;   /* Descriptor type STRING 03h */

 

    /* The last field is bString which is an unknown length. For string 0 it's

 

     an array of one or more language ID codes, for other strings this is a

 

     Unicode string */

 

    unsigned char bString[40];

 

}STRING_DESCRIPTOR,*PSTRING_DESCRIPTOR;

 

#pragma pack()

 

//Control Transfer->SETUP data->bRequest type

 

enum RequestCmd

 

{

 

    GET_STATUS,

 

    CLEAR_FEATURE,

 

    reserved1,

 

    SET_FEATURE,

 

    reserved2,

 

    SET_ADDRESS,

 

    GET_DESCRIPTOR,

 

    SET_DESCRIPTOR,

 

    GET_CONFIGURATION,

 

    SET_CONFIGURATION,

 

    GET_INTERFACE,

 

    SET_INTERFACE,

 

    SYNCH_FRAME

 

};

 

//Control Transfer->SETUP data->wValue(Higher Byte: Descriptor Type)

 

enum DescriptorType

 

{

 

    DEVICE = 1,

 

    CONFIGURATION,

 

    STRING,

 

    INTERFACE,

 

    ENDPOINT,

 

    DEVICE_QUALIFIER,

 

    OTHER_SPEED_CONFIGURATION,

 

    INTERFACE_POWER,

 

    ON_THE_GO

 

};

 

//function prototype

 

void adi_usbdrvd_EpZeroCallback(void *pCBParam, uint32_t Event, void *pArg);

 

void adi_usbdrvd_EpDataCallback(void *pCBParam, uint32_t Event, void *pArg);

 

void adi_usbdrvd_BusEventCallback(void *pCBParam, uint32_t Event, void *pArg);

 

//void adi_musbmhdrc_SpdSet (ADI_USB_HANDLE const hDevice, ADI_USB_SPEED DevSpd);

 

void CheckResult(char *operation, uint32_t result); //for DEBUG

 

void Init_Descriptor(PDEVICE_DESCRIPTOR pDeviceDescriptor,

 

                     PCONFIGURATION_DESCRIPTOR pConfigDescriptor,

 

                     PCONFIGURATION_FULL_DESCRIPTOR pConfigFullDescriptor,

 

                     //PINTERFACE_DESCRIPTOR pInterfaceDescriptor,

 

                     PSTRING_DESCRIPTOR pStringDescriptorLang,

 

                     PSTRING_DESCRIPTOR pStringDescriptor0,

 

                     PSTRING_DESCRIPTOR pStringDescriptor1,

 

                     ADI_USB_EP_DESC* pEP0Descriptor

 

                     );

 

void Init_Urb(ADI_USB_URB* UsbUrb);

 

//void Init_EPDescriptor(ADI_USB_EP_DESC EP0Descriptor);

 

void EP0CmdHandler(USB_SETUP_REQ UsbSetupPacket);

 

void Init_EPx(ADI_USB_EP_DESC* EPDescriptor);

 

void EPx_Config(void);

 

 

/************************************************************************************************************************/

 

In the source file, user is responsible for handling the data within EP0 and EPDATA callback functions.

 

Although this example works, there're some points I'm still puzzled:

 

1. When is the DMA Interrupt triggered? DMA is triggered after RxInterrupt. Why? I believe the enable and disable DMA is done within some macros.

 

2. During the trial, I've met this problem, it's a runtime error, as soon as I plug in the USB cable:

 

A non-recoverable error or exception has occurred.

 

  Description:   An illegal data memory access has occurred.

 

  General Type:  RunTimeError

 

  Specific Type: DCPLBProtectionViolation

 

  Error PC:      0xffa057ca

 

If I change the system.svc file -> Cache Configuration -> Data Cache from "Disable cache and enable memory protection" to "Enable Cache on Bank A", then this error disappears.

 

If anyone knows, please give the explanation. This example is not good enough, but at least it works. I hope it could do some help.

Outcomes