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.

TM4C1231 Hibernate Wake from RTC match not always working

It RTC match wake-up can work for hundreds of times in row then inexplicably stop waking up. It will always wake from a low on the wake pin.
The hardware has the VBAT pin tied directly to the VDDA - VDD4 pins and set to 3.3V, The 3.3V power supply is always on.

The HIB pin is pulled up and can be monitored to verify that the processor is in hibernation.

Please let me know what am I doing wrong, if anything?

Thanks

Here's the power-on code: ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  UINT32 ui32Status = 0;
  RTC_time_t timeDate, timeDateTst;
  volatile timeStamp_t timeStamp;


  // Check to see if Hibernation module is already active, which could mean
  // that the processor is waking from a hibernation.
  if( ROM_HibernateIsActive() )
  {
    // Read the status bits to see what caused the wake.
    // Clear the wake source so that the device can be put into hibernation again.
    ui32Status = ROM_HibernateIntStatus( 0 );         // Get raw interrupt status
    ROM_HibernateIntClear( ui32Status );

    if( ui32Status & HIBERNATE_INT_RTC_MATCH_0 )      // Wake was due to RTC match.
    {
      INFO( "Wake Due To: RTC TIMEOUT" );
    }
    else if( ui32Status & HIBERNATE_INT_RESET_WAKE )  // Wake was due to Sys Reset
    {
      INFO( "Wake Due To: RESET" );
    }
    else if( ui32Status & HIBERNATE_INT_PIN_WAKE )    // Wake was due to the External Wake pin.
    {
      INFO( "Wake Due To: WAKE PIN" );
    }
    else if( ui32Status & HIBERNATE_INT_GPIO_WAKE )   // Wake was due to GPIO wake.
    {
      INFO( "Wake Due To: GPIO WAKE" );
    }
  }
  else  // Hibernation module not active, so set it up
  {
    ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_HIBERNATE );
    // Configure the module clock source.
    ROM_HibernateEnableExpClk( ROM_SysCtlClockGet() );
    ROM_HibernateClockConfig( HIBERNATE_OSC_HIGHDRIVE );
    vTaskDelay( MS_TO_TICKS(1500) );          // Allow time for the crystal to power up.
    ROM_HibernateRTCEnable();                 // Enable RTC mode.
    HWREG( HIB_CTL ) |= HIB_CTL_VDD3ON;
    while( !(HWREG(HIB_CTL) & HIB_CTL_WRC) ); // Wait until the write complete bit is set.
    INFO( "Hib Module Initialized" );
  }
  // If the wake was not due to the above sources, then it was a system reset.
  if( !(ui32Status & (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0 |
                      HIBERNATE_INT_GPIO_WAKE | HIBERNATE_INT_RESET_WAKE)) )
  {
    INFO( "Wake Due To: SYSTEM RESET" );  // This was a system restart, not wake from hibernation.
  }
  ROM_HibernateDataGet( (uint32_t *)&hibData, HIB_DATA_MAX_NUM_WORDS ); // Read the battery backed memory

Here's the hibernation entry code: -------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void setRTCIntervalWakeupAlarm( UINT32 wakeUpSeconds )
{

  timeStamp_t RTCSeconds, matchSeconds; // (NOTE: timeStamp_t is a UINT32)
  UINT32 ui32Status;


  // Save hibernation data in battery backed RAM for next power-on wake
  ROM_HibernateDataSet( (uint32_t *)&hibData, HIB_DATA_MAX_NUM_WORDS );

  RTCSeconds   = RTC_get_timeStamp();
  matchSeconds = RTCSeconds + wakeUpSeconds;

  HibernateRTCMatchSet( 0, matchSeconds );    // Set the match 0 register for wakeUpSeconds seconds from now.

  ui32Status = ROM_HibernateIntStatus( 0 );   // Clear any pending status
  ROM_HibernateIntClear( ui32Status );

  while( HibernateRTCMatchGet(0) != matchSeconds )
  {
    HibernateRTCMatchSet( 0, matchSeconds );  // Set the match 0 register for wakeUpSeconds seconds from now.
    INFO( "ERROR: RTCMatchGet" );
  }

  HibernateWakeSet( HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC );

  while( (HibernateWakeGet() & (HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC)) != (HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC) )
  {
    HibernateWakeSet( HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC );
    INFO( "ERROR: RTCWakeGet" );
  }

  INFO( "CurrTime = %lu RTCMatchSet = %lu", RTCSeconds, matchSeconds );
  vTaskDelay( MS_TO_TICKS(50) );            // Wait for INFO message to print out

  IntMasterDisable();

  HWREG( HIB_CTL ) |= HIB_CTL_HIBREQ;       // Request hibernation.

  while( TRUE );

}

