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.

CC2541: Periodic Wakeup other than WDT?

The WDT periodic wakeup options are limited to a few intervals that do not suite my needs.  I need a wakeup from PM1 or PM2 every  5msec based on the 32KHz ROSC. 

My approach was to use the sleeptimer and to set the next sleeptimer compare in the sleeptimer ISR as shown below.  This works fine if the change to PM1 or PM2 is not invoked, that is, EnterSleepModeProcessInterruptsOnWakeup() below is commented out.  It works if EnterSleepModeProcessInterruptsOnWakeup() is not commented out if using a debugger and a breakpoint is set in the ISR.  However, if left to run free it ends up in the weeds.

I'm using TI's code examples in the following for setting the sleeptimer and for invoking sleep mode...

#include "power_mode.h"
#include "ioCC254x_bitdef.h"
#include "ioCC2541.h"

/***********************************************************************************
* LOCAL VARIABLES
*/
// Union for storing 24 bit sleep timer value.
typedef union {
    unsigned long value;
    unsigned char byte[4];
} union_32bit;

static union_32bit sleep_timer;
static long loop_cnt;

void    set_sleeptimer()
{
    while(!(SLEEPSTA & SLEEPSTA_CLK32K)); // Wait for positive flank on sleep timer.
    
    sleep_timer.byte[0] = ST0;    // ST0 must be read first.
    sleep_timer.byte[1] = ST1;                  
    sleep_timer.byte[2] = ST2;
    
    sleep_timer.value += 164;
        
    ST2 = sleep_timer.byte[2];
    ST1 = sleep_timer.byte[1];
            
    while( !(STLOAD & STLOAD_LDRDY) );
    ST0 = sleep_timer.byte[0];
}


#pragma vector = ST_VECTOR
__interrupt void sleep_isr(void)
{
    STIF = 0;
    set_sleeptimer();
}


int main(void)
{
    STIF = 0;            // Clear [IRCON.STIF] (Sleep Timer CPU interrupt flag).
    STIE = 1;            // Set the individual, interrupt enable bit [IEN0.STIE=1].
    EA = 1;                // Enable global interrupt by setting the   [IEN0.EA=1].
    
    SLEEPCMD = (SLEEPCMD & ~SLEEPCMD_MODE) | SLEEPCMD_MODE_PM1;
    set_sleeptimer();

    while(1)
    {
         EnterSleepModeProcessInterruptsOnWakeup();
        ++loop_cnt;
    }
}

  • Gi Gi said:
    However, if left to run free it ends up in the weeds.

    What do you mean by this, what do you observe? If you try to stop the execution with the debugger, please note that PM1 is not supported in debug mode. You should wither try it without debugger (this is also needed for realistic power numbers) or in PM2, where the debugger works and is able to break the target even in sleep.

  • Thank you!  I was blind to the fact that it was working.  A simple error in my toggling of a scope observable signal hid this. Weeds meant that I see instr counter in disassembly window at FFFFFF.  So, in sleep mode this is to be expected if I halt execution?

    Thanks again!

    GiGi