AnsweredAssumed Answered

Port interrupts from LLS (AN4503) don't wake Kinetis

Question asked by Derik DeVecchio on Feb 14, 2014
Latest reply on Feb 17, 2014 by Kan_Li

I am using a Kinetis K10DX64VLH7.

 

I am following the examples of SEction 3 of the AN4503.  I can see the chip going to sleep (current down to 575 uA - which still seems high for LLS).  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 and I never exit sleep mode.

 

I have attached my code below.  There are alot of extra commands in there to see if I could figure out what was going on. 

 

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 (like 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 swithc the switch.    After running the program in the debugger things will hang.  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