//------------------------------------------------------------------------------------------------------------------------
timeStamp_t RTC_get_timeStamp( void )
{
  timeStamp_t ulRTC1, ulRTC2, ulRTCSS1, ulRTCSS2;

  IntMasterDisable();

  do
  {
    ulRTC1   = HWREG( HIB_RTCC );
    ulRTCSS1 = HWREG( HIB_RTCSS );
    ulRTCSS2 = HWREG( HIB_RTCSS );
    ulRTC2   = HWREG( HIB_RTCC );
  } while( (ulRTC1 != ulRTC2) || (ulRTCSS1 != ulRTCSS2) );

  IntMasterEnable();

  return( ulRTC2 );                               // Return current time stamp
}

  • Here's a printout of the relevant registers prior to going into hibernation, and when it never woke up.

    49 PWRMGM: Enter Interval Hibernate State = 11 Seconds
    49 PWRMGM: HibernateWakeGet = 0x18 HIB_CTL = 0x80022159
    49 PWRMGM: CurrTime = 510321398 RTCMatchSet = 510321409 

  • As you can see everything is set up correctly for it to wake up on the RTC match, but it never did.
  • I've updated the hibernation entry routine to include setting the RTC sub second register match to it still not not occasionally work.
    Here's the print out:
    31 PWRMGM: Enter Interval Hibernate State = 8 Seconds
    31 PWRMGM: HIB_CTL = 0x80022159
    31 PWRMGM: CurrTime = 510324025 RTCMatchSet = 510324033

    As you can see all the registers are set up correctly, but it never woke up, it worked for many multiple times in row before this.

    void setRTCIntervalWakeupAlarm( UINT32 wakeUpSeconds )
    {
    UINT32 ui32Status;

    // Save hibernation data in battery backed RAM for next power-on wake
    ROM_HibernateDataSet( (uint32_t *)&hibData, HIB_DATA_MAX_NUM_WORDS );

    ui32Status = ROM_HibernateIntStatus( 0 ); // Clear any pending status
    ROM_HibernateIntClear( ui32Status );

    HibernateWakeSet( HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC );

    INFO( "HIB_CTL = 0x%X", HWREG(HIB_CTL) );

    HibernateRTCMatchSet( 0, RTC_get_timeStamp() + wakeUpSeconds ); // Set the match 0 register for wakeUpSeconds seconds from now.

    INFO( "CurrTime = %lu RTCMatchSet = %lu", RTC_get_timeStamp(), HibernateRTCMatchGet(0) );
    vTaskDelay( MS_TO_TICKS(50) ); // Wait for INFO message to print out

    IntMasterDisable();
    HibernateRTCSSMatchSet( 0, HibernateRTCSSMatchGet(0) );

    HWREG( HIB_CTL ) |= HIB_CTL_HIBREQ; // Request hibernation.

    while( TRUE ); // Need a loop here to wait for the power to be removed.
    }
  • Hello Frank,

    Can you have a look at this thread? It sounds very similar to the issue you are facing.

    e2e.ti.com/.../962788
  • Yes, adding the following lines fixed the problem. I can't tell you how many hours I've spent on this bug. Please make it clearer in the errata what the fix is.

    Thanks

    HibernateRTCTrimSet (0x7FFF);
    HibernateIntDisable (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_LOW_BAT | HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_WR_COMPLETE);