none
Where can I get more information about the OMAP AM35xx GPIO calls? RRS feed

  • Question

  • Hello:

    I am wondering where I can get more detailed information on the workings of the following GPIO commands for the OMAP AM35X. Some are self explaining but the one's shown below I don't quite understand on the how's , why's and where's in their usage:

    I see them being used in the SDController.cpp program( \\WINCE600\PLATFORM\...BSP\SRC\DRIVERS\SDHC\IMPL\sdcontroller.cpp  ), but I don't understand the details of their functions in what they actually perform or why they are needed.

    GPIOInterruptMask     Mask/unmask the GPIO’s interrupt

    GPIOInterruptDisable     Disable the interrupt event when no longer needed

    GPIOInterruptDone     Function to call when done processing a GPIO interrupt

    GPIOInterruptWakeUp     Register the GPIO as a wake up source for the system

    It is correct that these GPIO commands are Kernel mode routines, and cannot be directly access from a user mode application?

    Naturally my next question will be , once I understand the working of these routines, is how to gain access to them from a user mode application?

    I have 8 GPIO lines I need to be able to setup as interrupts.

    I have experimented with the sdcontroller.cpp program and was able to modify that code to set up one of the GPIO lines I need to act as a interrupt and trigger when I toggle that particular GPIO line.

    So I understand to a certian extent how this is set up in the SDController.cpp program, but I need call/use these routines within my own user mode application.

    Can any point me to how that can be done? How does the sdcontroller.cpp program link to access these GPIO commands?

    Thanks.

    Monday, October 20, 2014 5:06 PM

