Hi there,
I'm trying to get familiar using the hibernation module because my application will require it, but I'm having some issues. In my application, I'd like to wake from hibernate, talk to several sensors over their respective UARTs, log the data they return, and then hibernate again. I'm just in a prototyping phase right now; so, all I want to do is query the sensor over its UART, receive the information it returns via the respective UART interrupt handler and print the data out in a terminal on my desktop computer.
I was talking to one of my sensors ("MicroCAT" in the code), but was consistently getting garbage data along with the measurements it took. Best I tried, I could not get the garbage to go away. So, I UNPLUGGED the instrument entirely from the evaluation board to see if it was the problem (it wasn't).
So I reduced the problem and my code to try and debug, and now my code just does this: I check if I just woke up from hibernation. If it was a cold start-up, then I set up the hibernation module (allowing plenty of time for the crystal to stabilize after calling HibernateEnableExpClk()). Then I set up UART1; UART1 runs through a transceiver and then into a com port on my computer. Afterwards, I set up UART2 and enable the UART2RX interrupt to occur when the FIFO is 1/8 full. I print out "Start:" on my desktop, delay for a second, set up the hibernation module to wake up in 10 seconds, and then request hibernation.
I'd expect to see just this printed out after letting the program run for a while:
Start:
Start:
Start:
Instead, I wind up with something like this:
Start:
Start:
\mI
Ë',%!m
I:
0¸$I[$ù
Start:
}A<p¿?T6²ÿZ)ý¹Fª9=A
Start:
ª k@þ¶{é
Start:
@&"2Ü32h2A
(4 ÏZ©+¹0
Interestingly, the first run through the program (the space after the first "Start:") is always clean and clear of garbage. Afterwards, it goes downhill.
After debugging with delays, I found that a short delay (about 1/3 a second) after the code the determines if the hibernation module is active (setting it up if it it's not active) seems to "solve" the problem. With that delay (commented out in the code below) I get my desired output:
Start:
Start:
Start:
Does the controller just need a little time to wake up after getting out of hibernate? Have I goofed in my code somewhere? I really appreciate any help/advice.
I've been working with an EKS-LM4f232, Code Composer version 5.2.0.00069, and the code below:
-David
/*
* This function sends a string to the specified UART module.
*/
void UARTSend(unsigned long ulBase, const char *pucBuffer)
{
//ulCount is the length of the passed in string
unsigned long ulCount;
ulCount = strlen(pucBuffer);
// Loop while there are more characters to send.
while(ulCount--)
{
// Write the next character to the UART.
UARTCharPut(ulBase, *pucBuffer++);
}
}
/*
* This is the UART2RX interrupt handler--for the MicroCAT is on UART2.
* The handler simply writes characters out to the desktop.
*/
void UARTIntHandler(void)
{
unsigned long ulStatus;
// Get the interrupt status.
ulStatus = UARTIntStatus(UART2_BASE, true);
// Clear the asserted interrupts.
UARTIntClear(UART2_BASE, ulStatus);
// Loop while there are characters in the receive FIFO
while(UARTCharsAvail(UART2_BASE))
{
// Read the next character from the UART and write it to desktop.
UARTCharPutNonBlocking(UART1_BASE, UARTCharGetNonBlocking(UART2_BASE));
}
}
/*
* Enable the hibernation module and the RTC in it.
* This fcn does not set the RTC, just enables it.
*/
void hibernationModuleEnable()
{
//enable Hibernation module...it's given the clock rate of the processor
HibernateEnableExpClk(SysCtlClockGet());
//delay for crystal stabilization (data sheet says to expect 1500ms max)
SysCtlDelay(ONESEC);
SysCtlDelay(ONESEC);
//use the raw signal from the 32.768 kHz oscillator
HibernateClockSelect(HIBERNATE_CLOCK_SEL_RAW);
HibernateRTCEnable();
}
/*
* Enables UART1...9600, 8 bits, 1 stop, no parity.
* DOES NOT ENABLE THE UART it just sets it up.
*/
void UART1SetUp()
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); //UART1 is on GPIOC
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1); //it's UART1
GPIOPinConfigure(GPIO_PC4_U1RX); //configure the pins
GPIOPinConfigure(GPIO_PC5_U1TX);
GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);
//9600, one stop bit, no parity...
UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 9600,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
}
/*
* Sets up UART2...9600, 8 bits, 1 stop, no parity.
* DOES NOT ENABLE THE UART it just sets it up.
*/
void UART2SetUp()
{
// set up UART2
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); //enable the GPIO where the UART is, first
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2); //UART2
GPIOPinConfigure(GPIO_PG4_U2RX); //set up the pins
GPIOPinConfigure(GPIO_PG5_U2TX);
GPIOPinTypeUART(GPIO_PORTG_BASE, GPIO_PIN_4 | GPIO_PIN_5);
//9600 baud, 8, N, 1
UARTConfigSetExpClk(UART2_BASE, SysCtlClockGet(), 9600,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
}
int main(void)
{
//set the clock (50MHZ)
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
unsigned long ulStatus;
// Need to enable the Hibernation peripheral after wake/reset, before using it.
SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
//Was this a cold restart or out of hibernate? HibernateIsActive() returns true if the system woke from hibernate
if(HibernateIsActive())
{
//Read the status to determine cause of wake.
ulStatus = HibernateIntStatus(false);
//Wakeup from wake pin?
if(ulStatus & HIBERNATE_INT_PIN_WAKE)
{
//change wokenFromHibernate variable to true
wokenFromHibernate = 1;
}
//Wakeup by RTC match?
if(ulStatus & HIBERNATE_INT_RTC_MATCH_0)
{
//change wokenFromHibernate variable to true
wokenFromHibernate = 1;
}
}
//must be a cold restart, set up the hibernation module
else
{
//enable the hibernation module and it's RTC (does not set the RTC)
hibernationModuleEnable();
}
//SysCtlDelay(16000000);
//set up UART1 to run to the desktop
UART1SetUp();
//UART1SetUp() does not enable the UART, so do it here
UARTEnable(UART1_BASE);
//set up UART2 which will run to the MicroCAT
UART2SetUp();
//RX interrupt will occur when FIFO is 1/8 full
UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX7_8, UART_FIFO_RX1_8);
//enable UART2
UARTEnable(UART2_BASE);
//enable the interrupt
IntEnable(INT_UART2);
//Enable the UART peripheral interrupt...receive
UARTIntEnable(UART2_BASE, UART_INT_RX);
//enable processor interrupts
IntMasterEnable();
//print out "Start:" on the desktop
UARTSend(UART1_BASE, (char *)"\n\rStart:\n\r");
SysCtlDelay(ONESEC);
// Set the RTC to 0, or an initial value. The RTC can be set once when the
// system is initialized after the cold-startup, and then left to run. Or
// it can be initialized before every hibernate.
HibernateRTCSet(0);
// Set the match 0 register for 10 seconds from now.
HibernateRTCMatch0Set(HibernateRTCGet() + 10);
// Clear any pending status.
ulStatus = HibernateIntStatus(0);
HibernateIntClear(ulStatus);
// Configure to wake on RTC match.
HibernateWakeSet(HIBERNATE_WAKE_RTC);
// Request hibernation. The following call may return since it takes a
// finite amount of time for power to be removed.
HibernateRequest();
// Need a loop here to wait for the power to be removed. Power is
// removed while executing in this loop.
while(1)
{
}
}