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.

TCA6416 GPIO Driver Calls

Other Parts Discussed in Thread: TCA6416, AM3517

Hello,

I have a question regarding the calling of the GPIO drivers from user space. The normal GPIO driver would be reached over GIO1 and the TCA6416 ones over GIO2-GIO4.
Is it only possible to get connected to the TCA6416 functions directly over DeviceIoControl functions or also over GPIOOpen etc.? And am I right that the GPIO numbers from the TCA6416 would be added to the end of the "on-board" GPIOs? In the case of the AM35x they should begin at 193?

When I use the GPIO test program from the AM3517 BSP 1.2.0 (which uses GPIOOpen, GPIO...), it gets to the IOCTL_DDK_GET_DRIVER_IFC (tca6416_gpio.cpp) control with the following error message:

ERROR: GIO_IOControl: IOCTL_DDK_GET_DRIVER_IFC can be called only from device process (caller process id 0x00400002)

And IOCTL_GPIO_SETBIT or IOCTL_GPIO_CLRBIT are never called (tca6416_gpio.cpp).

Thanks ahead!

  • Hi Greg,

    Your understanding of the GPIO framework seems right, however please note that GPIO pin numbers for the expanders don't start at 193 but rather at 256 such as defined under bsp_def.h:

    //-----------------------------------------------------------------------------
    // GPIO id start for GPIO expander 1
    #define GPIO_EXPANDER_1_PINID_START  (256)
    //-----------------------------------------------------------------------------
    // GPIO id start for GPIO expander 2
    #define GPIO_EXPANDER_2_PINID_START  (288)
    //-----------------------------------------------------------------------------
    // GPIO id start for GPIO expander 3
    #define GPIO_EXPANDER_3_PINID_START  (320)

    This would explain why you fail to clear/set bits on the GPIO you are trying to reach. Also note that the error message you see is actually expected as you call the GPIO framework form userspace, but there is a fallback for this specific case. The GPIO SDK fails to retrieve the direct call functions table but should still have GPIOOpen to return TRUE (please check if this is your case). After that, any call to GPIOSetBit (or else) will test if the function table has been retrieved (which is not our case here) and use IOCTLs on the GIO drivers if it is not the case (see in gpio_dispatch.c):

    VOID GPIOSetBit(HANDLE hContext, DWORD id)
    {
        GpioDevice_t *pDevice = (GpioDevice_t*)hContext;
        int grp;
        if (GetGroupByID(pDevice,id,&grp))
        {
            id -= pDevice->rgRanges[grp];

            if (pDevice->rgGpioTbls[grp])
                pDevice->rgGpioTbls[grp]->pfnSetBit(pDevice->rgGpioTbls[grp]->context, id);
            else
            {
                DeviceIoControl(pDevice->rgHandles[grp],IOCTL_GPIO_SETBIT,&id,sizeof(id),NULL,0,NULL,NULL);
            }
        }
    }

    This mechanism allows for using the same GPIO sdk library from anywhere in the BSP: OAL, drivers, and user sapce. Depending on the code that is making the call, overhead may be reduced by using direct call to kernel functions instead of going through IoControls.

     

     

     

     

     

     

  • Thank you very much for your detailed and precise answer! I have no problems with the standard calls - like GPIOSetBit, GPIOGetBit and so on.

    But I have another question regarding the interrupt implementation for the TCA6416 GPIOs. The driver implements them through Tca6416GpioInterruptInitialize and other functions. But they aren't supported from the Tca6416GpioIoControl function which should be called over DeviceIoControl from GPIOInterruptInitialize. I've added the DeviceIoControl way to gpio_dispatch.c for GPIOInterruptInitialize and GPIOInterruptDone and also to tca6416_gpio.cpp for Tca6416GpioIoControl.

    I debugged it and it goes through everything and looks correct. But I didn't get an event in WaitForSingleObject in the user space when I toggle the pin. Did I miss something - isn't it possible to do it that way? (The GPIO interrupt pin is configured correctly through the tca6416_gpio.reg)

        GPIOSetMode(hGpio, dwId, GPIO_DIR_INPUT | GPIO_INT_LOW);
        if (!GPIOInterruptInitialize(hGpio, dwId, &dwSysInt, hIntEvent))
            GOTO_ERROR(-1, "GPIOInterruptInitialize failed");
        GPIOInterruptDone(hGpio, dwId, dwSysInt);

        for (;;)
        {
            if (WaitForSingleObject(hIntEvent, INFINITE) == WAIT_OBJECT_0)
            ...

        }

  • There is a problem to call the user space event handle directly in the interrupt routine thread (IST). I've added a CeDriverDuplicateCallerHandle call to Tca6416GpioInterruptInitialize for the event handle and now it did its work.

    pDevice->hPinEvent[bank][pin] = CeDriverDuplicateCallerHandle(hEvent, 0, FALSE, DUPLICATE_SAME_ACCESS);

  • Hi there,

    I jumped onto this thread and wanted to point you to my problem:

    http://e2e.ti.com/support/embedded/wince/f/353/t/177351.aspx

    I'm having some trivial issues accessing the gpio_dispatcher interface from either native or managed application.

    Hope you can help..

    Regards
    Palsson