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.

TM4C1290NCPDT: Hibernation module / wake pin behavior migrating from TM4C123G to TM4C1290

Part Number: TM4C1290NCPDT
Other Parts Discussed in Thread: TM4C123GH6PM, , EK-TM4C1294XL

Tool/software:

We have a design that was previously implemented using a TM4C123GH6PM, which we are now migrating to a TM4C1290NCPDT. 

In our system, the hibernation module powers the circuit off by disabling regulators using its /HIB output.  The code instructs the system to hibernate on command, and it can be woken by timer or /WAKE pin.  /WAKE is pulled up to the coin cell that powers the hibernation module (VBAT) by a 1M pullup.  I know this is a very weak pullup, but we are doing very low power operations and trying to save battery.  The system also wakes on serial Rx because /WAKE is pulled to ground by a mosfet circuit with Rx on the gate.

The following screenshot shows expected behavior, using the TM4C123GH6PM.  Ch1 (yellow) = VBAT (coin cell), Ch2 (blue) = /WAKE, Ch3 (pink) = /HIB, Ch4 (green) = 3.3V main power to processor.

Since /WAKE is tied to Rx, the command to hibernate can be seen in the /WAKE line.  Around 250ms later, /HIB goes low, then main power goes away as the regulator is disabled.

On the TM4C1290, the same behavior looks like:

The system wakes up immediately after it goes to sleep.

Zooming in on the behavior around when /HIB goes low (to turn off the regulator),

It seems like the /WAKE line is sagging. I wonder if somewhere internally on the TM4C129, /WAKE is affected by the main power, since I know there were some changes in behavior surrounding the main power takeover of the Hibernation module while awake.

Even though it's not ideal for our current consumption, I strengthened the pullups on /WAKE line.  Using a 10k pullup instead of 1M, I got the following waveform:

