Hello everyone,
I'm having trouble enabling the hibernation module on my TM4C123GXL. This the following code I'm executing:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_hibernate.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/hibernate.h"
uint32_t g_sysclk;
volatile uint32_t g_ms = 0;
static volatile uint8_t hib_stat_track = 0;
static __interrupt void systick_isr(void) {
++g_ms;
}
void init_main(void) {
SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ); // xtal > 10 MHz
SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_XTAL_16MHZ | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN);
g_sysclk = 40000000;
const uint32_t systick_clocks = g_sysclk / 1000;
SysTickPeriodSet(systick_clocks);
SysTickIntRegister(systick_isr);
SysTickIntEnable();
SysTickEnable();
}
void systick_delay(uint32_t ms_delay) {
ms_delay += g_ms;
while(g_ms <= ms_delay) {
}
}
int main(void) {
uint32_t hibernation_status = 0;
init_main();
SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
hibernation_status = HibernateIntStatus(0);
// the following function will return true if the MCU is just
// waking up from hibernation
if(HibernateIsActive()) {
HibernateIntClear(hibernation_status);
if(hibernation_status & HIBERNATE_INT_RTC_MATCH_0) {
hib_stat_track=1;
} else if(hibernation_status & HIBERNATE_INT_RESET_WAKE){
hib_stat_track=2;
} else if(hibernation_status & HIBERNATE_INT_LOW_BAT) {
hib_stat_track=3;
} else {
hib_stat_track=4;
}
} else {
hib_stat_track=5;
}
// hibernate module should be enabled again even if it was already enabled,
// because it "also initializes some timing parameters".
HibernateEnableExpClk(g_sysclk);
// time to check if the hibernation module needs to have its
// clock source reconfigured
if(!(hibernation_status & HIBERNATE_INT_RTC_MATCH_0)) {
// set the module source
// "HIBERNATE_OSC_HIGHDRIVE specifies a higher drive strength
// when a 24-pF filter capacitor is used with a crystal."
HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE);
// let the Hibernation Module crystal start up!
systick_delay(15);
}
// enable the RTC
HibernateRTCEnable();
// reset the RTC to 0
HibernateRTCSet(0);
// set RTC match index 0 to 10 seconds in the future
HibernateRTCMatchSet(0, 10);
// tell the module to abort when the battery is low!
//HibernateLowBatSet(HIBERNATE_LOW_BAT_ABORT | HIBERNATE_LOW_BAT_2_5V);
// tell the hibernation module to wakeup on a RTC match
HibernateWakeSet(HIBERNATE_WAKE_RTC);
// now we're ready to request hibernation!
HibernateRequest();
// Errata HIB#03 work-around
while((HWREG(HIB_CTL)&HIB_CTL_CLK32EN)==HIB_CTL_CLK32EN)
{}
// hibernate didnt come into effect, reseting!
SysCtlReset();
while(1) {}
}
(here's a pastebin link incase the formatting doesnt come through: http://pastebin.com/U9RquzfD)
The problem seems to occur right after calling the following line:
HibernateEnableExpClk(g_sysclk);
Following the function into the hibernate.c, the following code is called:
void
HibernateEnableExpClk(uint32_t ui32HibClk)
{
//
// Turn on the clock enable bit.
//
HWREG(HIB_CTL) |= HIB_CTL_CLK32EN;
//
// Wait for write complete following register load (above).
//
_HibernateWriteComplete();
}
Inspecting the HIB_CTL register it seems that the HIB_CTL_CLK32EN is NOT asserted. This seemingly appears to happen randomly. Sometimes after a few power cycles, the module wakes up with the bit set as expected.
However, when the line called to assert the HIB_CTL_CLK32EN bit is carried out, the HIB_CTL_WRC is de-asserted. The main issue here is that the HibernateEnableExpClk(...) function then NEVER returns, as the _HibernateWriteComplete() seems to get the MCU stuck in an infinite loop (this function simply waits for the assertion of the HIB_CTL_WRC bit which never happens).
The "hib_stat_track" serves simply as a way for me to insert a breakpoint in the code. The "hibernation_status" retains a value of 0 throughout the execution.
I'm using the EK-TM4C123GXL to test it out on, with nothing but a USB cable connected. Can anyone tell me what I'm doing wrong? I think it's a power issue, but looking at the schematic for the board I cannot really figure out what the real problem appears to be.