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.

CC2538 ZStack POWER_SAVING issues

Other Parts Discussed in Thread: CC2538

Hello All, 

I have attempted some power saving strategies on my CC2538 with ZStack Energy, but with poor results:

I have taken the ZED IPD example and modified it to use Port C for 8 switch/buttons. I have enabled regular interrupts, and with POWER_SAVING DISabled, they work well.

I have read the CC2538 power management document as given by ZStack. This is what I did to enable power saving:

1. Enable POWER_SAVING in the defined symbols.

2. DISable NWK_AUTO_POLL.

3. In f8wconfig.cfg:  -DRFD_RCVC_ALWAYS_ON=FALSE  ;   -DPOLL_RATE=0  ;  -DQUEUED_POLL_RATE=0  ;  -DRESPONSE_POLL_RATE=0.

4.  Set all unused IO to outputs, no connections.

5. Cancelled the time update event called IPD_UPDATE_TIME_EVT.

6. DISabled HAL_KEY.

After the module has joined the network, when I measure the current consumption on the CC2538EM across the Vdd and USB pins (power source is USB plug), I get 20mA constantly. This shows that it is not even in power-mode 1!

What else can I attempt to get to PM1 and hopefully PM2 ?

And ..

My interrupts stop working at this point too. They will work while the module searches for a network to join, but once joined, they stop working. Why would it do this.

Thanks in advance, any advice would be greatly appreciated!