All replies

  • By looking at the code from WINCE600\platform\<bsp>\SRC\CSP\INC\gpio.h, it seems that the inline functions declared can be used from a driver AND an application, by calling either the kernel mode function if the caller is a driver or the GPIO driver if called from an application.

    Include gpio.h in your application and call GPIOOpen(), followed by calls to other functions with the handle obtained from GPIOOpen().  Finish with GPIOClose().

    Monday, October 20, 2014 6:08 PM
  • Hi:

    Thanks..I understand with what your saying but I find no gpio.h files that contain the GPIO routines that you describe or I see in the sdcontroller.cpp file.

    Nor do I have a WINCE600\platform\<bsp>\SRC\CSP\INC folder.

    I do find them all declared in a header file called C:\WINCE600\PLATFORM\<bsp>\SRC\SOC\COMMON_TI_VI\COMMON_TI\INC\sdk_gpio.h but I have yet to figure out if that header file is associated with routines found in the SDController.cpp file.

    If I add test code into the SDController.cpp file, I can use all the GPIO routines in there on my own GPIO lines.

    I don't know how to link those GPIO calls in the SDController.cpp file into my own application.

    For example,in the SDController.cpp code there is the command:

        if (INVALID_HANDLE_VALUE == (m_hGPIO = GPIOOpen()))
        {
            RETAILMSG(1, (L"Can't open GPIO driver\r\n"));
            goto cleanUp;
        }

    Someplace, somewhere there should be code someplace called GPIOOpen(), and execute a command like:

    where GPIO_DEVICE_NAME is declared.

    and executes the command

                         hDevice = CreateFile(GPIO_DEVICE_NAME, 0, 0, NULL, 0, 0, NULL);

    that opens up a stream driver.

    And then have a series of functions, like

        DeviceIoControl(hGPIO,
                        IOCTL_GPIO_SETMODE,
                        &dwValue,
                        sizeof(dwValue),
                        NULL,
                        0,
                        NULL,
                        NULL );

    or other calls that execute some kind of DeviceIOControl() or KernelIOControl() routines that access the GPIO lines.

    The question I have is...How do I link in the GPIO calls that are used in the SDController.cpp file into my own application code? Where is it all located. I'm guess that perhaps it is already complied in a library someplace.

    Thanks;


    • Edited by Chulk Ches Monday, October 20, 2014 9:11 PM Added more info.
    Monday, October 20, 2014 8:57 PM
  • See the discussion here:

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

    Tuesday, October 21, 2014 11:34 AM
  • Thank Mario:

    Your above link got me a lot closer...but not their yet.

    By adding in the include paths to where all the header files that sdk_gpio.h required, and then including the coredll.dll and ceddek.dll in my project(which I hope point to the correct DLL), the program was able to recognize the GPIO functions.

    I though I had it when I was able to see the following commands actually work on a pair of GPIO lines, one of which will eventually be used as an interrupt line.

            GPIOSetMode(hGPIO,INPUT_GPIO_NUM, GPIO_DIR_INPUT);
            GPIOSetMode(hGPIO,OUTPUT_GPIO_NUM, GPIO_DIR_OUTPUT);

            GPIOClrBit(hGPIO,OUTPUT_GPIO_NUM);
            while(counter++ < SIMULATED_CLK_NUMBER_OF_CYCLES)
            {
                GPIOSetBit(hGPIO,OUTPUT_GPIO_NUM);
                val = GPIOGetBit( hGPIO, INPUT_GPIO_NUM );
                printf("GPIO:%d = %d\r\n", INPUT_GPIO_NUM, val);
                Sleep(SIMULATED_CLK_CYCLE_TIME/2);
                GPIOClrBit(hGPIO,OUTPUT_GPIO_NUM);
                val = GPIOGetBit( hGPIO, INPUT_GPIO_NUM );
                printf("GPIO:%d = %d\r\n", INPUT_GPIO_NUM, val);
                Sleep(SIMULATED_CLK_CYCLE_TIME/2);
            }

    This routine actually toggled my output high and low, and by jumpering that output to the input, I could then detect the input changing state.

    But that is where the happiness ended.

    My goal is to be able to use a input as a interrupt

    This next set of code fails with the message: " ERROR: ...Failed associate event with interrupt.

    // allocate the interrupt event for card detection
            m_hGPIODetectEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            if (NULL == m_hGPIODetectEvent)
            {
                printf("ERROR: m_hGPIODetectEvent...%d...Failed associate event.\r\n",INPUT_GPIO_NUM );
            }
            else
            {
                if (!GPIOInterruptInitialize(m_hGPIO, INPUT_GPIO_NUM, &m_dwGPIOSysintr, m_hGPIODetectEvent))
                {
                    printf("ERROR: 1...GPIOInterruptInitialize: %d...Failed associate event with interrupt\r\n",INPUT_GPIO_NUM );
                }
                else
                {
    // Wait for event
                    printf("1...GPIOInterruptInitialize: %d...WaitForSingleObject...\r\n", INPUT_GPIO_NUM);
                    dwWaitStatus = WaitForSingleObject(m_hGPIODetectEvent, INFINITE);
                    printf("SUCCESS...1...GPIOInterruptInitialize: %d...WaitForSingleObject...\r\n", INPUT_GPIO_NUM);
                    GPIOInterruptDone(m_hGPIO,INPUT_GPIO_NUM,m_dwGPIOSysintr);
                }
            }
            CloseHandle(m_hGPIODetectEvent);

    ===============================================

    GPIOInterruptInitialize() return a BOOL, so I'm not sure of the exact error.

    Am I still dealing with some kind of User Mode vs. Kernel mode type situation? Seems odd that the GPIOSetBit() rotuines work, yet the GPIOInterruptInitialize() fails. How can I determine why that routine cannot associate the event I created with the interrupt? If that in fact is whats happening.

    Also, I don't understand the details of the following functions in what they actually perform or why they are needed. I see them used in the SDController.cpp program but I am not sure what they are doing, or how I need to use them when I using the GPIOInterruptInitialize() routine.

    GPIOInterruptMask     Mask/unmask the GPIO’s interrupt

    GPIOInterruptDisable     Disable the interrupt event when no longer needed

    GPIOInterruptDone     Function to call when done processing a GPIO interrupt

    GPIOInterruptWakeUp     Register the GPIO as a wake up source for the system

    So no solution yet, but getting close.

    Tuesday, October 21, 2014 7:42 PM
  • Here are the inline functions in my gpio.h file.  Maybe you could create a gpio.h file from sdk_gpio.h and add those functions?  See if the related IOCTLs are implemented in the gpio driver.


    __inline DWORD
    GPIOInterruptInitialize(
        HANDLE hContext,
        DWORD id,
    	DWORD intrID,
    	HANDLE hEvent
        )
    {
        DEVICE_CONTEXT_GPIO *pContext = (DEVICE_CONTEXT_GPIO *)hContext;
    
        if ( (pContext != NULL) && (pContext->ifc.context) )
        {
            return pContext->ifc.pfnInterruptInitialize(pContext->ifc.context, id,intrID , hEvent);
    }
        else
        {
            DWORD   dwRC;
            IOCTL_GPIO_INIT_INTERRUPT_INFO sInitIntrInfo = {id, intrID, hEvent};
    
            dwRC = DeviceIoControl(pContext->hDevice,
                            IOCTL_GPIO_INIT_INTERRUPT,
                            &sInitIntrInfo,
                            sizeof(sInitIntrInfo),
                            NULL,
                            0,
                            NULL,
                            NULL );
    
            return dwRC;
        }
    }
    
    
    __inline DWORD
    GPIOInterruptDone(
        HANDLE hContext, 
        DWORD id,
    	DWORD intrID
        )
    {
        DEVICE_CONTEXT_GPIO *pContext = (DEVICE_CONTEXT_GPIO *)hContext;
    
        if ( (pContext != NULL) && (pContext->ifc.context) )
        {
            return pContext->ifc.pfnInterruptDone(pContext->ifc.context, id, intrID );
    }
        else
        {
            DWORD   dwRC;
            IOCTL_GPIO_INTERRUPT_INFO sIntrInfo = {id, intrID};
    
            dwRC = DeviceIoControl(pContext->hDevice,
                            IOCTL_GPIO_ACK_INTERRUPT,
                            &sIntrInfo,
                            sizeof(sIntrInfo),
                            NULL,
                            0,
                            NULL,
                            NULL );
    
            return dwRC;
        }
    }
    
    __inline DWORD
    GPIOInterruptDisable(
        HANDLE hContext, 
        DWORD id,
    	DWORD intrID
        )
    {
        DEVICE_CONTEXT_GPIO *pContext = (DEVICE_CONTEXT_GPIO *)hContext;
    
        if ( (pContext != NULL) && (pContext->ifc.context) )
        {
            return pContext->ifc.pfnInterruptDisable(pContext->ifc.context, id, intrID );
    }
        else
        {
            DWORD   dwRC;
            IOCTL_GPIO_INTERRUPT_INFO sIntrInfo = {id, intrID};
    
            dwRC = DeviceIoControl(pContext->hDevice,
                            IOCTL_GPIO_DISABLE_INTERRUPT,
                            &sIntrInfo,
                            sizeof(sIntrInfo),
                            NULL,
                            0,
                            NULL,
                            NULL );
    
            return dwRC;
        }
    }
    
    
    
    




    Tuesday, October 21, 2014 7:49 PM
  • Thanks Mario:

    But...I do have a header file called gpio.h and it contains the 4 routines, you enclosed, but(naturally), my routines contain one less passed parameter as yours...for example:

    Mine: __inline DWORD GPIOInterruptInitialize( HANDLE hContext,  DWORD id,  HANDLE hEvent )

    Yours: __inline DWORD GPIOInterruptInitialize( HANDLE hContext, DWORD id, DWORD intrID, HANDLE hEvent )

    So compiling I get an error with the one you supplied...and the GPIOInterruptInitialize() I have does not work. I'm guessing it was part of some sample code that did not work in the first place.

    Since I was able to make a hacked version of the SDController.cpp program, and actually got the interrupt routine to work, but trying the near identical routines in a user mode application, I suspect that some of these GPIO routines(like GPIOInterruptInitialize()) only work in Kernel mode, where the simplier GPIO routines, like GPIOSetMode() or GPIOSetBit() are ok.

    On the WinCE-TI forum I fond a entry that seems to confirm that(  http://e2e.ti.com/support/embedded/wince/f/353/p/149352/599108.aspx )..."The GPIO SDK you are referring to can be used by both applications and drivers. However some of its API can only be called from drivers that are running in kernel mode, and cannot be used by applications. This is the case for "GpioInterruptInitialize" that is intended to be used from drivers only as it calls the "KernelIoControl" which cannot be called from applications."

    So I think my next step is to create a Kernel mode driver, that have API calls that can be access from a User mode program, which then get to the GPIOInterruptInitialize() routine.  I made something like this to access real memory address lines from a User mode program via a Kernel mode API driver.

    Your help is greatly appreciated.

    Still working on this.

    Tuesday, October 21, 2014 11:50 PM
  • The solution to my problem was creating a kernal mode driver that would allow a user mode application to
    trigger the running of a thread that would setup a specific GPIO line to be an interrupt and in that thread
    wait for the GPIO to be triggered.

    The User mode program would create an named event,for example "GPIO150", then execute a API call that sets up the interrupt in the kernel driver, then wait for the kernel driver to signal the "GPIO150" event when the digital line changes state.

    The API call to the kernel driver would pass the GPIO number, for example '150', and the input trigger parameters,

    for example, "GPIO_DIR_INPUT | GPIO_INT_LOW_HIGH | GPIO_DEBOUNCE_ENABLE".


    *********************Here is snippets of the kernel driver code called EdasGpioDriver.cpp.

    [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\EdasGpioDriver]
        "Dll"="EdasGpioDriver.dll"
        "Prefix"="EGD"

    ------------------------------------------

    struct ARGS {
      int GpioNum;
      int GpioDirection;
    };

    DWORD EdasGPIOInterruptDisable(int GpioNum, DWORD  m_dwGPIOSysintr)
    {
        HANDLE m_hGPIO;

        m_hGPIO = GPIOOpen();
        if (m_hGPIO != 0)
        {
            GPIOInterruptDisable(m_hGPIO, GpioNum, m_dwGPIOSysintr);
            RETAILMSG(1,(TEXT("EdasGPIOInterruptDisable...OK.\r\n")));
            GPIOClose(m_hGPIO);
        }
        else
            RETAILMSG(1,(TEXT("EdasGPIOInterruptDisable...FAILED...GPIOOpen().r\n\r\n")));
        return 0;
    }

    DWORD EdasGPIOInterruptDone(int GpioNum, DWORD  m_dwGPIOSysintr)
    {
        HANDLE m_hGPIO;

        m_hGPIO = GPIOOpen();
        if (m_hGPIO != 0)
        {
            GPIOInterruptDone(m_hGPIO, GpioNum, m_dwGPIOSysintr);
            RETAILMSG(1,(TEXT("EdasGPIOInterruptDone...OK.\r\n")));
            GPIOClose(m_hGPIO);
        }
        else
            RETAILMSG(1,(TEXT("EdasGPIOInterruptDone...FAILED...GPIOOpen().r\n\r\n")));
        return 0;
    }

    DWORD EdasGPIOInterruptWakeUp(int GpioNum, DWORD  m_dwGPIOSysintr, int truefalse )
    {
        HANDLE m_hGPIO;

        m_hGPIO = GPIOOpen();
        if (m_hGPIO != 0)
        {
            if (truefalse == 1)
                GPIOInterruptWakeUp(m_hGPIO, GpioNum, m_dwGPIOSysintr, TRUE);
            else
                GPIOInterruptWakeUp(m_hGPIO, GpioNum, m_dwGPIOSysintr, FALSE);
            RETAILMSG(1,(TEXT("EdasGPIOInterruptWakeUp...OK.\r\n")));
            GPIOClose(m_hGPIO);
        }
        else
            RETAILMSG(1,(TEXT("GpioSampleThread...FAILED...GPIOOpen().r\n\r\n")));
        return 0;
    }

    DWORD EdasGPIOInterruptInitialize(int GpioNum, HANDLE  m_hGPIODetectEvent, int GPIODirection)
    {
        DWORD    m_dwGPIOSysintr;
        HANDLE m_hGPIO;
        int    ret;

        m_hGPIO = GPIOOpen();
        if (m_hGPIO != 0)
        {
            GPIOSetMode(m_hGPIO, GpioNum, GPIODirection);
            ret = GPIOInterruptInitialize(m_hGPIO, GpioNum, &m_dwGPIOSysintr, m_hGPIODetectEvent);
            if (ret == 0)
            {
                RETAILMSG(1,(TEXT("EdasGpioDriver...EdasGPIOInterruptInitialize...FAIL.\r\n")));
                return ret;
            }
            else
            {
                GPIOClose(m_hGPIO);
                return( m_dwGPIOSysintr);
            }
            GPIOClose(m_hGPIO);
        }
        else
            RETAILMSG(1,(TEXT("EdasGpioDriver...EdasGPIOInterruptInitialize...FAIL...GPIOOpen()\r\n")));

        RETAILMSG(1,(TEXT("EdasGpioDriver...EdasGPIOInterruptInitialize...3...END.\r\n")));
        return 0;
    }

    void GpioInterruptThread(LPVOID pArgs_)
    {
        ARGS *pArgs = (ARGS*)pArgs_;
        DWORD counter = 0;
        DWORD dwWaitStatus = 0;
        HANDLE   m_hGPIODetectEvent = NULL;
        DWORD    m_dwGPIOSysintr;
        HANDLE EdasGpioDriverDetectEvent;
        int    ret;
        TCHAR EdasGpioNamedEvent[20];        
        m_hGPIODetectEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == m_hGPIODetectEvent)
        {
            RETAILMSG(1,(TEXT("GpioInterruptThread...FAIL CreateEvent().\r\n")));
        }
        else
        {
            m_dwGPIOSysintr = EdasGPIOInterruptInitialize(pArgs->GpioNum, m_hGPIODetectEvent,
                GPIO_DIR_INPUT | GPIO_INT_LOW_HIGH | GPIO_DEBOUNCE_ENABLE);
            if (m_dwGPIOSysintr != 0)
            {
                RETAILMSG(1,(TEXT("GpioInterruptThread...SUCCESS...GPIOInterruptInitialize.")));
    // Don't think I need Wake.
                EdasGPIOInterruptWakeUp(pArgs->GpioNum, m_dwGPIOSysintr, 1);
    // Wait for event
                RETAILMSG(1,(TEXT("GpioInterruptThread...WaitForSingleObject...\r\n")));
    // Changed to 60 seconds to prevent it from getting stuck while testing.
    // I'm guessing that I eventually need to change this back to Inifinite.
                dwWaitStatus = WaitForSingleObject(m_hGPIODetectEvent, 60000);
                if (dwWaitStatus == WAIT_TIMEOUT)
                {
                    RETAILMSG(1,(TEXT("\r\nGpioInterruptThread...ERROR...Event TIMEOUT...\r\n")));
                }
                else
                {
                    RETAILMSG(1,(TEXT("\r\nGpioInterruptThread...SUCCESS...\r\n")));
                }
    // This reset the interrupt.
                EdasGPIOInterruptDone(pArgs->GpioNum, m_dwGPIOSysintr);
    //Signal the event back to User Mode application.
    // The User mode application initially creats a named event based on the GPIO line used.
    // and waits for the event to get signaled here.
                _stprintf( EdasGpioNamedEvent, _T("GPIO%d"),pArgs->GpioNum);
                EdasGpioDriverDetectEvent = CreateEvent(NULL, FALSE, FALSE, EdasGpioNamedEvent);
                ret = GetLastError();
                RETAILMSG(1,(TEXT("GpioInterruptThread...GetLastError=")));
                if (ret == ERROR_ALREADY_EXISTS)
                {
                    RETAILMSG(1,(TEXT("ERROR_ALREADY_EXISTS\r\n")));
                    RETAILMSG(1,(TEXT("GpioInterruptThread...SetEvent SIGNALED!\r\n")));
                    SetEvent(EdasGpioDriverDetectEvent);
                }
                else
                {
                    RETAILMSG(1,(TEXT("%d\r\n"), ret));
                    RETAILMSG(1,(TEXT("GpioInterruptThread...SetEvent NOT signaled.\r\n")));
                }
            }
            EdasGPIOInterruptDisable(pArgs->GpioNum, m_dwGPIOSysintr);
                CloseHandle(EdasGpioDriverDetectEvent);
                CloseHandle(m_hGPIODetectEvent);
        }
        RETAILMSG(1,(TEXT("GpioInterruptThread...END.\r\n")));
    }

    BOOL EGD_IOControl(DWORD hOpenContext, DWORD dwCode,
                       PBYTE pBufIn, DWORD dwLenIn,
                       PBYTE pBufOut, DWORD dwLenOut,
                       PDWORD pdwActualOut)
    {
        ARGS args;
        HANDLE hThread;
        BOOL RetVal = TRUE;

        EDAS_GPIO_ARGS *GpioParameters;
        GpioParameters = (EDAS_GPIO_ARGS *)pBufIn;

        args.GpioNum = GpioParameters->GpioNum;
        args.GpioDirection = GpioParameters->GPIODirection;

        switch(dwCode)
            {
            case EDAS_GPIOINTERRUPTINITIALIZE:
                RETAILMSG( 1, (TEXT("EGD_IOControl...EDAS_GPIOINTERRUPTINITIALIZE...START\r\n")));
                  hThread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)GpioInterruptThread,&args,0,&ThreadID);
                WaitForSingleObject(hThread,INFINITE);
                    if (NULL == hThread)
                    RETAILMSG( 1, (TEXT("EGD_IOControl...FAIL...GpioInterruptThread.\r\n")));
                else
                {
                    CloseHandle(hThread);    // Don't leak this!
                        RETAILMSG( 1, (TEXT("EGD_IOControl...SUCCESS...GpioInterruptThread.\r\n")));
                }
                RETAILMSG( 1, (TEXT("EGD_IOControl...EDAS_GPIOINTERRUPTINITIALIZE...END\r\n")));
            break;

            default:
                RetVal = FALSE;
            break;
        }
        return RetVal;
    }

    **************Here is snippets of the kernel API driver code called EdasGpioDriver_API.cpp.

    // This is the stucture that I need to send to the EdasGpioDriver
    typedef struct {
        int GpioNum;
        int GPIODirection;
    }  EDAS_GPIO_ARGS;

    HANDLE OpenEdasGpio()
    {
        HANDLE hDriver;
    // Get a handle to the driver. Which causes the driver's XXX_Open function to be called
        hDriver = CreateFile( TEXT("EGD1:"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,

    OPEN_EXISTING, 0, 0 );
        return hDriver;
    }

    void CloseEdasGpio(HANDLE hDriver )
    {
        CloseHandle( hDriver );
    }

    DWORD EdasGPIOInterruptInitializeAPI(HANDLE hDriver, int GpioNum, int GPIODirection)
    {
        BOOL RetVal = TRUE;
        DWORD BytesHandled;

        DWORD  m_dwGPIOSysintr = 0;
        EDAS_GPIO_ARGS GpioParameters;

        RETAILMSG( 1, (TEXT("EdasGpioDriver_API...EdasGPIOInterruptInitializeAPI...START.\r\n")));

        GpioParameters.GpioNum = GpioNum;
        GpioParameters.GPIODirection = GPIODirection;
        RetVal = DeviceIoControl(
                    hDriver,
                    EDAS_GPIOINTERRUPTINITIALIZE,
                            &GpioParameters, sizeof( GpioParameters ),
                    &m_dwGPIOSysintr, sizeof(m_dwGPIOSysintr),
                            &BytesHandled,
                            NULL );
        return m_dwGPIOSysintr;
    }

    **************************And here is the User Mode application snippet called EdasGpioDriver_Test.cpp:

    #include "stdafx.h"
    #include <windows.h>
    #include <commctrl.h>

    // This will eventually be in the SDK but for now I
    // use the exact path to where this file is located
    // in case I make changes to it.
    #include "C:\WINCE600\OSDesigns\EdasCE_CM_T3517\subproject\EdasGpioDriver_API\EdasGpioDriver_API.h"

    #define GPIO_DIR_OUTPUT         (0 << 0)
    #define GPIO_DIR_INPUT          (1 << 0)
    #define GPIO_INT_LOW_HIGH       (1 << 1)
    #define GPIO_INT_HIGH_LOW       (1 << 2)
    #define GPIO_INT_LOW            (1 << 3)
    #define GPIO_INT_HIGH           (1 << 4)
    #define GPIO_DEBOUNCE_ENABLE    (1 << 5)

    #define GPIO_PULLUP_DISABLE     0
    #define GPIO_PULLUP_ENABLE      1
    #define GPIO_PULLDOWN_DISABLE   0
    #define GPIO_PULLDOWN_ENABLE    1

    #define INPUT_GPIO_NUM 151

    int _tmain(int argc, _TCHAR* argv[])
    {
        HANDLE hEdasGpioDriver_API;     
        DWORD counter = 0;
        int    xx;
        DWORD dwWaitStatus = 0;
        HANDLE   m_hGPIODetectEvent = NULL;
        DWORD    m_dwGPIOSysintr;

        TCHAR EdasGpioNamedEvent[20];        

        hEdasGpioDriver_API = OpenEdasGpio();

        if( hEdasGpioDriver_API != INVALID_HANDLE_VALUE )
        {
            RETAILMSG(1,(TEXT("===========================================\r\n")));
            RETAILMSG(1,(TEXT( "GOOD...EdasGpioDriver_API_Test...OpenEdasGpio()...\r\n" )));
            RETAILMSG(1,(TEXT("===========================================\r\n")));

            RETAILMSG(1,(TEXT("EdasGpioDriver_Test...START.\r\n")));
    /*
        Create a named event in EdasGpioDriver_test.cpp and wait for the
        EdasGpioDriver.cpp program to signal that event.
    */
            _stprintf( EdasGpioNamedEvent, _T("GPIO%d"),INPUT_GPIO_NUM);
            RETAILMSG(1,(TEXT("EdasGpioDriver_Test...EdasGpioNamedEvent=...%s...\r\n"), EdasGpioNamedEvent));
            m_hGPIODetectEvent = CreateEvent(NULL, FALSE, FALSE, EdasGpioNamedEvent);
            if (NULL == m_hGPIODetectEvent)
            {
                RETAILMSG(1,(TEXT("EdasGpioDriver_Test...SUCCESS...CreateEvent().\r\n")));
            }
            else
            {
                RETAILMSG(1,(TEXT("EdasGpioDriver_Test...SUCCESS...CreateEvent().\r\n")));
                m_dwGPIOSysintr = EdasGPIOInterruptInitializeAPI(hEdasGpioDriver_API, INPUT_GPIO_NUM,
                    GPIO_DIR_INPUT | GPIO_INT_LOW_HIGH | GPIO_DEBOUNCE_ENABLE);
                RETAILMSG(1,(TEXT("EdasGpioDriver_Test...WaitForSingleObject.\r\n")));
    // Add a timeout so the program does not hang forever if this does not work.
                dwWaitStatus = WaitForSingleObject(m_hGPIODetectEvent, 60000);
                if (dwWaitStatus == WAIT_TIMEOUT)
                {
                    RETAILMSG(1,(TEXT("EdasGpioDriver_Test...WaitForSingleObject...TIMEOUT.\r\n")));
                }
                else
                {
                    RETAILMSG(1,(TEXT("EdasGpioDriver_Test...WaitForSingleObject...SUCCESS\r\n")));
                }
                    CloseHandle(m_hGPIODetectEvent);
            }
            CloseEdasGpio(hEdasGpioDriver_API);
            RETAILMSG(1,(TEXT("EdasGpioDriver_Test...END.\r\n")));
        }
        else
        {
            RETAILMSG(1,(TEXT("===========================================\r\n")));
            RETAILMSG(1,(TEXT( "FAIL...EdasGpioDriver_API_Test...OpenEdasGpio()...\r\n" )));
             RETAILMSG(1,(TEXT("===========================================\r\n")));
        }
        return 0;
    }






                     
    Tuesday, November 11, 2014 4:39 PM