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.

How long should it take to wake up from deep sleep?



I've been reading through the data sheet and can't seem to find this bit of info.  How long should it take to wake up from deep sleep? I'm trying to wake up and kick off a timer, but when I'm in deep sleep it looks like the clock doesn't change over (i'm going from PLL'd 80 Mhz down to 16 Mhz MOSC for sleep and upon wake up back to 80Mhz) to 80Mhz for a while there fore driving my timer that is supposed to run upon wake up by the slow clock from when it was asleep.  For a 10ms delay it takes about 30ms.  I can test this with out going to into deep sleep and my timer now is right on 10mS.

Thanks,

Rob

  • Hello Robbie,

    When the device goes from Run mode to Deep Sleep the system clock source is changed and the PLL shut down to save power. Hence when the system starts again it takes time for the PLL to lock and hence the timer may still work of the 16MHZ MOSC for some more time before it switches to PLL clock of 80MHz

    Regards

    Amit Ashara

  • Hey Amit,

    Thanks for the reply!  I was thinking that was the case, but even if I make the delay 1 second the timer doesn't interrupt until 2+ seconds...like 2.2S.  It just seems like the time to lock should be so small compared to a whole second I shouldn't notice it.  I'm wondering if the clock source is getting stuck on 16Mhz or something.  I'm still working on it and I don't really have any new info other than this problem of the elongated time applies to  very large delays as well as the 30mS I originally posted about.

    Rob

  • Hello Rob,

    Can you post the code, that would help understand the issue better,

    Regards

    Amit

  • Yea,

    My configuration function for WTimer2 that I kick off when I Power up.  Counter is a value pulled from some other code.

    void WTimer2_64bit_config(uint64_t counter)
    {
    	// Enable Timer peripheral
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER2);
    
    	TimerConfigure(WTIMER2_BASE, TIMER_CFG_PERIODIC);
    
    	TimerLoadSet64(WTIMER2_BASE, counter);
    
    	// Enable timer interrupt in master interrupt controller
    	TimerIntEnable(WTIMER2_BASE, TIMER_TIMA_TIMEOUT);
    	// Register ISR
    	TimerIntRegister(WTIMER2_BASE, TIMER_A, WTimer2IntHandler);
    	// Enable debug stall
    	TimerControlStall(WTIMER2_BASE, TIMER_A, true);
    	TimerIntClear(WTIMER2_BASE, TIMER_TIMA_TIMEOUT);
    }

    Deep sleep mode configuration:

        //
        // Enable deep sleep mode configurations
        //
        SysCtlDeepSleepClockSet(SYSCTL_DSLP_DIV_1 | SYSCTL_DSLP_OSC_MAIN);		// Set deep sleep clock to be main OSC divided by 1 -> 16Mhz crystal
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_USB0);					// Enable USB0 to interrupt form deep sleep
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_WTIMER0);					// Enable WTimer0 to interrupt from deep sleep (won't happen because this only runs
    																			// when the system is actively sampling)
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_WTIMER1);					// Enable WTimer1 to interrupt from deep sleep
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_WTIMER2);					//
    	//SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_GPIOF);
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_ADC1);					// Enable ADC1 to interrupt from deep sleep
    	SysCtlPeripheralClockGating(true);										// Enable clock gating which will utilize the above configurations regarding
    																			// peripherals in sleep mode

    GPIO ISR

    void GPIO_Discrete_Trigger(void)
    {
    	// Discrete trigger interrupt disable
    	GPIOIntDisable(GPIO_PORTF_BASE, GPIO_PIN_4);
    
    
    	// Clear interrupt flag (this ISR)
    	GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);
    
    
    	Triggered_Flag = 1;
    }

    So, I basically power up, configure and then enter deep sleep.  I wanted to receive a falling edge in an IO pin to wake up, kick of another timer creating a delay before I kick off an ADC.  Now, in main I have some if statements that check flags set in different interrupt routines and if they are set they kick off the functionality in my system.  One of the if statements in my main loop is a block that checks to see if anything is running and if not (all flags == 0) then I enter that if and go back to deep sleep.  This works for my main functionality.  For some reason when I added this third one (the trigger delay timer) it just didn't block like the others.  Here is an example of what checks to see if I should enter deep sleep.

    		if((WTimer0_running && ADC_running && DelayTriggerRunning) == 0){
    
    			/* Here I make sure I spin for 500 cycles before
    			 * I go into sleep mode.  These are main loop cycles
    			 * because when a USB packet is received it takes a
    			 * couple main loop cycles to work through the
    			 * packet and respond to the GUI accordingly.
    			 */
    			if(sleepCnt < 500){
    				sleepCnt++;
    			}else{
    				sleepCnt = 0;
    				SysCtlDeepSleep();
    			}// end burn cycle block
    
    		}// end deep sleep catch block

    The problem I think I was having is that I wasn't blocking with my flag and there fore after I threw the flag in the IO interrupt service routine I jumped into my if block that checked to see if this flag was set and kick off my delay timer.  If I put a while loop here trapping the cpu so it can't go back and service stuff in main it worked.  If I let it go back even though DelayTriggerRunning = 1 at this point it went back to sleep. 


    The solution for me (so far tonight...I'll test more in the morning) was to change my if statement that checked my flags to this:

    		if((WTimer0_running == 0) && (ADC_running == 0) && (DelayTriggerRunning == 0)){
    
    			/* Here I make sure I spin for 500 cycles before
    			 * I go into sleep mode.  These are main loop cycles
    			 * because when a USB packet is received it takes a
    			 * couple main loop cycles to work through the
    			 * packet and respond to the GUI accordingly.
    			 */
    			if(sleepCnt < 500){
    				sleepCnt++;
    			}else{
    				sleepCnt = 0;
    				SysCtlDeepSleep();
    			}// end burn cycle block
    
    		}// end deep sleep catch block

    Now it is working correctly.  When I tell it to delay for 1 second the scope shows the appropriate toggling at 1 second and then the chip goes back to sleep.  You can also see my isAlive LED accelerate in blinking now that the chip isn't asleep during the trigger delay which is just the time that the trigger delay WTimer2 runs. 

    Long story short, I re-wrote the same logic in the if statement a different way and it works now.  Not sure why.

  • Hello Rob,

    The two if statements will have different result. In the first If statement if any of the flags is 0 then the condition will equate to 0 even if the other flags are 1. The second if statement fixes that by returning the result of compare and then logically anding it.

    Please note that in deep sleep the timer will be working at 16MHz v/s 80MHz in run mode giving a factor of x5. So based on the time it would remain in deep sleep, the timer will be working for 16MHz and then once PLL locks it will work at 80MHz.

    Total time for the timer to timeout = Counts/80M + Counts/16M + Counts/80M

    Regards

    Amit Ashara

  • Ok.  I'm having a hard time seeing them not being functionally equivalent ifs but they do behave differently.  As before, thank you so much for the quick responses.   I may try to get a time next week when I'm back in town just for the sake of more info.   If I wake up and wait in a while loop until the sys control sysclkget() returns 80000000 will this work as a timing analyses mechanism.   In other words if the sysctrlclkget function returns 80 MHz does that mean the pll is locked?

  • Hi Robbie,

    The SysCtlClockGet function will return the value based on the RCC/RCC2 register setting. To look at the true lock you can poll the SYSCTL_RIS register bit 6.

    Regards

    Amit