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

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

975 Views
derikdevecchio
Contributor II

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();

}

0 Kudos
3 Replies

467 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Derik Devecchio,

     After reading your question, I do a low power PE project for your chip:Kinetis K10DX64VLH7, please find it from the attachment.

    My project is enter to LLS mode, and then use PTC11 as the wakeup source, because I don't have the K10DX64VLH7, so I test it on our K20D72M tower board, it works OK, K20D72M is compatible to your chip, so you can use it directly!

    I think your code can't run normally, mainly is the configuration problem, please refer to my code and check it again!

   If you don't want PE project, we still have the bare board project, please download the project from this link:

TWR-K20D72M: Kinetis K20 72 MHz MCU模块

   I wish my code will help you!

   If you still have question after using my code, please let me know, or maybe you should give us your project!

Best regards!

Jingjing

0 Kudos

467 Views
derikdevecchio
Contributor II

I hammered on this problem for half the weekend (12 hours) and I did make some progress.

1)  As mentioned earlier the LPTMR interrupt also did not wake the device.

2)  If I unmasked the corresponding NVIC table entries, for LPTMR and/or for PortC/D then I would wake up from whatever low power mode I am in.   

3) The LLWU interrupt is never fired, even when that interrupt is unmasked in the NVIC as well.  

4) With the LPTMR and PORT interrupts enabled in NVIC, I can remove all the code that involves the LLWU and the device will behave the same.  I conclude that whatever is waking me, it has nothing to do with the LLWU and its registers.

5) I believe that I am not in LLS because the NVIC does work even though it should not be active in LLS.   Also the current draw (about 550 uA) is more than double what I would expect for that mode.  Perhaps the LLWU will only work in Low Leakage modes. 

My main goal now is to figure out answer to the following questions.

1) If I am not in LLS, what mode am I in?  Now that I can finally exit, Is there any way to determine what mode I exited from?

2) What was preventing me from entering LLS? 

3) Why can't I read certain important registers like PMCTRL and LPTMR_CNR, even when I am in RUN mode and I have enabled the SIM gating for those modules.

467 Views
derikdevecchio
Contributor II

Since I originally posted this I have since tried waking the chip with the LPTMR.  It also fails to wake the chip on interrupt.  As near as I can tell the LLWU is completly non-functional.

I played with the LPTMR for long enough to convince myself it was wroking.  If I set  it to use the LPO (1kHz) and set the match for 9000, then the interrupt will trigger in about 9 seconds.  But if I am in Sleep mode, or in whatever mode the code above puts me in, then that intterupt does not wake me up.  


I have also noticed, that I can not read the LP Timers count register, LPTMR_CNR.   It says in the data sheet that I should be able to read it.  Any variable I fill with that always comes back zero, and the debugger always reports zero as well.


We are using the Keil/ Ulink2 development environment if that matters.  But since it is not just the debugger, but also the variables that don't read, I think that it must be some setting I am not doing right.  For example, if you don't set the SIM module bit you will get a hard fault when you access the registers.  I wonder if there is some other bit I need to set to make the LPTMR_CNR readable?   And perhaps that same bit explains why interrupts don't make it through the LLWU even though I have set the correspnding LLWU_ME bit for the timer.




0 Kudos