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 low power issues

Other Parts Discussed in Thread: CC2538, TIMAC, CC2538-SW

Good morning everyone,

I'm facing problems with the low power management of CC2538 since a long while and would like to see if anyone can give me tips on the topic. Essentially I'm not able to control the way the module exit low power modes. I'd like to wake it up with a GPIO but it keeps caring only about the sleep timer.

So, the setup is a custom hardware based on CC2538 with both 32 MHz and 32 KHz quartz integrated on board and TIMAC 1.5 firmware.

The modifications I did on the TIMAC 1.5 are the following:

  • disabled key module
  • disabled LED module
  • initialized the GPIO I'd like to use to wake the chip up, using the following code in HAL_BOARD_COMMON_INIT():
    GPIOPinTypeGPIOInput(GPIO_A_BASE, GPIO_PIN_5);
    IOCPadConfigSet(GPIO_A_BASE, GPIO_PIN_5, IOC_OVERRIDE_PUE);
  • modified in hal_sys_ctrl.c every function involving the POW interrupt for the keys to my gpio (GPIO_A_BASE, GPIO_PIN_5). Something like this:
    GPIOPowIntTypeSet(GPIO_A_BASE, GPIO_PIN_5, GPIO_POW_FALLING_EDGE);
  • ensured that GPIOIntWakeupEnable(GPIO_IWE_PORT_A); is there
  • inserted MSA_PowerMgr(TRUE); before OSAL_START_SYSTEM(); in order to trigger sleep modes

Now, while debugging, all the registers associated to the port and wake up system are correctly set (PORT_A_PI_IEN, SYS_CTRL_IWE and port settings). I can read the pin correctly in a variable, etc. Moving the GPIO still can't wake the device up, though. Pausing the debugger make the mcu exit the sleep condition and I can see that PORT_A_IRQ_DETECT_ACK has seen the edge also but for some reason still didn't wake the device up.

Am I missing something big here? Is there something particular in the closed source bsp key library that make the key work properly?

I even tryed enabling also the normal interrupt for the gpio in addition to the wake up one but without success.

