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.

USB bulk device

Other Parts Discussed in Thread: CONTROLSUITE

Hello,

I'd like to try out the usb_dev_bulk example project on my F28M35H52C1 control card. I take this project from the 3.2.4 controlSuite release, F28m35x/v110/F28M35x_examples_Master/usb_dev_bulk. After I built the project I programmed it to the device, but unfortunately it doesn't seem to work properly. I've noticed that some subtle things are missing from the source code.
For instance UART0 is nowhere enabled with SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); Therefore I became unsure where is the bug in my experiment.
Has somebody ever tried this example project?

Thanks in advance,
Tamas

  • Hi Markus,

    If you check the "usb_dev_bulk.c" file, you find these line:

    // Enable the UART.
        // Set GPIO E4 and E5 as UART.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPinConfigure(GPIO_PE4_U0RX);
        GPIOPinConfigure(GPIO_PE5_U0TX);
        UARTStdioInit(0);
        UARTprintf("\033[2JBulk device application\n");

    I've herewith attached the same file if in case yours differs.

    //###########################################################################
    // FILE:   usb_dev_bulk.c
    // TITLE:  Main routines for the generic bulk device example.
    //###########################################################################
    // $TI Release: F28M35x Support Library v110 $
    // $Release Date: December 12, 2011 $
    //###########################################################################
    
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_sysctl.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "usblib/usblib.h"
    #include "usblib/device/usbdevice.h"
    #include "usblib/device/usbdbulk.h"
    #include "utils/uartstdio.h"
    #include "usb_bulk_structs.h"
    
    //*****************************************************************************
    //! \addtogroup master_example_list
    //! <h1>USB Generic Bulk Device (usb_dev_bulk)</h1>
    //!
    //! This example provides a generic USB device offering simple bulk data
    //! transfer to and from the host.  The device uses a vendor-specific class ID
    //! and supports a single bulk IN endpoint and a single bulk OUT endpoint.
    //! Data received from the host is assumed to be ASCII text and it is
    //! echoed back with the case of all alphabetic characters swapped.
    //!
    //! UART0, connected to the FTDI virtual COM port and running at 115,200,
    //! 8-N-1, is used to display messages from this application.
    //!
    //! A Windows INF file for the device is provided in ControlSUITE.  This
    //! INF contains information required to install the WinUSB subsystem on
    //! WindowsXP and Vista PCs.  WinUSB is a Windows subsystem allowing user mode
    //! applications to access the USB device without the need for a
    //! vendor-specific kernel mode driver.
    //!
    //! A sample Windows command-line application, usb_bulk_example, illustrating
    //! how to connect to and communicate with the bulk device is also provided.
    //! Project files are included to allow the examples to be built using Microsoft
    //! VisualStudio.  Source code for this application can be found in directory
    //! MWare/tools/usb_bulk_example.
    //*****************************************************************************
    
    //*****************************************************************************
    // The system tick rate expressed both as ticks per second and a millisecond
    // period.
    //*****************************************************************************
    #define SYSTICKS_PER_SECOND     100
    #define SYSTICK_PERIOD_MS       (1000 / SYSTICKS_PER_SECOND)
    
    //*****************************************************************************
    // The global system tick counter.
    //*****************************************************************************
    volatile unsigned long g_ulSysTickCount = 0;
    
    //*****************************************************************************
    // Variables tracking transmit and receive counts.
    //*****************************************************************************
    volatile unsigned long g_ulTxCount = 0;
    volatile unsigned long g_ulRxCount = 0;
    
    //*****************************************************************************
    // Global flag indicating that a USB configuration has been set.
    //*****************************************************************************
    static volatile tBoolean g_bUSBConfigured = false;
    
    //*****************************************************************************
    // The error routine that is called if the driver library encounters an error.
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    
    #endif
    
    //*****************************************************************************
    // Interrupt handler for the system tick counter.
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
        // Update our system tick counter.
        g_ulSysTickCount++;
    }
    
    //*****************************************************************************
    // Receive new data and echo it back to the host.
    // \param psDevice points to the instance data for the device whose data is to
    // be processed.
    // \param pcData points to the newly received data in the USB receive buffer.
    // \param ulNumBytes is the number of bytes of data available to be processed.
    // This function is called whenever there is data available from the host.  The
    // data is read byte-by-byte, the case of any alphabetical characters is
    // swapped, and then it is written back out to be transmitted back to the host.
    // \return Returns the number of bytes of data processed.
    //*****************************************************************************
    static unsigned long
    EchoNewDataToHost(tUSBDBulkDevice *psDevice, unsigned char *pcData,
                      unsigned long ulNumBytes)
    {
        unsigned long ulLoop, ulSpace, ulCount;
        unsigned long ulReadIndex;
        unsigned long ulWriteIndex;
        tUSBRingBufObject sTxRing;
    
        // Get the current buffer information to allow us to write directly to the
        // transmit buffer (there is already have enough information from the
        // parameters to access the receive buffer directly).
        USBBufferInfoGet(&g_sTxBuffer, &sTxRing);
    
        // How much space is there in the transmit buffer?
        ulSpace = USBBufferSpaceAvailable(&g_sTxBuffer);
    
        // How many characters can be processed this time round?
        ulLoop = (ulSpace < ulNumBytes) ? ulSpace : ulNumBytes;
        ulCount = ulLoop;
    
        // Update our receive counter.
        g_ulRxCount += ulNumBytes;
    
        // Set up to process the characters by directly accessing the USB buffers.
        ulReadIndex = (unsigned long)(pcData - g_pucUSBRxBuffer);
        ulWriteIndex = sTxRing.ulWriteIndex;
    
        // Copy from the receive buffer to the transmit buffer converting character
        // case on the way.
        while(ulLoop--)
        {
            // Is this a lower case character?
            if((g_pucUSBRxBuffer[ulReadIndex] >= 'a') &&
               (g_pucUSBRxBuffer[ulReadIndex] <= 'z'))
            {
                // Convert to upper case and write to the transmit buffer.
                g_pucUSBTxBuffer[ulWriteIndex] =
                    (g_pucUSBRxBuffer[ulReadIndex] - 'a') + 'A';
            }
            else
            {
                // Is this an upper case character?
                if((g_pucUSBRxBuffer[ulReadIndex] >= 'A') &&
                   (g_pucUSBRxBuffer[ulReadIndex] <= 'Z'))
                {
                    // Convert to lower case and write to the transmit buffer.
                    g_pucUSBTxBuffer[ulWriteIndex] =
                        (g_pucUSBRxBuffer[ulReadIndex] - 'Z') + 'z';
                }
                else
                {
                    // Copy the received character to the transmit buffer.
                    g_pucUSBTxBuffer[ulWriteIndex] = g_pucUSBRxBuffer[ulReadIndex];
                }
            }
    
            // Move to the next character taking care to adjust the pointer for
            // the buffer wrap if necessary.
            ulWriteIndex++;
            ulWriteIndex = (ulWriteIndex == BULK_BUFFER_SIZE) ? 0 : ulWriteIndex;
            ulReadIndex++;
            ulReadIndex = (ulReadIndex == BULK_BUFFER_SIZE) ? 0 : ulReadIndex;
        }
    
        // The data has been processed in place so now send the processed data back
        // to the host.
        USBBufferDataWritten(&g_sTxBuffer, ulCount);
    
        // Return the number of bytes processed to allow the bulk device driver to
        // update its read pointer appropriately.
        return(ulCount);
    }
    
    //*****************************************************************************
    // Handles bulk driver notifications related to the transmit channel (data to
    // the USB host).
    // \param pvCBData is the client-supplied callback pointer for this channel.
    // \param ulEvent identifies the event that has been sent.
    // \param ulMsgValue is an event-specific value.
    // \param pvMsgData is an event-specific pointer.
    // This function is called by the bulk driver to notify us of any events
    // related to operation of the transmit data channel (the IN channel carrying
    // data to the USB host).
    // \return The return value is event-specific.
    //*****************************************************************************
    unsigned long
    TxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulMsgValue,
              void *pvMsgData)
    {
        // No action is required in response to any transmit event in this example.
        // All that is done is to update the transmit counter.
        if(ulEvent == USB_EVENT_TX_COMPLETE)
        {
            g_ulTxCount += ulMsgValue;
        }
    
        return(0);
    }
    
    //*****************************************************************************
    // Handles bulk driver notifications related to the receive channel (data from
    // the USB host).
    // \param pvCBData is the client-supplied callback pointer for this channel.
    // \param ulEvent identifies the event that has been sent.
    // \param ulMsgValue is an event-specific value.
    // \param pvMsgData is an event-specific pointer.
    // This function is called by the bulk driver to notify us of any events
    // related to operation of the receive data channel (the OUT channel carrying
    // data from the USB host).
    // \return The return value is event-specific.
    //*****************************************************************************
    unsigned long
    RxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulMsgValue,
              void *pvMsgData)
    {
        // Which event was sent?
        switch(ulEvent)
        {
        // The host has connected.
        case USB_EVENT_CONNECTED:
        {
            g_bUSBConfigured = true;
            UARTprintf("Host connected.\n");
    
            // Flush our buffers.
            USBBufferFlush(&g_sTxBuffer);
            USBBufferFlush(&g_sRxBuffer);
    
            break;
        }
    
        // The host has disconnected.
        case USB_EVENT_DISCONNECTED:
        {
            g_bUSBConfigured = false;
            UARTprintf("Host disconnected.\n");
            break;
        }
    
        // A new packet has been received.
        case USB_EVENT_RX_AVAILABLE:
        {
            tUSBDBulkDevice *psDevice;
    
            // Get a pointer to our instance data from the callback data
            // parameter.
            psDevice = (tUSBDBulkDevice *)pvCBData;
    
            // Read the new packet and echo it back to the host.
            return(EchoNewDataToHost(psDevice, pvMsgData, ulMsgValue));
        }
    
        // Ignore SUSPEND and RESUME for now.
        case USB_EVENT_SUSPEND:
        case USB_EVENT_RESUME:
        {
            break;
        }
    
        // Ignore all other events and return 0.
        default:
        {
            break;
        }
        }
    
        return(0);
    }
    
    //*****************************************************************************
    // This is the main application entry function.
    //*****************************************************************************
    int
    main(void)
    {
        unsigned long ulTxCount;
        unsigned long ulRxCount;
    
        // Disable Protection
        HWREG(SYSCTL_MWRALLOW) =  0xA5A5A5A5;
    
        // Setup main clock tree for 75MHz - M3 and 150MHz - C28x
        SysCtlClockConfigSet(SYSCTL_SYSDIV_1 | SYSCTL_M3SSDIV_2 | SYSCTL_USE_PLL |
                             (SYSCTL_SPLLIMULT_M & 0x0F));
    
        // Setup USB clock tree for 60MHz
        // 20MHz * 12 / 4 = 60
        SysCtlUSBPLLConfigSet(
            (SYSCTL_UPLLIMULT_M & 12) | SYSCTL_UPLLCLKSRC_X1 | SYSCTL_UPLLEN);
    
        // Setup pins for USB operation
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
        GPIOPinTypeUSBAnalog(GPIO_PORTF_BASE, GPIO_PIN_6);
        GPIOPinTypeUSBAnalog(GPIO_PORTG_BASE, GPIO_PIN_2 | GPIO_PIN_5 | GPIO_PIN_6);
    
        // Enable the UART.
        // Set GPIO E4 and E5 as UART.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPinConfigure(GPIO_PE4_U0RX);
        GPIOPinConfigure(GPIO_PE5_U0TX);
        UARTStdioInit(0);
        UARTprintf("\033[2JBulk device application\n");
    
        // Not configured initially.
        g_bUSBConfigured = false;
    
        // Enable the system tick.
        SysTickPeriodSet(SysCtlClockGet(SYSTEM_CLOCK_SPEED) / SYSTICKS_PER_SECOND);
        SysTickIntEnable();
        SysTickEnable();
    
        // Register interrupt handlers in the RAM vector table
        IntRegister(INT_USB0, USB0DeviceIntHandler);
        IntRegister(FAULT_SYSTICK, SysTickIntHandler);
    
        // Initialize the transmit and receive buffers.
        USBBufferInit(&g_sTxBuffer);
        USBBufferInit(&g_sRxBuffer);
        
        // Set the USB stack mode to Device mode with VBUS monitoring.
        USBStackModeSet(0, USB_MODE_DEVICE, 0);
    
        // Pass our device information to the USB library and place the device
        // on the bus.
        USBDBulkInit(0, &g_sBulkDevice);
    
        // Wait for initial configuration to complete.
        UARTprintf("Waiting for host...\n");
    
        // Clear our local byte counters.
        ulRxCount = 0;
        ulTxCount = 0;
    
        // Main application loop.
        while(1)
        {
            // See if any data has been transferred.
            if((ulTxCount != g_ulTxCount) || (ulRxCount != g_ulRxCount))
            {
                // Take a snapshot of the latest transmit and receive counts.
                ulTxCount = g_ulTxCount;
                ulRxCount = g_ulRxCount;
    
                // Update the display of bytes transferred.
                UARTprintf("\rTx: %d  Rx: %d", ulTxCount, ulRxCount);
            }
        }
    }
    
    
    
    

    Regards,

    Gautam

  • Hi Gautam,

    Thank you for the fast reply. I have the same code, so I was wrong when I suspected that the missing SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); line is a bug. Sorry for this.

    However, the usb bulk device is still not working for me.From the UART I can read that the device is waiting for an USB host, but when I plug it into a Windows 7 PC no device is detected.

    Do you have any idea, what can be the problem?

    Thanks in advance,
    Tamas

  • Hi Tamas,

    Without looking at the code I won't be able to comment. Also the example codes do work without any modification. So check your connections and instructions properly.

    Regards,

    Gautam

  • Hi Tamas,

    If you run the example code without any modification on TI's control card, I pretty sure it can work.

    So what I suggest is:
    1. Do NOT modify TI's example code before you can detect the device on your computer.
    2. Make sure all your hardware can work well, including the control card, usb port on your computer, and usb cable.
    3. I don't know what you mean "not seem to work properly", if your computer can detect an unknown device, the only thing you need to do is installing the window driver for the device. This driver can be found from "F28m35x/v110/MWare/windows_drivers".