AnsweredAssumed Answered

Port interrupts do not seem to wake Kinetis from LLS (AN4503)

Question asked by Derik DeVecchio on Feb 14, 2014
Latest reply on Feb 24, 2014 by Kerry Zhou

I might be cross posting this.   The first time I posted it just seemed to vanish into a non-forum.  As penance I took the trouble to clean up a little grammar at least.

 

I am using a Kinetis K10DX64VLH7.  I am following the examples of SEction 3 of the AN4503.

 

After executing reset, I can tell that the chip has entered a low power mode because the current is at 575 uA (which still seems high for LLS), instead of several milliamps.  However, when I toggle the port switch I can see the increase in current from the ports internal pull up that suggests that the line did indeed change state.  But no interrupt occurs, or if it does occur it does not wake me from sleep.

 

I have attached my code below.  There are a lot of extra commands (NOPs mostly) in there to see if I could figure out what was going on.  But essentially this code is straight out of AN4503.

 

one of the things I noticed was that no matter what values I write to PMPROT and PMCTRL, when I read those registers, I get junk.  Even values that are impossible.  For example I might read 0x17 from PMPROT reading back 0x17 when bits 0 and 2 are supposed to always read 0.

 

I have tried this with and without the debugger attached.  The results are the same: They system just hangs no matter how many times I toggle the switch attached to Port pin C11.   I know for certain that pin is changing state because I can see the current increase by about 100uA when the switch is closed (shorted to ground).    After running the program in the debugger things will hang in the LLS statemet.  When I "stop" the debugger I will find myself on the instruction after the asm("WFI"); instruction.  From there, the program will run as normal.  Basically the Debugger can wake the chip from LLS.  But the interrupt from the port can not.

 

The following code executes immediately after reset.

 

void INIT_System (void) {

  // Disable the WDOG module  - BootStub doesn't handle this for us like a real bootloader

  WDOG_UNLOCK = (uint16_t)0xC520u;     /* Key 1 */

  // WDOG_UNLOCK : WDOGUNLOCK=0xD928 */

  WDOG_UNLOCK  = (uint16_t)0xD928u;    /* Key 2 */

// WDOG_STCTRLH: DISTESTWDOG=0,BYTESEL=0,TESTSEL=0,TESTWDOG=0,STNDBYEN=1,WAITEN=1,STOPEN=1,DBGEN=0,ALLOWUPDATE=1,WINEN=0,IRQRSTEN=0,CLKSRC=1,WDOGEN=0 */

  WDOG_STCTRLH = (uint16_t)0x01D2u;

 

 

      // DEBUG  This just puts the CPU to LLS immediately after reset.

      // I configure 2 GPIO's necesary to wake the chip.

      {

          volatile static unsigned int temp1;

          volatile static unsigned int temp2;

           // enable gates for ports C and D, we use one pin on each

           // as an interupt to wake from sleep                                                                                                                                                               SIM_SCGC5 |=  (SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTB_MASK);

        SIM_SCGC5 |= (

                   SIM_SCGC5_PORTC_MASK |

                   SIM_SCGC5_PORTD_MASK

              );

 

 

          // set POWER_SWITCH_DETECT pin as an interrupt,

          // this pin shorts to ground when switch is turned on.

          #define PSD_PIN_MASK     ((uint32_t)0x01 << 11)

          PORTC_PCR11  = (PORT_PCR_MUX(0x1) |    //pin 0 is GPIO

                          PORT_PCR_ISF_MASK |    // clear interupt flag

                          PORT_PCR_IRQC(0x0B) |  // interrupt on FALLING edge 0A

                          PORT_PCR_PE_MASK    |  // pull up/down enabled

                          PORT_PCR_PS_MASK);     // pull towards Vdd

          GPIOC_PDDR &= ~PSD_PIN_MASK;     // configure this pin as input

          LLWU_PE3 = LLWU_PE3_WUPE11(3);   // 2 enable low leakage mode interupt on RISING edge

 

 

          // set Extertnal Power Detect (EPD) pin as interrupt.

          // this pin is shorted to ground until barrel connector inserted

          // an external pull up on the board pulls it high.

          #define EPD_PIN_MASK     ((uint32_t)0x01 << 4)

          PORTD_PCR11  = (PORT_PCR_MUX(0x1) |    //pin 0 is GPIO

                          PORT_PCR_ISF_MASK |    // clear interupt flag

                          PORT_PCR_IRQC(0x0B));  // interrupt on RISING edge 09

          GPIOD_PDDR &= ~EPD_PIN_MASK;     // configure this pin as input

          LLWU_PE4 = LLWU_PE4_WUPE14(3);   // 1 enable low leakage mode interupt on RISING edge

 

 

          SIM_SCGC4 = SIM_SCGC4_LLWU_MASK;   // enables LLWU (seems to be not necessary on K10)

          MCG_C6 &= ~MCG_C6_CME_MASK;    // turns off clock monitoring, should be off

         

 

 

       // prepare to enter sleep mode

      

       temp1 = MC_PMPROT;

       temp1 = MC_PMCTRL;

      //MC_PMPROT = MC_PMPROT_ALLS_MASK;

      MC_PMPROT= 0x2A;  // just enable everythying (debug)

       temp1 = MC_PMPROT;

       temp1 = MC_PMCTRL;

       asm("NOP");

       asm("NOP");

       asm("NOP");

 

 

 

    

   MC_PMCTRL = ( MC_PMCTRL_LPLLSM(0x3)) ;

 

 

       /*wait for write to MC_PMCTRL to complete to SMC before stopping core */

       temp1 = MC_PMCTRL;

       asm("NOP");

       asm("NOP");

       asm("NOP");

       asm("NOP");

       asm("NOP");

 

 

       /* Now execute the stop instruction to go into LLSS */

 

 

      // deepsleep();

        SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;

       asm("NOP");

       asm("NOP");

       asm("NOP");

       asm("NOP");

 

 

 

 

        asm("WFI");

 

 

 

 

       asm("NOP");    // first instruction after wake - never executes!

       asm("NOP");   

       asm("NOP");

       

      } // end debug

  

// normal program execution begins here. 

 

  //Enable gate for all port clocks.   We use at least one pin in every port.

  SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK

   | SIM_SCGC5_PORTB_MASK

   | SIM_SCGC5_PORTC_MASK

   | SIM_SCGC5_PORTD_MASK

   | SIM_SCGC5_PORTE_MASK );

 

 

  INIT_SystemClock();

}

Outcomes