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 Host TM4C123G

I've been doing a lot of reading about USB and the Tiva Ware USB library. After reading through all the documentation and the examples I've come up with the following test program for handling mouse input on the TM4C123G LaunchPad, but it does not seem to be working. There are no compile errors and no faults thrown when run, but the mouse callback never gets called.

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "driverlib/rom.h"
#include "usblib/usblib.h"
#include "usblib/host/usbhost.h"
#include "usblib/host/usbhhid.h"
#include "usblib/host/usbhhidmouse.h"


//*****************************************************************************
//
// The the host controller’s memory pool in bytes.
//
//*****************************************************************************
#define HCD_MEMORY_SIZE 128
uint8_t g_pui8HCDPool[HCD_MEMORY_SIZE];

//*****************************************************************************
//
// The the mouse memory pool in bytes.
//
//*****************************************************************************
#define M_MEMORY_SIZE 128
uint8_t g_pui8Buffer[M_MEMORY_SIZE];

//*****************************************************************************
//
// The global that holds all of the host drivers in use in the application.
// In this case, only the Keyboard class is loaded.
//
//*****************************************************************************
static tUSBHostClassDriver const * const g_ppsHostClassDrivers[] =
{
	&g_sUSBHIDClassDriver//, &g_sUSBHostMSCClassDriver
};
static const uint32_t g_ui32NumHostClassDrivers =
		sizeof(g_ppsHostClassDrivers) / sizeof(tUSBHostClassDriver *);

//*****************************************************************************
//
// Mouse control
//
//*****************************************************************************
#define MOUSE_NOT_CONNECTED 0
#define MOUSE_INIT 1
#define MOUSE_CONNECTED 2
uint32_t iMouseState = MOUSE_NOT_CONNECTED;

//*****************************************************************************
//
// Mouse Callback
//
//*****************************************************************************
uint32_t MouseCallback(tUSBHMouse *psMsInstance, uint32_t ui32Event, uint32_t ui32MsgParam, void *pvMsgData)
{
	switch(ui32Event)
	{
		//
		// New mouse detected.
		//
		case USB_EVENT_CONNECTED:
		{
			iMouseState = MOUSE_INIT;
			break;
		}

		//
		// Mouse has been unplugged.
		//
		case USB_EVENT_DISCONNECTED:
		{
			iMouseState = MOUSE_NOT_CONNECTED;
			break;
		}

		//
		// New Mouse events detected.
		//
		case USBH_EVENT_HID_MS_PRESS:
		{
			break;
		}
		case USBH_EVENT_HID_MS_REL:
		{
			break;
		}
		case USBH_EVENT_HID_MS_X:
		{
			break;
		}
		case USBH_EVENT_HID_MS_Y:
		{
			break;
		}
	}
	return(0);
}

//*****************************************************************************
//
// Application start
//
//*****************************************************************************
int main()
{
	//
	// Enable Clocking to the USB controller.
	//
	SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
	USBStackModeSet(0, eUSBModeForceHost, 0);

	//
	// Set the USB0EPEN and USB0PFLT pins to be controlled by the USB
	// controller.
	//
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	GPIOPinTypeUSBDigital(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);

	//
	// Register the host class drivers.
	//
	USBHCDRegisterDrivers(0, g_ppsHostClassDrivers,
	g_ui32NumHostClassDrivers);

	//
	// Open an instance of the mouse driver. The mouse does not need
	// to be present at this time, this just saves a place for it and allows
	// the applications to be notified when a mouse is present.
	//
	tUSBHMouse *g_psMouseInstance = USBHMouseOpen((tUSBHIDMouseCallback)MouseCallback, g_pui8Buffer, M_MEMORY_SIZE);

	//
	// Initialize the host controller.
	//
	USBHCDInit(0, g_pui8HCDPool, HCD_MEMORY_SIZE);

	//
	// Main loop of application.
	//
	while(1)
	{
		switch(iMouseState)
		{
			//
			// This state is entered when they mouse is first detected.
			//
			case MOUSE_INIT:
			{
				//
				// Initialized the newly connected mouse.
				//
				USBHMouseInit(g_psMouseInstance);

				//
				// Proceed to the mouse connected state.
				//
				iMouseState = MOUSE_CONNECTED;
				break;
			}
			case MOUSE_CONNECTED:
			{
				break;
			}
			case MOUSE_NOT_CONNECTED:
				default:
			{
				break;
			}
		}

		//
		// Periodic call the main loop for the Host controller driver.
		//
		USBHCDMain();
	}
}

Here is my hardware setup:

Instead of putting in the 0 ohm resistors, like the documentation says to do for host operation, I routed the VBus through jumper wires. PB0 is connected to ground and PB1 is connected to VBus. 

