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.

External interrupt issue

Other Parts Discussed in Thread: CC2538

Hi,

In my application I am using the Sample Thermostat (HA 1.1.0) on CC2538. I am using a button to activate the match description request (falling edge=wake up; rising edge=trigger). I used to use another button to send temperature value from sleeping end device to coordinator in the same way but now I have a 15ms wide pulse of different polarity from external hardware instead. The pulse starts low (rising edge=wake up, falling edge=trigger) and generates a following problem:

The application seems to be working fine when the match description request is issued. MCU enters sleep mode and waits for the external hardware interrupt mentioned earlier. When interrupt is issued the mcu wakes up on the rising edge and after 15ms when the failing edge is issued the mcu triggers to transmit the temperature value and enter the sleep mode. However, when the next interrupt arrives it wakes up the mcu on rising edge but the falling edge is missed for some reason. This causing the mcu to stay awake until the next interrupt occurs. In that instance it recognises the falling edge, transmits the temperature and enters the sleep mode. Any idea why the falling edge interrupt is missed? I disabled the de-bouncer on that pin but problem still occurs.

I have a problem to sort this one out and would like to hear from someone who can help me with this. Perhaps even better would be to set up the wake up and trigger interrupts both on the same rising edge. 

Kind regards

Milan

  • It might be filter by the debounce since you only use a 15ms wide pulse of different polarity. Do you try wider pulse?

  • That was my first thought so I commented out the debouncer but no effect. Debouncer lasts only 500 counts so that is I think too short to affect the 15ms pulse. Thanks

    Next, I changed the trigger to wake up the mcu on falling edge and to trigger the transition on low level. I scoped out that there is about 120ms delay (hanging) before the transition occurs. This is why the previous 15ms edge trigger was missed. 

    On the other hand, if I press the match description request any time after the system has been running the first following pulse is always fine (no 120ms delay) but the next includes the delay again. Any ideas?

  • Hi Milan,

    This has been identified as an issue and will be corrected in the future release. For Home Automation -1.2 and previous releases. 

    Interrupts may be missed when used as wake up source or wake up interrupts. The GPIOs have two separate configurations: as generic interrupts, and as power-up interrupts (i.e. wakeup sources from sleep): These are enabled using the registers GPIO_IE and GPIO_PI_IEN respectively. (please see the CC2538 user’s guide: http://www.ti.com/lit/ug/swru319b/swru319b.pdf). The status of each of the interrupt type (i.e. which source triggered the interrupt) is also available separately, via GPIO_MIS for the enabled general interrupts, and GPIO_IRQ_DETECT_ACK for enabled power interrupts. 

    Both type of interrupts triggers the same interrupt handler, which is registered in the interrupt vector. This direct interrupt handler is a single function that is called for all the GPIOs of the same port. This handler, in turn, checks to see which specific GPIO triggered it, and calls a specific handler. 

    In the code, this ‘direct’ interrupt handler for all PortA GPIOs is ioPortAIsr() ( download the source code from http://www.ti.com/tool/cc2538-sw and the project at install-dir\bsp\srf06eb_cc2538\drivers\projects\iar)  you can see the bsp project file io_pin_int.c for this ). To determine the actual GPIO that triggered the interrupt, it reads GPIO_O_MIS (i.e. the indication of the triggered general-interrupts). The issue seems to be that sometimes while the device is asleep, a button-press successfully triggers a power-interrupt, but fails to trigger the respective normal interrupt. So, ioPortAIsr() is called (since triggered by the power-interrupt), but when it checks which GPIO caused the interrupt it sees none. Then it finishes without doing anything, and immediately called again since the power interrupt is never cleared. Pressing the button again at this time will be successfully caught as a general interrupt, and release the loop: ioPortAIsr() will check the sources again, will see this button was pressed, and will call the respective GPIO-specific interrupt handler - in our case interrupt_keybd(), which call SysCtrlPowIntClear() that clears the power-interrupt signal. 

    A minor modification to the deiverlib code is required to resolve this. The respective source code may be downloaded from http://www.ti.com/tool/cc2538-sw. After downloading the source package from the link above, please add to the IAR project all the C files from swrc271a\cc2538_foundation_firmware_1_0_1_0\driverlib\cc2538\source. Please also remove the ‘driverlib’ library from the linker list, in project->options->linker->Library. 

    Then, in gpio.c, modify GPIOPinIntStatus() as follows: 

    GPIOPinIntStatus(uint32_t ui32Port, bool bMasked) 

    { 
        // 
        // Check the arguments. 
        // 
        ASSERT(GPIOBaseValid(ui32Port)); 
     
        // 
        // Return the interrupt status. 
        // 
        if(bMasked) 
        { 
            return(HWREG(ui32Port + GPIO_O_MIS) | GPIOPowIntStatus(ui32Port,bMasked)); 
        } 
        else 
        { 
            return(HWREG(ui32Port + GPIO_O_RIS) | GPIOPowIntStatus(ui32Port, bMasked)); 
        } 
    } 

    Doing these changes should resolve the issue of missed interrupts when the GPIO is used for both power up and normal interrupts.
    Regards,

     
  • Thank you for explanation problem sorted.

    Regards

    Milan

  • Do you now how exactly the driverlib code was modified to resolve this issue?

    I'm using Contiki-OS which is based on this driverlib and I've encountered the same problem. I'd like to fix this in Contiki-OS.

    Many thanks in advance.
  • I have no idea why you suffer this but I can suggest you an alternative. You can start a timer event to check if GPI goes to low and go to sleep mode after receiving rising edge interrupt. In this way, you can avoid the non-sleeping problem.
  • In fact I was trying to remove my post because I just have to add the modification in gpio.c

    Thanks for your reply.