Regards, DanO.

  • DanO,
    Can you please clarify the stack version you are using?

    In your use case, assuming the CC2538 entered a low power mode, what would wake up the CPU. Typically this would be an Osal timer or a poll timer for PM 1/2. If you enable a 5s timer in the application that should suffice for debug purposes. Can you put a break point on HAL_SLEEP_SET_POWER_MODE in hal_sleep.c and verify if this is being hit.

    Regards,
    TC.
  • Hi TopCat, Thanks for your response,
    It is ZStack Energy 1.1.0, IAR 7.20.1.
    Its end of the day here, Ill do the timer and breakpoint tomorrow.

    Thanks again, DanO.
  • Ok thanks, I am also setting up the same test with 1.1.0.
  • Hi TopCat,

    I have done the test as you suggested. In an attempt to make it a more straight-forward ZStack power-saving scenario, I did change some of the parameters of the test to something more simple:

    1. As before, enable POWER_SAVING in the defined symbols.

    2. Re-enable NWK_AUTO_POLL in the defined symbols.

    3. In f8wconfig.cfg, back to defaults: -DRFD_RCVC_ALWAYS_ON=FALSE ; -DPOLL_RATE=1000 ; -DQUEUED_POLL_RATE=100 ; -DRESPONSE_POLL_RATE=100.

    4. As before, set all unused IO to outputs, no connections.

    5. As before, cancelled the time update event called IPD_UPDATE_TIME_EVT, but had the timer-test event active.

    6. As before, disabled HAL_KEY.

    Even with the simpler scenario, the breakpoint at HAL_SLEEP_SET_POWER_MODE () does NOT trigger. So something must be wrong.

    Any suggestions are welcome, thanks again for your time.

    Regards, DanO.
  • I forgot to add:

    Whilst the test is running, when I push the "break" button under the debug controls, the execution is on the MAC_RADIO_TIMER_SLEEP(); line in mac_sleep.c. When I push "go", and "break" again, the execution is still there.

    I tried disabling POWER_SAVING again, and everything works fine( Interrupts, test-timer event, etc)

    Something else I forgot to add: I disabled as many of the defined symbols as I could, as I thought that they were not necessary and might add to the power consumption. Perhaps I "broke" the code by doing this?! Here is the list of pre-defined symbols for my test:

    DANIEL_PCT_CI_SE_2013 (Personal addition)
    POWER_SAVING
    REMOTE_CONTROL_IT (Personal addition)
    HAL_LED
    ZCL_REPORT
    xHAL_KEY
    xOSALMEM_METRICS
    xLCD_SUPPORTED
    ewarm
    ZCL_KEY_ESTABLISH
    TC_LINKKEY_JOIN
    NWK_AUTO_POLL
    NV_INIT
    xNV_RESTORE
    xZTOOL_P1
    xMT_TASK
    xMT_APP_FUNC
    xMT_SYS_FUNC
    xMT_ZDO_FUNC
    INTER_PAN
    HOLD_AUTO_START
    xTEST_CERT_DATA
    xMT_SYS_KEY_MANAGEMENT
    CC2538_USE_ALTERNATE_INTERRUPT_MAP=1

    I hope that this helps, thanks again.
    Rgds, DanO
  • Hi TopCat (and any other readers),

    It seems I have solved most of the problem:

    Firstly, being an IPD, there were default price-update timers running that I did not know about. What would happen is that it would go into some low power mode and then after 5s it would service the timer and not go back into low power mode. Anyway after disabling the timer it seemed to wait a bit at 10mA consumption, and then eventually drop significantly to the low 10s of uA.

    Secondly, I didn't read the CC2538 power document properly and missed the bit about changing OnboardKeyIntEnable to HAL_KEY_INTERRUPT_ENABLE, although in this case I had HAL_KEY disbaled, so it wouldnt have made a difference, but someone else reading this might find that changing these setting will help them.

    Thirdly, also being an IPD, the default setting for ipdPowerSource was the default "POWER_SOURCE_MAINS_1_PHASE", so I changed it to POWER_SOURCE_BATTERY. Not sure if this was needed to make it work, but there seemed to be ares of the power-saving manager that checked for this. This setting is found under ipd_data.c


    But, I still have one more issue:

    Once in sleep-mode, it will not wake up for any state changes on PortC or Port D. I have tried to make use of GPIOPowIntTypeSet(), GPIOPowIntDisable(), GPIOPowIntEnable(), GPIOPowIntClear. These are found in hal_sys_crtl.c and I have tried to use these functions in the same way that the file has them set up for the board buttons, see the code below ( "REMOTE_CONTROL_IT " is my project name):

    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntTypeSet(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ), GPIO_POW_FALLING_EDGE );
    GPIOPowIntTypeSet( GPIO_D_BASE, GPIO_PIN_2, GPIO_POW_FALLING_EDGE);
    #else //REMOTE_CONTROL_IT
    /* Setup GPIO A, C as a falling edge */
    GPIOPowIntTypeSet(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT |
    BSP_KEY_UP | BSP_KEY_DOWN, GPIO_POW_FALLING_EDGE);
    GPIOPowIntTypeSet(BSP_KEY_SEL_BASE, BSP_KEY_SELECT, GPIO_POW_FALLING_EDGE);
    #endif //REMOTE_CONTROL_IT

    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntEnable(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ) );
    GPIOPowIntEnable( GPIO_D_BASE, GPIO_PIN_2 );
    #else //REMOTE_CONTROL_IT
    GPIOPowIntEnable(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT | BSP_KEY_UP |
    BSP_KEY_DOWN);
    GPIOPowIntEnable(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);
    #endif //REMOTE_CONTROL_IT
    }

    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntDisable(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ) );
    GPIOPowIntDisable( GPIO_D_BASE, GPIO_PIN_2 );
    #else //REMOTE_CONTROL_IT
    GPIOPowIntDisable(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT | BSP_KEY_UP |
    BSP_KEY_DOWN);
    GPIOPowIntDisable(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);
    #endif //REMOTE_CONTROL_IT

    void SysCtrlPowIntClear(void)
    {
    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntClear(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ) );
    GPIOPowIntClear( GPIO_D_BASE, GPIO_PIN_2 );
    #else //REMOTE_CONTROL_IT
    GPIOPowIntClear(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT | BSP_KEY_UP |
    BSP_KEY_DOWN);
    GPIOPowIntClear(BSP_KEY_SEL_BASE,BSP_KEY_SELECT);
    #endif //REMOTE_CONTROL_IT
    }

    Any advice would be highly valued! Thanks for your time in reading all this.

    Regards, DanO.
  • Apologies for the code snippets, they are incomplete, see below:

    void SysCtrlWakeupSetting(void)
    {
    ...
    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntTypeSet(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ), GPIO_POW_FALLING_EDGE );
    GPIOPowIntTypeSet( GPIO_D_BASE, GPIO_PIN_2, GPIO_POW_FALLING_EDGE);
    #else //REMOTE_CONTROL_IT
    /* Setup GPIO A, C as a falling edge */
    GPIOPowIntTypeSet(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT |
    BSP_KEY_UP | BSP_KEY_DOWN, GPIO_POW_FALLING_EDGE);
    GPIOPowIntTypeSet(BSP_KEY_SEL_BASE, BSP_KEY_SELECT, GPIO_POW_FALLING_EDGE);
    #endif //REMOTE_CONTROL_IT
    }

    void SysCtrlPowIntEnableSetting(void)
    {
    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntEnable(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ) );
    GPIOPowIntEnable( GPIO_D_BASE, GPIO_PIN_2 );
    #else //REMOTE_CONTROL_IT
    GPIOPowIntEnable(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT | BSP_KEY_UP |
    BSP_KEY_DOWN);
    GPIOPowIntEnable(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);
    #endif //REMOTE_CONTROL_IT
    }

    void SysCtrlPowIntDisableSetting(void)
    {
    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntDisable(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ) );
    GPIOPowIntDisable( GPIO_D_BASE, GPIO_PIN_2 );
    #else //REMOTE_CONTROL_IT
    GPIOPowIntDisable(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT | BSP_KEY_UP |
    BSP_KEY_DOWN);
    GPIOPowIntDisable(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);
    #endif //REMOTE_CONTROL_IT
    }

    void SysCtrlPowIntClear(void)
    {
    #if defined ( REMOTE_CONTROL_IT )
    GPIOPowIntClear(GPIO_C_BASE, ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
    GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ) );
    GPIOPowIntClear( GPIO_D_BASE, GPIO_PIN_2 );
    #else //REMOTE_CONTROL_IT
    GPIOPowIntClear(BSP_KEY_DIR_BASE, BSP_KEY_LEFT | BSP_KEY_RIGHT | BSP_KEY_UP |
    BSP_KEY_DOWN);
    GPIOPowIntClear(BSP_KEY_SEL_BASE,BSP_KEY_SELECT);
    #endif //REMOTE_CONTROL_IT
    }
  • DanO,
    I am glad to hear that you have progressed significantly.

    Can you treat the IO's the same as the hal_key IO's in the sample apps provided. You will need to change hal_key.c to use the GPIO's you intend to use. Re-enable HAL_KEY define and (as you mentioned above) change onboardKeyIntEnable to HAL_KEY_INTERRUPT_ENABLE. This should then be running the way we tested it.

    Regards,
    TC.
  • Hi TC,

    Ok thanks for the suggestions. I have been attempting to change HAL_KEY.c all of today actually. I've almost got it to work, but there is a little problem, perhaps you could help? ...

    I have tried to replicate the code to suit 8 inputs instead of 4, such that all 8 of port C's IO is used. When I test it, only the original button-designated IO of port C trigger the interrupt system. I do not use the SmartRF06EB's buttons, I have used the various breakout headers with bridging wires, etc, to simulate my scenario.

    It seems like the other IO have not been registered to interrupt. So, the problem seems to be with the function called
    bspKeyIntEnable( BSP_KEY_ALL );

    I changed BSP_KEY_ALL as follows ...

    #define BSP_KEY_ALL ( BSP_KEY_1| \
    BSP_KEY_2| \
    BSP_KEY_3| \
    BSP_KEY_4| \
    BSP_KEY_5| \
    BSP_KEY_6| \
    BSP_KEY_7| \
    BSP_KEY_8 ) //!< Bitmask of all keys

    I defined each BSP_KEY_x as ...

    #define BSP_KEY_DIR_BASE GPIO_C_BASE //!< Base for keys
    #define BSP_KEY_SEL_BASE GPIO_D_BASE //!< Base for Select (Mode)
    #define BSP_KEY_1 GPIO_PIN_0 //!< PC0
    #define BSP_KEY_2 GPIO_PIN_1 //!< PC1
    #define BSP_KEY_3 GPIO_PIN_2 //!< PC2
    #define BSP_KEY_4 GPIO_PIN_3 //!< PC3
    #define BSP_KEY_5 GPIO_PIN_4 //!< PA4
    #define BSP_KEY_6 GPIO_PIN_5 //!< PC5
    #define BSP_KEY_7 GPIO_PIN_6 //!< PC6
    #define BSP_KEY_8 GPIO_PIN_7 //!< PC7

    All of these original defines are found in bsp.h

    I cannot find the function code for bspKeyIntEnable(...), I assume that its in a library file, perhaps you know which one?

    Any suggestions are welcome. Thanks again for your time.

    Regards, DanO.
  • Hi TC & others,

    I seem to have solved my problems.

    I ended up not using HAL_KEY.c, and instead made my own ISR. The problem is that HAL_KEY uses many of the bsp... functions, which are all written in the bsp library, and are set up just for the 5 buttons, and so if you want to have a different button number or layout, you'd have to change the library. As I was not wanting to do this, I reverted to having my own ISR.

    As far as power control was concerned, I had to keep the changes that I made to hal_sys_crtl.c ( see post: Thu, Mar 5 2015 4:16 PM), but this was easy enough to do and refine.

    I have learned the following important things when attempting to use one's own interrupt system and get maximum power saving with the CC2538 running ZStack:

    In the ISR, SysCtrlPowIntClear() must be called right after disabling and clearing the interrupt flags.

    CLEAR_SLEEP_MODE() should be called before handling is started.

    ALLOW_SLEEP_MODE() should be called after handling is completed.

    In my particular case, I had an ISR for portC and port D. To avoid switch-bounce and let the inputs settle, I would begin a timer within each ISR, so that only after 40ms would the actual handling begin.

    Enable IOC_OVERRIDE_PUE on all IO that are not being used. Also define those IO as Inputs. Be careful not to interfere with the outputs for the LCD and LED's if you are using those systems!

    Place a breakpoint on SysCtrlDeepSleep() within halSetSleepMode() to ensure that it really is going into deep sleep.

    For maximum power saving, as many as possible of the jumpers on the SmartRF06EB should be removed, thus disabling all the systems. The debug jumpers (P408) should also be removed.

    Powersave Mode 2 gets enabled after as much as a few minutes, but when it is enabled, I got about 1.5 uA current consumption. The button interrupt system that I had was a normally-high setup, and this seemed to work well .

    I have not yet fully tested my system, more posts may follow, please add any comments that might help.