(I also got some different strange behavior using a 100k pullup, but the above waveform more clearly indicates that sag on the /WAKE pin is probably not what's causing the system to wake up.)

I do have a version of this circuit where the regulator is not disabled by /HIB, so main power stays present even after the system hibernates.  It's also different in a few other ways (eg no wake on Rx).  This version hibernates properly and there is no sag on /WAKE, even with the 1M pullup.  However, none of the ways it's different stand out to me as something that could make the difference.  The idea of /WAKE sagging below threshold due to being affected by main power seems to be disproved by the above scope trace (also, it never even got that low).

I'm looking for ideas on what might be causing our system to wake up immediately after hibernation.  I'm not sure if the behavior of the /WAKE line is a clue or not, but I would prefer to use the weakest pullups I can to save power.  The circuitry and code around the hibernation module should be pretty much the same as the working TM4C123 board.  I looked through some of the differences between the TM4C123 and TM4C129, and while I do, e.g. ground some of the GPIOs that can be configured to Wake, they should not be configured in the software to function as /WAKE.  

Thanks!

  • To add more clues, the clock is not maintained through hibernation; it resets after the sleep-wake event.  I have probed the VBAT pin on the uC and confirmed it is powered.  We are using an external oscillator on XOSC0, same as for our working TM4C123 board.

    The code does check for cause of wakeup.  To the best of my understanding (I did not write the code), the cause of wakeup is identified as POR due to MAP_HibernateIsActive() (a macro for the hibernate API) being False.  It seems to me that there is some software issue such that things that should be maintained through hibernation (eg clock, configuration?) are not.  Are there any differences in how we need to set up the hibernation module, between the TM4C123 and TM4C129?  I did not find any differences from comparing the data sheets.

  • Hi,

      - Can you reproduce the problem (using your existing code) on a EK-TM4C1294XL LaunchPad?

      - Can you reproduce the problem by running the TM4C129 hibernate examples at:

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\hibernate

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\hibernate_calendar

      By running your code on a LaunchPad and the stock TivaWare hibernate examples on your custom board, I hope you can find some clues as to what happens. 

     

      Please also refer to TM4C129 for a reference circuit for hibernate mode. 

  • Hi Charles,

    Thanks for your suggestions.  I started by trying to get the TM4C129 hibernate examples working with our hardware.

    With some modifications to accommodate differences (eg different system crystal), the hibernate_calendar is mostly able to work.  When asleep, the coin cell is parasitically powering a bit of the main power, but I suspect this might be due to some features on the Launchpad that are implemented in the code and I didn't remove. 

    The hibernate example is having more issues.  Behavior is inconsistent and seems to possibly depend on previously loaded code.  I was wondering if this example is missing a call to HibernateWakeSet().  I found the ROM User's Guide which says that a wake source must be configured with HibernateWakeSet() before HibernateRequest() is called.  I didn't find a call to HibernateWakeSet() in my Tivaware 2.2.0.295 version of the TM4C1294XL hibernate example.  My example does not sleep at all until I call HibernateWakeSet() adding RTC as the wake source.

    After adding a call to HibernateWakeSet(), the example sleeps and wakes but is still not working properly because the call to HibernateIntStatus() in the interrupt function is not returning the right value.  Based on my understanding, this function returns a flag that indicates source of interrupt.  The raw return of HibernateIntStatus(0) in my code as an integer is 16 (I also saw 17 once but the circumstances under which this happened were very confusing). I found in some documentation that HIBERNATE_INT_RTC_MATCH_0 flag would be 0x1, and HIBERNATE_INT_WR_COMPLETE is the HIBERNATE_INT flag with value 0x10. 

    Although I'm not sure I'm interpreting everything correctly, I have actually seen the HIBERNATE_INT_WR_COMPLETE flag before.  It was showing in our own code (that wakes immediately after hibernation) as the cause of wake.  We were a bit confused by it and then it got written out of the code.  I can't find documentation on what this wake source means or when it shows up.  Do you have any more information on this flag?

    Regarding the circuit, I also noticed that the circuit for using a dedicated oscillator (our use case), which shows up in the device sheet right after the one you posted, has a 1M pullup.  So I would imagine that our 1M pullup should be ok as well.

    I actually found another E2E post that seemed to have a similar problem, but I didn't see a solution in this thread.

    I will continue with trying to compare our code with the working hibernate_calendar code, but in the meantime, if you have any information on the HIBERNATE_INT_WR_COMPLETE flag or any other ideas, please let me know.  Thanks!

  • Hi Irene,

    I will continue with trying to compare our code with the working hibernate_calendar code,

    Do you have any update?

    if you have any information on the HIBERNATE_INT_WR_COMPLETE flag or any other ideas, please let me know.

    Sorry for the late reply. This is to enable an interrupt when the Hibernate module is ready to take a write access from the CPU since the CPU and the Hibernate module are not synchronous to each other as they are on different clock domains. 

    Register Access Timing
    Because the Hibernation module has an independent clocking domain, hibernation registers must
    be written only with a timing gap between accesses. The delay time is tHIB_REG_ACCESS, therefore
    software must guarantee that this delay is inserted between back-to-back writes to Hibernation
    registers or between a write followed by a read. The WC interrupt in the HIBMIS register can be used
    to notify the application when the Hibernation modules registers can be accessed. Alternatively,
    software may make use of the WRC bit in the Hibernation Control (HIBCTL) register to ensure that
    the required timing gap has elapsed. This bit is cleared on a write operation and set once the write
    completes, indicating to software that another write or read may be started safely. Software should
    poll HIBCTL for WRC=1 prior to accessing any hibernation register.

  • Hi Charles,

    Thanks for the information.  My colleague has come up with a fix and it seems to have solved our problem.  (I still can't get the hibernate example to work properly, so it may have a different set of issues when paired with our hardware, but it doesn't really matter if we can solve our main problem).

    My colleague says: 

    There is an error in Tivaware's HibernateWakeSet that turns on HIB_CTL_VDD3ON. I bet if that bit is set and VDD fails (because we turn it off) it triggers the HIB to reset like a POR reset. Or maybe we brown something out since when VDD3ON is set the gpios can still source some current. not sure.

    The bug is in hibernate.c line 453, it tries to test if ui32WakeFlags is set to HIBERNATE_WAKE_RESET or HIBERNATE_WAKE_GPIO, but since it does it bitwise instead of by value it incorrectly resolves as true if HIBERNATE_WAKE_PIN is set, so then it enables HIB_CTL_VDD3ON, since HIB_CTL_VDD3ON is required for HIBERNATE_WAKE_RESET (nRESET based wake).

    Here is the function in Tivaware hibernate.c that he is referring to:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //*****************************************************************************
    //
    //! Configures the wake conditions for the Hibernation module.
    //!
    //! \param ui32WakeFlags specifies which conditions should be used for waking.
    //!
    //! This function enables the conditions under which the Hibernation module
    //! wakes. The \e ui32WakeFlags parameter is the logical OR of any combination
    //! of the following:
    //!
    //! - \b HIBERNATE_WAKE_PIN - wake when the external wake pin is asserted.
    //! - \b HIBERNATE_WAKE_RTC - wake when the RTC match occurs.
    //! - \b HIBERNATE_WAKE_LOW_BAT - wake from hibernate due to a low-battery
    //! level being detected.
    //! - \b HIBERNATE_WAKE_GPIO - wake when a GPIO pin is asserted.
    //! - \b HIBERNATE_WAKE_RESET - wake when a reset pin is asserted.
    //!
    //! If the \b HIBERNATE_WAKE_GPIO flag is set, then one of the GPIO
    //! configuration functions GPIOPinTypeWakeHigh() or GPIOPinTypeWakeLow() must
    //! be called to properly configure and enable a GPIO as a wake source for
    //! hibernation.
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    He writes his own function that is called in place of HibernateWakeSet().  To help anyone else having this problem, I'll post it here (note that our wake sources are RTC and wake pin).

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void wait_for_hib_wrc()
    {
    while(!(HWREG(HIB_CTL) & HIB_CTL_WRC))
    {
    }
    }
    // wake_flags may be bit-or of HIB_CTL_RTCWEN, HIB_CTL_PINWEN, HIB_CTL_BATWKEN
    void hib_set_wake_source(const uint32_t wake_flags)
    {
    uint32_t wake_mask = 0;
    uint32_t temp = 0;
    wake_mask = HIB_CTL_RTCWEN | HIB_CTL_PINWEN | HIB_CTL_BATWKEN;
    temp = HWREG(HIB_CTL);
    temp &= (~wake_mask);
    temp |= (wake_flags & wake_mask);
    HWREG(HIB_CTL) = temp;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    After replacing our calls to MAP_HibernateWakeSet() with this new function, our board is able to hibernate properly.

    Thanks for your help on this,

    Irene