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.

TM4C123AH6PM: Deep sleep fails to wake up occasionally - GPIO

Part Number: TM4C123AH6PM
Other Parts Discussed in Thread: TM4C123

Greetings,

We have a project where a board with a TM4C123 is permanently powered. To avoid draining the battery, the strategy is to put it down to DeepSleep (it won't really be doing ANYTHING, it just has to be awaken by a pulse in a specific GPIO). It is not HIBERNATE, because the wake up pulse was not routed to a convenient hibernate GPIO, so Deep Sleep was the best we could come up with. When system wakes up from hibernation, it simply resets so that we have a fully fresh state.

It works quite well, almost always... However, occasionally the board will not wake up, even though the pulse signal is confirmedly there.

We did look at some posts regarding errata HIB#01 and tried to add some code from those posts, but I honestly did not fully understand the proposed solution, the adequate code nor am I even sure that the cause is the said errata issue.

/*
 * Puts the system in DeepSleep mode
 * This function will only exit when an interrupt caused by EXP_GPIO_PIN is triggered
 */
void TaskSystemDeepSleep(void)
{
    /* Now enable the interrupt for the wake up pin */
    GPIOIntRegister(EXP_GPIO_BASE, TaskDeepSleepISR);
    GPIOIntTypeSet(EXP_GPIO_BASE, EXP_GPIO_PIN, GPIO_RISING_EDGE);
    IntEnable(EXP_GPIO_INT);
    GPIOIntClear(EXP_GPIO_BASE, 0xFF);
    GPIOIntEnable(EXP_GPIO_BASE, EXP_GPIO_PIN);

    /* Disabled Peripherals */
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_ADC0);
	    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_ADC1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_CAN0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_CAN1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_COMP0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_EMAC0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_EPHY0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_EPI0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOC);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOG);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOH);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOJ);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_HIBERNATE);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_CCM0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_EEPROM0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_FAN0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_FAN1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOK);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOL);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOM);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPION);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOP);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOQ);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOR);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOS);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_GPIOT);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C2);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C3);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C4);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C5);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C6);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C7);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C8);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_I2C9);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_LCD0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_ONEWIRE0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_PWM0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_PWM1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_QEI0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_QEI1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_SSI1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_SSI2);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_SSI3);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER2);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER3);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER4);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER5);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER6);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_TIMER7);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART2);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART3);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART4);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART5);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART6);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UART7);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_UDMA);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_USB0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WDOG0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WDOG1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WTIMER0);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WTIMER1);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WTIMER2);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WTIMER3);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WTIMER4);
    SysCtlPeripheralDeepSleepDisable(SYSCTL_PERIPH_WTIMER5);

    /* Enabled Peripherals */
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOA);		// Should not be needed but just in case...
    SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_GPIOA);

    /*
     * There is a HW bug regarding deep sleep. See these posts:
     * https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/606846/tm4c123ge6pm-tm4c123gxl-deep-sleep-mode-issue
     * https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/275336/rtc-will-sometimes-miss-waking-from-hibernate/964156#964156
     */

    /* DeepSleep configurations */
    SysCtlPeripheralClockGating(true);
    /* Function below is for TM4C123 devices */
    SysCtlDeepSleepClockSet(SYSCTL_DSLP_DIV_1 | SYSCTL_DSLP_OSC_INT30 | SYSCTL_DSLP_PIOSC_PD);
    /* Function below is for TM4C129 devices */
    // SysCtlDeepSleepClockConfigSet(1, (SYSCTL_LDO_SLEEP|SYSCTL_TEMP_LOW_POWER|SYSCTL_FLASH_LOW_POWER|SYSCTL_SRAM_LOW_POWER));
    SysCtlDeepSleepPowerSet(SYSCTL_LDO_SLEEP|SYSCTL_TEMP_LOW_POWER|SYSCTL_FLASH_LOW_POWER|SYSCTL_SRAM_LOW_POWER);
    SysCtlLDODeepSleepSet(SYSCTL_LDO_0_90V);        // Select LDO to Scale to 0.9V in Deep Sleep

    while (!canWakeUp)
    {
        HWREG(HIB_CTL) |= HIB_CTL_CLK32EN | HIB_CTL_OSCDRV;
        SysCtlDelay(SYSTEM_CLOCK_HZ/2);	// Wait for 1500 ms
        HibernateRTCSet (0);
    	HibernateRTCTrimSet (0x7FFF);
        SysCtlDeepSleep();
    }
    /* Code will never come here unless the interrupt was caused by EXP_GPIO_PIN */
	
	HWREG(NVIC_APINT) = (NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ);
}