What am I over looking?

  • Haven't used USB host, so I'm going to be much help, but I don't see where you are setting the system clock. USB needs a minimum 20MHz clock, but the Tiva defaults to a 16MHz clock. Pretty sure this is true if you are running device or host mode

    From a USB example

        //
        // Set the clocking to run from the PLL at 50MHz
        //
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                           SYSCTL_XTAL_16MHZ);

  • You need to enable the usb data pins

        //
        // Configure the required pins for USB operation.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_5 | GPIO_PIN_4);

  • Thanks for the help so far, but now I'm running into an unexpected interrupt from USB0. Stepping through the code, this appears to be occurring at USBHCDInit(), if I step slowly and USBHCDMain() if I step through fast.

    What is a good way to debug this once It's caught in an infinite loop from the startup_ccs IntDefaultHandler? 

    I've also caught a few additional bugs in the code, so here is the up to date version:

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/timer.h"
    #include "driverlib/uart.h"
    #include "driverlib/rom.h"
    #include "usblib/usblib.h"
    #include "usblib/host/usbhost.h"
    #include "usblib/host/usbhhid.h"
    #include "usblib/host/usbhhidmouse.h"
    
    
    //*****************************************************************************
    //
    // The the host controller’s memory pool in bytes.
    //
    //*****************************************************************************
    #define HCD_MEMORY_SIZE 128
    uint8_t g_pui8HCDPool[HCD_MEMORY_SIZE];
    
    //*****************************************************************************
    //
    // The the mouse memory pool in bytes.
    //
    //*****************************************************************************
    #define M_MEMORY_SIZE 128
    uint8_t g_pui8Buffer[M_MEMORY_SIZE];
    
    //*****************************************************************************
    //
    // The global that holds all of the host drivers in use in the application.
    // In this case, only the Keyboard class is loaded.
    //
    //*****************************************************************************
    static tUSBHostClassDriver const * const g_ppsHostClassDrivers[] =
    {
    	&g_sUSBHIDClassDriver//, &g_sUSBHostMSCClassDriver
    };
    static const uint32_t g_ui32NumHostClassDrivers =
    		sizeof(g_ppsHostClassDrivers) / sizeof(tUSBHostClassDriver *);
    
    //*****************************************************************************
    //
    // Mouse control
    //
    //*****************************************************************************
    #define MOUSE_NOT_CONNECTED 0
    #define MOUSE_INIT 1
    #define MOUSE_CONNECTED 2
    uint32_t iMouseState = MOUSE_NOT_CONNECTED;
    
    //*****************************************************************************
    //
    // Mouse Callback
    //
    //*****************************************************************************
    void MouseCallback(tUSBHMouse *psMsInstance, uint32_t ui32Event, uint32_t ui32MsgParam, void *pvMsgData)
    {
    	switch(ui32Event)
    	{
    		//
    		// New mouse detected.
    		//
    		case USB_EVENT_CONNECTED:
    		{
    			iMouseState = MOUSE_INIT;
    			break;
    		}
    
    		//
    		// Mouse has been unplugged.
    		//
    		case USB_EVENT_DISCONNECTED:
    		{
    			iMouseState = MOUSE_NOT_CONNECTED;
    			break;
    		}
    
    		//
    		// New Mouse events detected.
    		//
    		case USBH_EVENT_HID_MS_PRESS:
    		{
    			break;
    		}
    		case USBH_EVENT_HID_MS_REL:
    		{
    			break;
    		}
    		case USBH_EVENT_HID_MS_X:
    		{
    			break;
    		}
    		case USBH_EVENT_HID_MS_Y:
    		{
    			break;
    		}
    	}
    }
    
    //*****************************************************************************
    //
    // Application start
    //
    //*****************************************************************************
    int main()
    {
    	//
    	// Set the clocking to run from the PLL at 50MHz
    	//
    	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    	SysCtlUSBPLLEnable();
    
    	//
    	// Enable Clocking to the USB controller.
    	//
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
    	USBStackModeSet(0, eUSBModeForceHost, 0);
    
    	// Configure the required pins for USB operation.
    	//
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);            // ID+VBUS
    	GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1); // ID+VBUS
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);            // DP+DN
    	GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5); // DP+DN
    
    	//
    	// Register the host class drivers.
    	//
    	USBHCDRegisterDrivers(0, g_ppsHostClassDrivers,	g_ui32NumHostClassDrivers);
    
    	//
    	// Open an instance of the mouse driver. The mouse does not need
    	// to be present at this time, this just saves a place for it and allows
    	// the applications to be notified when a mouse is present.
    	//
    	tUSBHMouse *g_psMouseInstance = USBHMouseOpen(MouseCallback, g_pui8Buffer, M_MEMORY_SIZE);
    
    	//
    	// Initialize the host controller.
    	//
    	USBHCDInit(0, g_pui8HCDPool, HCD_MEMORY_SIZE);
    
    	//
    	// Main loop of application.
    	//
    	while(1)
    	{
    		switch(iMouseState)
    		{
    			//
    			// This state is entered when they mouse is first detected.
    			//
    			case MOUSE_INIT:
    			{
    				//
    				// Initialized the newly connected mouse.
    				//
    				USBHMouseInit(g_psMouseInstance);
    
    				//
    				// Proceed to the mouse connected state.
    				//
    				iMouseState = MOUSE_CONNECTED;
    				break;
    			}
    			case MOUSE_CONNECTED:
    			{
    				break;
    			}
    			case MOUSE_NOT_CONNECTED:
    				default:
    			{
    				break;
    			}
    		}
    
    		//
    		// Periodic call the main loop for the Host controller driver.
    		//
    		USBHCDMain();
    	}
    }
    

    Any suggestions are appreciated.

  • Did you make any progress with this?

    If you are in IntDefaultHandler that means you haven't setup your interrupt handler in startup_ccs.c (assuming you are using TI's CCS environment). Did you start this from an existing example or was it a new project?

    I'll post details tomorrow if you are still having problems.

  • No, I have not had any luck. This project was started from the blinking LED example program with startup_ccs.c included. Although I do not understand what is causing the interrupt in the first place. After doing some debugging, I know it's coming from USB0 but I do not know why or how to appropriately handle it.

    Thank you for your help.

  • The USB peripheral generates the interrupt. You have to add the USB Library's interrupt to the vector table. The vector table is defined in startup_ccs.c

    Find the line

        IntDefaultHandler,                      // USB0

    and change it to

        USB0HostIntHandler,  	                // USB0

  • Thank you for the help. The code works fine now. I just need to fine tune my hardware setup.

  • Hello, I'm trying to reproduce your success, but with little result by now.

    I also routed usb port with jumper wires, but my setup is slightly different

    better resulution of image here: http://postimg.org/image/m9nw8f0yn/

    Wires by colors:

    • red: PB1 <-> VBUS
    • green: PB0 <-> GND
    • purple: VBUS
    • black: GND
    • white: D+
    • green: D-

    Code copied from yours, exceptt startup.c. I use sourcery codebench lite on linux and so startup file is slightly different, but interrupt handler set as suggested in this conversation.

    Still my mouse driver callback function got no calls whlle debug ran.

    Also something strange happened when i pulled out my mouse from usb host port. Debugger suddenly started to alert me about losing control over MCU and curciut became quite hot. I disconnected power as soon as i felt chip temperature. I thought that chip was dead, but after disconnecting all wires it seems as it works fine (except usb part, which had problems from begining)

    Where can I be wrong? And what the point in connecting VBUS and GND to pins PB0 and PB1? GND signal on ID line helps MCU to understand that its working in host mode i think. Will connecting VBUS to one of MCU pins allow chip to control it? But how? If MCU tries to pull it to GND it will cause short circuit in chip and cause mentioned overheat, so its not possible. 

    Thanks in advance

  • Vasilly Prokopiev said:
    red: PB1 <-> VBUS

     Hi remove this from supply rail, it is not protected. It is 5 volt tolerant to detect external bus power but your case never sense 5Volt rail, +VBUS is different from +VUSBBUS coming from user socket.

     On manual also recommend never move the slide of power selector Device-Debugger to avoid spikes and latchup.

  • Ty for answer. Could you be a little more particular? I thought that signal on pin VBUS on booster pack pins are the same as VBUS on supply rail pin. And which pin is 5V tolerant? PB1?

    I read the documents and there is said, that i can drop additional pins except D+ D- and gnd when i'm not using OTG mode, but when i removed theese wires - nothing happened

  • Hi Vasilly,

    Did you find an answer?

  • Hello Andrey, No, its a hobby project and I'm currently out of free time, so I did not dig any deeper in this.

  • Thanks Stephen and stepman for the nice and useful example.  It is working for me too on KEIL.

    To have a "cleaner" solution I have used the following USB adapter: http://www.dx.com/p/micro-5pin-to-usb-female-otg-data-cable-black-129671#.U9Y3HKPmTcs

    and shorted the R25 and R29 pads on the board (0 ohm resistors). To power supply the device I have short-circuited the middle and outer contacts of the switch as described here: http://forum.stellarisiti.com/topic/1714-usb-power-for-host-operation/

    In this way, when the switch is on "DEBUG" position the USB device (a mouse in this case) is powered from the TIVA C board.

    when the switch is on "DEVICE" position the TIVA C board (and the mouse, of course) is off.

     

  • Dear all,

    My query is if I need to connect pendrive with tiva C123G launchpad kit and use the tiva C as a host and dump my data in pendrive what should I do..? where to start?

    should I go for MSD device class or CDC class.?

    Please suggest.