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.

TM4C123GH6PM: Slow Usb HID Keyboard Device

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: EK-TM4C123GXL, EK-TM4C1294XL

Hi All,

I used an example C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\dk-tm4c123g\usb_dev_keyboard and modified for TM4C123GH6PM. Which is working successfully. But there is too much delay between characters. Communication is too slow. How can I increase this?

  • Hello Metin,

    I presume the port is to work on the EK-TM4C123GXL LaunchPad? If all you did is port, could you provide the project so I can get a feel for the behavior?

    If not, I'd like to understand better about how the communication is slow. It could just be an issue with the port maybe, though I never tried the keyboard example with that LaunchPad. The example for the EK-TM4C1294XL Launchpad that comes with TivaWare performed well though, so I don't feel LaunchPad hardware should limit it (though the EK-TM4C123GXL board is a more simplistic build than the other boards mentioned).

    Also what keyboard are you using with it? Have you tested that keyboard with an unmodified HID USB example from TivaWare? (Not sure if you have a DK 123G board or TM4C1294 LaunchPad available)
  • Hello Ralph,

    Web designed custom PCB with TM4C123GH6PM and at the first, I tried on EK-TM4C123GXL with small hacks about VBUS. This is my code.

    /*
     * main.h
     *
     *  Created on: 2 Eki 2017
     *      Author: Metin KOC
     */
    
    #include "main.h"
    
    
    void IntUartDebug(void){
        uint32_t ui32Status;
        int32_t rcv_ch;
    
        ui32Status = MAP_UARTIntStatus(BASE_UART_DEBUG, true);
        MAP_UARTIntClear(BASE_UART_DEBUG, ui32Status);
    
        rcv_ch = MAP_UARTCharGetNonBlocking(BASE_UART_DEBUG);
    
        if(rcv_ch==-1)
            return;
    
    }
    
    
    uint32_t
    KeyboardHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgData,
                    void *pvMsgData)
    {
        switch (ui32Event)
        {
            //
            // The host has connected to us and configured the device.
            //
            case USB_EVENT_CONNECTED:
            {
                sendUartString(BASE_UART_DEBUG, "Connected\r\n");
                g_bConnected = true;
                g_bSuspended = false;
                break;
            }
    
            //
            // The host has disconnected from us.
            //
            case USB_EVENT_DISCONNECTED:
            {
                sendUartString(BASE_UART_DEBUG, "Disconnected\r\n");
                g_bConnected = false;
                break;
            }
    
            //
            // We receive this event every time the host acknowledges transmission
            // of a report. It is used here purely as a way of determining whether
            // the host is still talking to us or not.
            //
            case USB_EVENT_TX_COMPLETE:
            {
                //
                // Enter the idle state since we finished sending something.
                //
                g_eKeyboardState = STATE_IDLE;
                break;
            }
    
            //
            // This event indicates that the host has suspended the USB bus.
            //
            case USB_EVENT_SUSPEND:
            {
                sendUartString(BASE_UART_DEBUG, "Suspended\r\n");
                g_bSuspended = true;
                break;
            }
    
            //
            // This event signals that the host has resumed signalling on the bus.
            //
            case USB_EVENT_RESUME:
            {
                sendUartString(BASE_UART_DEBUG, "UnSuspended\r\n");
                g_bSuspended = false;
                break;
            }
    
            //
            // This event indicates that the host has sent us an Output or
            // Feature report and that the report is now in the buffer we provided
            // on the previous USBD_HID_EVENT_GET_REPORT_BUFFER callback.
            //
            case USBD_HID_KEYB_EVENT_SET_LEDS:
            {
    
                break;
            }
    
            //
            // We ignore all other events.
            //
            default:
            {
                break;
            }
        }
    
        return(0);
    }
    
    bool
    WaitForSendIdle(uint_fast32_t ui32TimeoutTicks)
    {
        uint32_t ui32Start;
        uint32_t ui32Now;
        uint32_t ui32Elapsed;
    
        ui32Start = g_ui32SysTickCount;
        ui32Elapsed = 0;
    
        while(ui32Elapsed < ui32TimeoutTicks)
        {
            //
            // Is the keyboard is idle, return immediately.
            //
            if(g_eKeyboardState == STATE_IDLE)
            {
                return(true);
            }
    
            //
            // Determine how much time has elapsed since we started waiting.  This
            // should be safe across a wrap of g_ui32SysTickCount.
            //
            ui32Now = g_ui32SysTickCount;
            ui32Elapsed = ((ui32Start < ui32Now) ? (ui32Now - ui32Start) :
                         (((uint32_t)0xFFFFFFFF - ui32Start) + ui32Now + 1));
        }
    
        //
        // If we get here, we timed out so return a bad return code to let the
        // caller know.
        //
        return(false);
    }
    
    void
    SendString(char *pcStr)
    {
        uint32_t ui32Char;
    
    
        while(*pcStr)
        {
            //
            // Get the next character from the string.
            //
            ui32Char = *pcStr++;
    
            //
            // Skip this character if it is a non-printable character.
            //
    
            if( ui32Char == '\n' ){
    
                g_eKeyboardState = STATE_SENDING;
                if(USBDHIDKeyboardKeyStateChange((void *)&g_sKeyboardDevice,
                                                 g_ppi8KeyUsageCodes[0x5F][0],
                                                 g_ppi8KeyUsageCodes[0x5F][1],
                                                 true) != KEYB_SUCCESS)
                {
                    return;
                }
    
                if(!WaitForSendIdle(MAX_SEND_DELAY))
                {
                    g_bConnected = 0;
                    return;
                }
    
                g_eKeyboardState = STATE_SENDING;
                if(USBDHIDKeyboardKeyStateChange((void *)&g_sKeyboardDevice,
                                                 0, g_ppi8KeyUsageCodes[0x5F][1],
                                                 false) != KEYB_SUCCESS)
                {
                    return;
                }
    
                if(!WaitForSendIdle(MAX_SEND_DELAY))
                {
                    g_bConnected = 0;
                    return;
                }
    
                return;
    
            }else if((ui32Char < ' ') || (ui32Char > '~'))
            {
                continue;
            }
    
            //
            // Convert the character into an index into the keyboard usage code
            // table.
            //
            ui32Char -= ' ';
    
            //
            // Send the key press message.
            //
            g_eKeyboardState = STATE_SENDING;
            if(USBDHIDKeyboardKeyStateChange((void *)&g_sKeyboardDevice,
                                             g_ppi8KeyUsageCodes[ui32Char][0],
                                             g_ppi8KeyUsageCodes[ui32Char][1],
                                             true) != KEYB_SUCCESS)
            {
                return;
            }
    
            //
            // Wait until the key press message has been sent.
            //
            if(!WaitForSendIdle(MAX_SEND_DELAY))
            {
                g_bConnected = 0;
                return;
            }
    
            //
            // Send the key release message.
            //
            g_eKeyboardState = STATE_SENDING;
            if(USBDHIDKeyboardKeyStateChange((void *)&g_sKeyboardDevice,
                                             0, g_ppi8KeyUsageCodes[ui32Char][1],
                                             false) != KEYB_SUCCESS)
            {
                return;
            }
    
            //
            // Wait until the key release message has been sent.
            //
            if(!WaitForSendIdle(MAX_SEND_DELAY))
            {
                g_bConnected = 0;
                return;
            }
        }
    }
    
    void initUsb(void){
    
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
        MAP_SysCtlUSBPLLEnable();
    
        MAP_SysCtlPeripheralEnable(PERIPH_GPIO_USB0ID);
        MAP_GPIOPinTypeUSBAnalog(BASE_GPIO_USB0ID, PIN_GPIO_USB0ID);
    
        MAP_SysCtlPeripheralEnable(PERIPH_GPIO_USB0VBUS);
        MAP_GPIOPinTypeUSBAnalog(BASE_GPIO_USB0VBUS, PIN_GPIO_USB0VBUS);
    
        MAP_SysCtlPeripheralEnable(PERIPH_GPIO_USB0DM);
        MAP_GPIOPinTypeUSBAnalog(BASE_GPIO_USB0DM, PIN_GPIO_USB0DM);
    
        MAP_SysCtlPeripheralEnable(PERIPH_GPIO_USB0DP);
        MAP_GPIOPinTypeUSBAnalog(BASE_GPIO_USB0DP, PIN_GPIO_USB0DP);
    
        HWREG(GPIO_PORTB_BASE + GPIO_O_PDR) |= GPIO_PIN_1;
    
        g_bConnected = false;
        g_bSuspended = false;
    
    
        USBStackModeSet(0, eUSBModeForceDevice, 0);
        USBDHIDKeyboardInit(0, &g_sKeyboardDevice);
    
    }
    
    void
    IntWatchdog(void)
    {
        if(clearWatchdog)
        {
            clearWatchdog = false;
            MAP_WatchdogIntClear(WATCHDOG0_BASE);
            MAP_WatchdogReloadSet(WATCHDOG0_BASE, MAP_SysCtlClockGet());
        }
    }
    
    void initHardware(void){
    
        ROM_FPULazyStackingEnable();
    
        MAP_SysCtlPeripheralEnable( PERIPH_GPIO_UART_DEBUG );
        MAP_GPIOPinConfigure( CONF_GPIO_UART_DEBUG_TX );
        MAP_GPIOPinConfigure( CONF_GPIO_UART_DEBUG_RX );
        MAP_GPIOPinTypeUART( BASE_GPIO_UART_DEBUG, PIN_GPIO_UART_DEBUG_TX | PIN_GPIO_UART_DEBUG_RX );
        MAP_SysCtlPeripheralEnable( PERIPH_UART_DEBUG );
        MAP_IntDisable( INT_UART_DEBUG );
        MAP_UARTDisable( BASE_UART_DEBUG );
        MAP_UARTClockSourceSet( BASE_UART_DEBUG, UART_CLOCK_PIOSC );
        MAP_UARTConfigSetExpClk( BASE_UART_DEBUG, 16000000, BAUDRATE_UART_DEBUG, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE );
        MAP_UARTIntEnable( BASE_UART_DEBUG, UART_INT_RX | UART_INT_RT );
        MAP_UARTEnable( BASE_UART_DEBUG);
        MAP_IntEnable( INT_UART_DEBUG );
    
        MAP_SysCtlPeripheralEnable( PERIPH_GPIO_LED_1 );
        MAP_GPIOPinTypeGPIOOutput( BASE_GPIO_LED_1, PIN_GPIO_LED_1 );
        MAP_GPIOPadConfigSet( BASE_GPIO_LED_1, PIN_GPIO_LED_1, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD );
        MAP_GPIOPinWrite( BASE_GPIO_LED_1, PIN_GPIO_LED_1, !PIN_GPIO_LED_1 );
    
        MAP_SysCtlPeripheralEnable( PERIPH_GPIO_LED_2 );
        MAP_GPIOPinTypeGPIOOutput( BASE_GPIO_LED_2, PIN_GPIO_LED_2 );
        MAP_GPIOPadConfigSet( BASE_GPIO_LED_2, PIN_GPIO_LED_2, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD );
        MAP_GPIOPinWrite( BASE_GPIO_LED_2, PIN_GPIO_LED_2, !PIN_GPIO_LED_2 );
    
        MAP_SysCtlPeripheralEnable(PERIPH_TIMER);
        MAP_TimerConfigure(BASE_TIMER, TIMER_CFG_PERIODIC);
        MAP_TimerLoadSet(BASE_TIMER, TIMER_A, MAP_SysCtlClockGet());
        MAP_TimerIntEnable(BASE_TIMER, INT_TIMER_TYPE);
        MAP_TimerEnable(BASE_TIMER, TIMER_A);
        MAP_IntEnable(INT_TIMER);
    
    
        initUsb();
    
        ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICKS_PER_SECOND);
        ROM_SysTickIntEnable();
        ROM_SysTickEnable();
    
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG0);
        MAP_WatchdogReloadSet(WATCHDOG0_BASE, MAP_SysCtlClockGet());
        MAP_WatchdogResetEnable(WATCHDOG0_BASE);
        MAP_WatchdogEnable(WATCHDOG0_BASE);
        MAP_IntEnable(INT_WATCHDOG);
    }
    
    void
    SysTickIntHandler(void)
    {
        g_ui32SysTickCount++;
    }
    
    
    
    
    int main(void){
    
        uint_fast32_t ui32LastTickCount;
        bool bLastSuspend;
    
        MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_OSC_MAIN  | SYSCTL_XTAL_16MHZ | SYSCTL_USE_PLL);
    
        initHardware();
    
        sendUartString(BASE_UART_DEBUG, "Start\r\n");
    
        while(1){
    
            clearWatchdog = true;
    
            while(!g_bConnected)
            {
                clearWatchdog = true;
            }
    
            g_eKeyboardState = STATE_IDLE;
    
            bLastSuspend = false;
    
            bufIxUart = 0;
    
            while(g_bConnected)
            {
                ui32LastTickCount = g_ui32SysTickCount;
    
                if(bLastSuspend != g_bSuspended)
                {
                    bLastSuspend = g_bSuspended;
    
                    if(bLastSuspend)
                    {
                        sendUartString(BASE_UART_DEBUG, "Bus suspended!\r\n");
                    }
                    else
                    {
                        sendUartString(BASE_UART_DEBUG, "Host Connected!\r\n");
                    }
                }
    
    
                if(g_bSuspended)
                {
                    USBDHIDKeyboardRemoteWakeupRequest(
                                                   (void *)&g_sKeyboardDevice);
                }else{
    
                    SendString("This is try");
                }
    
                while(g_ui32SysTickCount == ui32LastTickCount)
                {
                    clearWatchdog = true;
                }
            }
    
        }
    }
    

  • Hello Metin,

    I've seen your post, haven't had enough time to dig into the details yet, will try and get back to you tomorrow. Just letting you know you aren't forgotten.
  • I found a fix for a slow connection. This is about Endpoint interval. At the C:\ti\TivaWare_C_Series-2.1.4.178\usblib\device\usbdhidkeyb.c file I changed 2 parameters at the following bold and colored lines.

    static const uint8_t g_pui8HIDInEndpoint[HIDINENDPOINT_SIZE] =
    {
        //
        // Interrupt IN endpoint descriptor
        //
        7, // The size of the endpoint descriptor. 
        USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. 
        USB_EP_DESC_IN | USBEPToIndex(USB_EP_1),
        USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint.
        USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)),
        // The maximum packet size.
        1, // The polling interval for this endpoint.
    };

    static const uint8_t g_pui8HIDOutEndpoint[HIDOUTENDPOINT_SIZE] =
    {
       //
       // Interrupt OUT endpoint descriptor
       //
       7, // The size of the endpoint descriptor.
       USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint.
        USB_EP_DESC_OUT | USBEPToIndex(USB_EP_2),
        USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint.
        USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)),
        // The maximum packet size.
        1, // The polling interval for this endpoint.
    };

  • Hello Metin,

    Thanks for sharing your resolution for this with the community!
  • May it be noted (crack staff noted) that "No such Bold Lines" prove visible!      (thus the "sharing" - not so complete)    

    Might "color coding" - rather than "bold" - prove more effective?

    Of interest TO MANY - by what (even estimated) amount - did the USB HID speed's increase?      That - along w/the "better identification" of the "fix" - would yield,  "More effective SHARING!"

    Poster's effort is much appreciated - yet the "fix" is NOT easily detected - and the improvement's extent -  should be "better described!"

  • Hi cb1,

    The "Strong" note in the code is where the bold is... E2E Insert Code feature is lacking at times, or perhaps it's just too strong. It parses out everything related to coding, including bold text etc. added within the post editor, so it doesn't display the right coding but rather the syntax. I don't think color coding circumvents that, though I must confess to never trying as such.
  • Wow Ralph - you ARE tireless - and SO responsive!      Thank you - first I - then younger eyes - none could see!
    Note that I've requested the "extent of the speed-up!"     That's important too - don't you agree?

  • Hi cb1,

    Of course, I wasn't attempting dismiss your questions - just to jump in and comment on what I could on my end :)