Above is the function that configures and initiates the DeepSleep.

/*
 * Specific ISR for deep sleep mode, makes sure that only the EXP_GPIO pin wakes the board up
 */
void TaskDeepSleepISR(void)
{
    uint32_t intFlags;
    intFlags = GPIOIntStatus(EXP_GPIO_BASE, false);     // false means we are concerned about unmasked interrupts
    GPIOIntClear(EXP_GPIO_BASE, intFlags);

    if (intFlags & EXP_GPIO_PIN)
    {
        canWakeUp = true;
    }
}

Then we have the associated ISR. The idea is to have the GPIO trigger an interrupt, wake up the system into the ISR, check that the cause was the expected pin and set canWakeUp, which will the lead code to reset.

Any ideas of how to debug and solve this?

Cheers

Bruno

  • Hi Bruno,

      Glad to hear from you again! It's been a while. 

      I have read your post and the other two posts you referred that were answered by Chester. However, at the moment I don't really have an answer for your question. I also don't understand why would the workaround for HIB#1 will have any effects on DeepSleep since you are not even using RTC as I understand. You are using just the DeepSleep mode. 

      When you said it works most of the time, can you elaborate in terms of percentage when it will fail to wake up?

      Will additional wake pulses wake up the device?

      Is this problem repeatable on all the boards you have?

      Not that I know if the cause is due to some of the settings in your below configuration. I think you are trying to get to the settings resulting in lowest deepsleep current consumption. For experiment, I wonder if you change some of these settings, will it make any difference?

    SysCtlDeepSleepClockSet(SYSCTL_DSLP_DIV_1 | SYSCTL_DSLP_OSC_INT30 | SYSCTL_DSLP_PIOSC_PD);
    /* Function below is for TM4C129 devices */
    // SysCtlDeepSleepClockConfigSet(1, (SYSCTL_LDO_SLEEP|SYSCTL_TEMP_LOW_POWER|SYSCTL_FLASH_LOW_POWER|SYSCTL_SRAM_LOW_POWER));
    SysCtlDeepSleepPowerSet(SYSCTL_LDO_SLEEP|SYSCTL_TEMP_LOW_POWER|SYSCTL_FLASH_LOW_POWER|SYSCTL_SRAM_LOW_POWER);
    SysCtlLDODeepSleepSet(SYSCTL_LDO_0_90V);

        

  • Hey Charles, thanks for the comment and for the quick reply!

    Yes, life's been a bit too hectic, I can't even dream of enjoying some forum time except for emergencies!

    Anyway, following your suggestion:

    - I removed all those things related to Hibernate (actually that code I posted would crash unless the hibernate module had been enabled first).

    - Increased the LDO voltage from 0.90 to 1.00V.

    That seemed to have solved the issue.

    As for your other questions, additional wake pulses would not wake up the device (the signal is actually a 2 Hz continuous square coming in when the "rest" of the system is ON). We have not tested in other boards. And it would fail after some 6-8 attempts...

    Anyway, I can say your suggestion was key for solving - thanks again.

    Cheers

  • Too early to celebrate.
    A couple of hours later it failed to wake up once again...  :(

    Adding to injury, it is a sealed enclosure with no easy access to the reset button.

    I'll raise the LDO a bit more and see if it makes any difference.

  • Hi Bruno,

      When you raise the LDO voltage to 1.0V and it runs some hours, it kind of tell me the power supply at 0.9V is either too low or marginal for the transistor to work. I hope you can raise the LDO to higher than 1.08V per datasheet. 

  • I'm pretty sure I've just replied on another computer, but the message is not here...
    Anyway, I've raised the LDO to the maximum setting of 1.2V (we don't really care that much for low power at this stage)
    Tested some 40 times with perfect results. But after leaving the board deep asleep for a couple of hours, again it won't wake up...

  • Hi Bruno,

     Any more updates?

  • Hi Charles,

    Last attempt was having the LDO at 1.2V, which was the highest macro I found around those parameters. That still did not solve the issue (again this morning it would not wake up - but barely I could as well...)

    I was just reading about the LDO adjustment: the Tivaware user guide says the device has an internal LDO ... with default setting of 2.5V. I am confused as why the SysCtlLDODeepSleepSet parameters are around 1V, still haven't looked it up.

    Also, I am thinking of enabling and implementing an interrupt routine to service SysClt events such as LDO failure, oscillator failure, etc, to maybe try a full reset if something on that line occurs... But haven't got my hands on it, will try to find time later today.

    Any suggestions and comments are highly appreciated.  ;)