Thanks in advance

  • Hi Augusto,

    I think you are missing the call to enable the right bits in the power-up interrupt enable register.

    This is done through the call to GPIOPowIntEnable() API.

    To see the programming model to configure the GPIO as a source for wakeup interrupt, please check out chapter 7.1 in http://www.ti.com/lit/pdf/swru325

    Please also note that the driverlib code, though integrated in a library in TI-MAC, is provided in clear source here: http://www.ti.com/tool/cc2538-sw

    Thanks,

    TheDarkSide

  • Hi TheDarkSide,

    I've been using the TIMAC structure at first and now I simplified the program to isolate the issue but still without success. I do all the steps of the literature as you can see from the code posted here (project is based on TIMAC):

    int main(void)
    {
      HWREG(NVIC_VTABLE) = HAL_NVIC_ADDR;
      SysCtrlClockStartSetting();
      HAL_CLOCK_STABLE();
      PREFETCH_ENABLE();
      IntAltMapEnable();
      
      // Setup IOs
      GPIODirModeSet(GPIO_A_BASE, GPIO_PIN_5,GPIO_DIR_MODE_IN);
      IOCPadConfigSet(GPIO_A_BASE, GPIO_PIN_5, IOC_OVERRIDE_PUE);
      
      // Setup wakeup
      GPIOIntWakeupEnable(GPIO_IWE_PORT_A);
      GPIOPowIntTypeSet(GPIO_A_BASE, GPIO_PIN_5, GPIO_POW_FALLING_EDGE);
      
      while(TRUE)
      {
        HAL_ENABLE_INTERRUPTS();
        GPIOPowIntClear(GPIO_A_BASE, GPIO_PIN_5);
        GPIOPowIntEnable(GPIO_A_BASE, GPIO_PIN_5);
        
        SysCtrlDeepSleep();
        
        // DEBUG
        {
          uint32_t gpiostate = GPIOPinRead(GPIO_A_BASE, GPIO_PIN_5);
          uint32_t irqdetect = GPIOPowIntStatus(GPIO_A_BASE, TRUE);
          gpiostate = irqdetect; // Place breakpoint here!
        }
        
        GPIOPowIntDisable(GPIO_A_BASE, GPIO_PIN_5);
        HAL_DISABLE_INTERRUPTS();
      }
    }

    At the breakpoint, I check both variables obtaining that the gpio is read correctly and the irq is detected and passes the mask. Also checking the SYS_CTRL_IWE register it can be seen that the port is enabled as a wake up source. Attached the screenshot of the debugging watches.

    The device stays in sleep mode regardless of pressing the switches and the only way to wake it up is to pause the debugger and hit continue again to reach the breakpoint.

    Regards

    Augusto

  • I tried the code on the official SmartRF06 board + CC2538EM and found the same issue.

    To verify this, open the original TIMAC sample project and replace in msa_Main.c the line

    HalLedBlink (HAL_LED_4, 0, 40, 200);

    with

    MSA_PowerMgr(TRUE);

    This way, the device enters sleep right away at startup and a key pressed should wake it up but, as I noticed in the previous tests, it doesn't. The registers seems allright here too (see previous post).

  • Hi  

     I am also working on cc2538 and facing the same issue. Its not waking up from PM1 by any interrupts.

    Have you solved this problem. can u share your remark please?

     

    Thanks in advance,

  • Hi Avira,

    You can refer to sleepmode example in cc2538 foundation firmware. Try it first and see if it works on your CC2538.

  • Hello Augusto,

    There is a known issue that Interrupts may be missed when used as wake up source or wake up interrupts. Which can be the issue in this case. Please see the explanation of the issue below and can you please test with suggested change and let me know if this resolves the issue. 

    For CC2538 the GPIOs have two separate configurations: as generic interrupts, and as power-up interrupts (i.e. wakeup sources from sleep): These are enabled using the registers GPIO_IE and GPIO_PI_IEN respectively. (please see the CC2538 user’s guide:http://www.ti.com/lit/ug/swru319b/swru319b.pdf). The status of each of the interrupt type (i.e. which source triggered the interrupt) is also available separately, via GPIO_MIS for the enabled general interrupts, and GPIO_IRQ_DETECT_ACK for enabled power interrupts. 

    Both type of interrupts triggers the same interrupt handler, which is registered in the interrupt vector. This direct interrupt handler is a single function that is called for all the GPIOs of the same port. This handler, in turn, checks to see which specific GPIO triggered it, and calls a specific handler. 

    In the code, this ‘direct’ interrupt handler for all PortA GPIOs is ioPortAIsr() ( download the source code fromhttp://www.ti.com/tool/cc2538-sw and the project at install-dir\bsp\srf06eb_cc2538\drivers\projects\iar)  you can see the bsp project file io_pin_int.c for this ). To determine the actual GPIO that triggered the interrupt, it reads GPIO_O_MIS (i.e. the indication of the triggered general-interrupts). The issue seems to be that sometimes while the device is asleep, a button-press successfully triggers a power-interrupt, but fails to trigger the respective normal interrupt. So, ioPortAIsr() is called (since triggered by the power-interrupt), but when it checks which GPIO caused the interrupt it sees none. Then it finishes without doing anything, and immediately called again since the power interrupt is never cleared. Pressing the button again at this time will be successfully caught as a general interrupt, and release the loop: ioPortAIsr() will check the sources again, will see this button was pressed, and will call the respective GPIO-specific interrupt handler - in our case interrupt_keybd(), which call SysCtrlPowIntClear() that clears the power-interrupt signal. 

    A minor modification to the deiverlib code is required to resolve this. The respective source code may be downloaded from http://www.ti.com/tool/cc2538-sw. After downloading the source package from the link above, please add to the IAR project all the C files from swrc271a\cc2538_foundation_firmware_1_0_1_0\driverlib\cc2538\source. Please also remove the ‘driverlib’ library from the linker list, in project->options->linker->Library. 

    Then, in gpio.c, modify GPIOPinIntStatus() as follows: 

    GPIOPinIntStatus(uint32_t ui32Port, bool bMasked) 

    { 
        // 
        // Check the arguments. 
        // 
        ASSERT(GPIOBaseValid(ui32Port)); 
     
        // 
        // Return the interrupt status. 
        // 
        if(bMasked) 
        { 
            return(HWREG(ui32Port + GPIO_O_MIS) | GPIOPowIntStatus(ui32Port,bMasked)); 
        } 
        else 
        { 
            return(HWREG(ui32Port + GPIO_O_RIS) | GPIOPowIntStatus(ui32Port, bMasked)); 
        } 
    } 

    Doing these changes should resolve the issue of missed interrupts when the GPIO is used for both power up and normal interrupts.

    Regards,

  • Hello Jain,

    first of all thanks for your support. I tried the modification you said but the problem I face seems to be worst. I tried the sleeptimer demo in CC2538 fundation software and it's working properly in debug mode while it doesn't work as expected in stand alone mode. I get corrupted text on the UART and if I try to reprogram the device (or run in debug mode again) I get unexpected behavior and the debugger fails giving the error "failed to halt CPU" when I try to stop and restart. It needs a lot of retries to get the debugger (J-link) to work again flawless.

    Here is the printout of the UART (3 trials in debug mode, 4 trials detached from the debugger and 1 trial again in debug mode:
    Sleepmode timer
    Timer val = 2008984
    Timer val = 2018985 (after wakeup)
    Sleepmode timer
    Timer val = 2501364
    Timer val = 2511365 (after wakeup)
    Sleepmode timer
    Timer val = 2707852
    Timer val = 2717853 (after wakeup)
    Sleepmode timer
    Timer val = 11
    `3¦?•??…???Š‚š?B
    ™?•??…?•??¥jR?Sleepmode timer
    Timer val = 11
    `3¦?•??…???Š‚š?B
    ™?•??…?•??¥jR?Sleepmode timer
    Timer val = 11
    `3¦?•??…???Š‚š?B
    ™?•??…?•??¥jR?Sleepmode timer
    Timer val = 11
    `3¦?•??…???Š‚š?B
    ™?•??…?•??¥jR?Sleepmode timer
    Timer val = 352917
    `3¦?•??…???š?’?Š??B
    ™?•??…?•??¥jR?
    The same behavior appears on multiple devices and boards.
    Regards
    Augusto
  • Hi All, I know that its 7 months later, but did you all come right? I have been using CC2538 ZStack with low power modes, and have been mostly successful.

    Regards, DanO.