In Windows CE: Interrupt Service Thread I discussed the steps required by an Interrupt Service Thread (IST.) Refer to that post for an explanation of the following code.
static DWORD WINAPI DSInterruptThread(LPVOID p)
{
                DWORD RetVal = 0;
                HANDLE hEvent;
                DWORD SysintrValue;
                DWORD IRQ = MYDRIVER_IRQ;
 
                // Create an Event
                hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 
                // Register with the Kernel
                KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &IRQ, sizeof(DWORD), &SysintrValue, sizeof(DWORD), NULL) ;
                RetVal = InterruptInitialize( SysintrValue, hEvent, NULL, 0 );
               
                // Set the Thread Priority            
                CeSetThreadPriority(GetCurrentThread(), 150);
 
                while (1)
                {
                                // Wait for the Event to be Signaled
                                RetVal = WaitForSingleObject(hEvent, 2000 );
 
                                if( RetVal == WAIT_OBJECT_0 )
                                {
                                                // Service the Interrupt
                                                // In this case suspend the device
                                                SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
                                               
                                                // Tell the Kernel that the Interrupt has been Serviced
                                                InterruptDone( SysintrValue );
                                }
                                else if( RetVal == WAIT_TIMEOUT )
                                {
                                                // Optional, provide a way to stop the thread when the driver unloads
                                                // This is optional because the driver may never unload
                                                if( StopThreads )
                                                                break;
                                }
                }
 
                // When and if the driver unloads and the thread exits release resources
                InterruptDisable( SysintrValue );
                CloseHandle( hEvent );
                KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &SysintrValue, sizeof(DWORD), NULL, 0, NULL);
 
    return 0;
}
 
As Valter noted in his comment, there are many ways to write an IST.  So this is only one way to do it.
There are some things that this code doesn't show:
  • Setting up the IRQ as an input and interrupt source.  Each BSP and CPU family is different so a discussion of that is more complicated than I wanted to get into for this post.   Some will set up the interrupt as rising edge and/or falling edge or level detect in the kernel.  Some are automatic and some require some runtime configuration.
  • Set up the wake sources.  This IST puts the device in suspend, so somewhere the wake sources must be established.  Again this is BSP and CPU family dependent.
  • How to start the thread in XXX_Init() and stop it in XXX_Deinit().  I will get to that later.
Tags: Drivers
Copyright © 2009 – Bruce Eitman
All Rights Reserved