GPIO Interrupt handling in Win CE 6.0

May 29, 2008 at 1:43 PM
Hi All,

I'm using GPIO_101 to monitor the state of external signal in kernel mode driver. The pin is configured to generate interrupts if the falling (or rising) edges are detected.
The driver doesn't receive any interrupt caused by GPIO_101. I see that the appropriate bit in GPIO status register (GEDR3) is never set.

The same code works fine on BSP (with PXA270 processor) of other vendor, running Windows CE 5.0.

Is it possible that all interrupts from GPIOs are being intercepted by any module in BSP ?

Thanks in advance,
May 30, 2008 at 12:15 PM

I have found that corresponding bits in GPIO status register is being set when GPIO IRQs are disabled in IRQ controller.
It means that when GPIO IRQs are enabled any X module in WinCE 6.0/BSP intercepts all GPIO interrupts and clears whole status registers (GEDR0-GEDR3). 

Is anybody familiar with this issue?

Thanks again,
Jun 1, 2008 at 7:06 PM
Look at gumio.h and you will see GPIO101 is reserved for the notification LED.
It is configured as an output by the bootloader (if notification LED is selected in the hardware config word).
You will see a message on the boot terminal:

Configuring notification LED ...Configured.
If you have this option enabled.

If you deselect the Notification LED from the hardware word this GPIO should be free to use.

Jun 2, 2008 at 5:58 AM

Thank you for your reply,

Notification LED is disabled in HW configuration. GPIO_101 is configured as input in our driver and the falling edge detection bit is set (GPDR3[5] is clear, GFER3[5] is set).
I read the logic level of this pin from the GPLR3 register and see that it changes depending on external signal, but the corresponding bin of GEDR3 status register is never set.
The same behavior I see for  GPIO_16 and GPIO_113.

The problem is not in configration. GEDR3[5] bit of status register is being set when GPIO IRQs of all pins (2-120) are disabled in IRQ controller.
I think that some module in BSP intercepts interrupts of GPIO16/101/113 and clears correspondings bits of GEDR register. Or maybe some of the modules handles interrupts from the own GPIOs and unintentionally clears status bits of other GPIOs. How we can clarify it?

Thank you,

Jun 3, 2008 at 2:26 AM
I have not experimented much with installable interrupts but I think it is working as designed.
Look at the intr.c file in the PXA270 common SOC directory. I think it may be recognizing the interrupt
and clearing the GEDR bit as intended ... it my be just you don't have the sysintr registered for the interrupt
so it doesn't know how to call your IST after the interrupt is serviced in the ISR.

I think you may need to use the IOCTL_HAL_REQUEST_SYSINTR with the interrupt number 201 (for GPIO101).

I'll look a little deeper too.

Jun 3, 2008 at 12:55 PM
Thank you for your helpful reply. You are rigth, it seems that we have a problem with registration of sysintr. 
Actually I register my sysintr with the interrupt number IRQ_GPIOXX_2=10 (it works fine under the WinCE 5.0).
I changes my code to use IRQ number 201 in the case of WinCE 6.0 - but no positive results.

Jun 4, 2008 at 1:31 PM

I found the following code in intr.c. BSPIntrActiveIrq() function allways returns  irq = IRQ_GPIOXX_2 for IRQ_GPIOXX_2 and therefore allways executed the code in  if (irq == IRQ_GPIOXX_2 && origIrq== irq) condition which clears status registers without calling any ISR handler. I think that BSPIntrActiveIrq()  should return IRQ code of corresponding GPIO.
What do you think about that?

Thank you,

        UINT32 origIrq = irq;  // save the original so we can tell if it's BSP specific irq
        if (irq == IRQ_GPIO0 || irq == IRQ_GPIO1 || irq == IRQ_GPIOXX_2)
            // Give BSP chance to translate IRQ -- if there is subordinate
            // interrupt controller in BSP it give chance to decode its status
            // and change IRQ
            irq = BSPIntrActiveIrq(irq);

            // if irq equals IRQ_GPIOXX_2 demultiplex it to a particular emulated GPIO IRQ if it's not a BSP specific IRQ
            if (irq == IRQ_GPIOXX_2 && origIrq== irq) {
                // find the GPIO IRQ
                irq = FindIRQ_GPIOXX_2();

                if (irq != OAL_INTR_IRQ_UNDEFINED)
                    // Mask the interrupt
                    CLRREG32(&g_pICReg->icmr, (1 << IRQ_GPIOXX_2));
                    //clear the GEDRx bit otherwise this ISR will be called again

                    // Unmask the interrupt
                    SETREG32(&g_pICReg->icmr, (1 << IRQ_GPIOXX_2));
            else if (irq == IRQ_GPIO1 && origIrq== irq) {
                //clear the GEDRx bit otherwise this ISR will be called again
                g_pGpioRegs->GEDR0 = 1u << 1;

Jun 5, 2008 at 3:25 PM
Edited Jun 5, 2008 at 3:32 PM
Yes, I saw that too. You can override the default GPIO interrupt handling by returning OAL_INTR_IRQ_UNDEFINED for the BSPInterActiveIrq().
For the normal path, I believe irq should be set to IRQ_GPIOXX_2 (the primary irq) BSPIntrActiveIrq should leave this unchanged so FindIRQ_GPIOXX_2
should execute. This will look through all the pending (secondary interrupt) edge status registers and set the new (secondary) irq number. After that it should
reset the pending secondary IRQ status then farther down in the routine (not shown) it should call the IST based on this new (secondary) irq number.
If the sysintr is registered to this secondary irq number I think the IST should be called. At least thats how I read it.