Other Parts Discussed in Thread: EK-TM4C1294XL
I am trying to use RTC in counter mode using hibernation module but not sending processor into hibernating mode.
I am trying to create a sub second interrupt using RTC Match registers - precisely 10 HZ interrupt about 10 times within one second. I use a different GPIO pin to enable interrupt every one second. And within this one second I need precise ten 10 HZ interrupts. I am using the RTC subseconds register and Match Register for the same.
The code snippets to enable RTC and HIB:
// Configure Hibernate module clock.
//
HibernateEnableExpClk(ui32SysClock);
// Enable RTC mode.
//
HibernateRTCEnable();
//
// Configure the hibernate module counter to 24-hour calendar mode.
//
// HibernateCounterMode(HIBERNATE_COUNTER_24HR);
// Configure the hibernate module counter to RTC counter mode.
HibernateCounterMode(HIBERNATE_COUNTER_RTC);
############To get inetrrupt every ones econd we use the GPIO######################################################################################
// LaunchPad BoosterPack 1 Header for taking 1 PPS pulse configure pins
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_3); // Init PF3 as input
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
// Interrupt setup
GPIOIntDisable(GPIO_PORTF_BASE, GPIO_PIN_3); // Disable interrupt for PF4 (in case it was enabled)
GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_3); // Clear pending interrupts for PF4
// Register our handler function for port F pin 3
GPIOIntRegisterPin(GPIO_PORTF_BASE, GPIO_INT_PIN_3,IntGPIOf_Pin3);
GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_RISING_EDGE);
//
// Register the interrupt handler function for GPIO F pin 3
//
IntRegister(INT_GPIOF_TM4C129 , IntGPIOf_Pin3);
####################################################################################################
ENABLE HIBERNATE MATCH INTERRUPT
// Enable Hibernate Match Interrupt
HibernateRTCSet(0); // set RTC counter second to zero
// Clear pending interrupt from Hibernate Module
HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0);
// Disable interrupts for Hibernate module
HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_0);
HibernateIntRegister(Count10Hz_ISR); // register handler for this interrupt
// Register the interrupt handler function for RTC Match 0
//
IntRegister(INT_HIBERNATE_TM4C129 , Count10Hz_ISR);
//
// Enable the interrupt for RTC Match 0 in the processor vector table
//
// IntEnable(INT_HIBERNATE_TM4C129); // moved to just before main loop
// Enable processor interrupts.
// Reset RTC counter seconds
HibernateRTCMatchSet(0,0);
##########################################################################################################################################################
iSECOND ISR through GPIO
void
IntGPIOf_Pin3(void)
{
// set PPS flag = true for processing in main loop
HWREG(UART0_BASE + 0) = '$'; // 400nS delay, 550nS jitter @ 115200 baud // UART send
// // Turn on the bit
pps_flag = TRUE;
hibRegister_subseconds = HibernateRTCSSGet(); // HWREG(HIB_RTCSS);get subseconds alone here in ISR
// set both RTC counters to zero seconds and sub seconds
HibernateRTCSet(0);
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_3);
}
#############################################################################################################
SUB SECOND ISR ENABLED BY HIB MATCH ISR
//*****************************************************************************
//
// This is the handler for 10 HZ interrupt within each 1 pps interval.
// Use RTC Match value to generate interrupt 10 times within 1 sec
//
//*****************************************************************************
void Count10Hz_ISR(void) {
HWREG(UART0_BASE + 0) = '|'; // ###########
// Turn on the bit
//MAIN LOOP FLAG
RTC_Flag = TRUE;
HWREG(HIB_IC) |= HIBERNATE_INT_RTC_MATCH_0;
} // end ISR
##############################################################################################
MAIN LOOP
while(1)
{
// spit out $ in an infinite loop
if (pps_flag == TRUE){
// reset pps flag
pps_flag = FALSE;
MatchDollarCounter = 0; // ###############
HWREG(HIB_RTCSS) &= 0x0000FFFF; // retaining lower 16 bits as is
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write
// measured ~90uS
HWREG(HIB_RTCSS) |= 0x0CCD0000; // ##### disassembled code shows that this does a read-modify-write over 4 instructions, which introduces a timing error ######
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write
HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0); // interrupt source for RTC interrupt} // end if pps flag
else if (RTC_Flag == TRUE) { // #############
// UARTFlushTx(FALSE); // Flush UART Transmit Buffer #############
// Turn off the bit
// GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_PIN_1);
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1);
MatchDollarCounter++; // ##########
// hibernateRTCMatchValue = (HibernateRTCMatchGet(0) + 0x1000) << 16; // add 100 msec more each time. So zero is start of time ###############
hibernateRTCMatchValue = (0xCCD + 0xCCD*MatchDollarCounter) << 16; // add 100 msec more each time. So zero is start of time ###############
HWREG(HIB_RTCSS) &= 0x0000FFFF; // retaining lower 16 bits as is #################
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write (~90uS)
HWREG(HIB_RTCSS) |= hibernateRTCMatchValue; // ##### disassembled code shows that this does a read-modify-write over several instructions, which introduces a timing error ######
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write (~90uS)
// HibernateRTCSSMatchSet(0,hibernateRTCMatchValue); // ######## This will alter the Subsample Seconds, which we don't want to do! ########
RTC_Flag = FALSE;
if (MatchDollarCounter == 3)
HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_0);
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
}
} // end while 1
#####################################################################################################################
PROBLEM: We can generate only 3 pulses and they are not evenly spaced at 10 HZ. They keelp increasing in time: The first interrupt is at 1/10 sec, the second at 132 microsecond and third at about 250 usec and we do not get fourth one.
I would appreciate reply on this as as much as help from TI as possible.
I am attaching original code file which was adapted from Tivaware example :
Example code for Hybernation Module is found in Tivaware\examples\boards\ek-tm4c1294xl\hibernate\hibernate.c
Thank you
Pavitra
//*****************************************************************************
//
// hibernate.c - Hibernation Example.
//
// Copyright (c) 2013-2016 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.3.156 of the EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include "inc/hw_gpio.h"
#include "inc/hw_hibernate.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/hibernate.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/systick.h"
#include "utils/ustdlib.h"
#include "utils/uartstdio.h"
#include "utils/cmdline.h"
#include "drivers/buttons.h"
#include "drivers/pinout.h"
//#include "inc/tm4c1294ncpdt.h"
//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Hibernate Example (hibernate)</h1>
//!
//! An example to demonstrate the use of the Hibernation module. The user
//! can put the microcontroller in hibernation by typing 'hib' in the terminal
//! and pressing ENTER or by pressing USR_SW1 on the board. The
//! microcontroller will then wake on its own after 5 seconds, or immediately
//! if the user presses the RESET button. The External WAKE button, external
//! WAKE pins, and GPIO (PK6) wake sources can also be used to wake
//! immediately from hibernation. The following wiring enables the use of
//! these pins as wake sources.
//! WAKE on breadboard connection header (X11-95) to GND
//! PK6 on BoosterPack 2 (X7-17) to GND
//! PK6 on breadboard connection header (X11-63) to GND
//!
//! The program keeps a count of the number of times it has entered
//! hibernation. The value of the counter is stored in the battery-backed
//! memory of the Hibernation module so that it can be retrieved when the
//! microcontroller wakes. The program displays the wall time and date by
//! making use of the calendar function of the Hibernate module. User can
//! modify the date and time if so desired.
//
//*****************************************************************************
// defines
#define FALSE 0
#define TRUE 1
#define FREQ 9 // we need 9- 10 HZ pulses in 1 second width
#define CLKARRAYLEN 5 // we store these many samples of RTC clock
#define RTCTRIM 64 // trim reloaded every 64 sec
//*****************************************************************************
//
// A collection of wake sources that will be displayed to indicate the source
// of the most recent wake.
//
//*****************************************************************************
static char *g_ppcWakeSource[] =
{
"RTC TIMEOUT",
"RESET",
"WAKE PIN",
"GPIO WAKE",
"SYSTEM RESET"
};
//*****************************************************************************
//
// Lookup table to convert numerical value of a month into text.
//
//*****************************************************************************
static char *g_ppcMonth[12] =
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
//*****************************************************************************
//
// Flag that informs that the user has requested hibernation.
//
//*****************************************************************************
volatile bool g_bHibernate;
//*****************************************************************************
//
// Variables that keep terminal position and status.
//
//*****************************************************************************
bool g_bFirstUpdate;
uint8_t g_ui8FirstLine;
//*****************************************************************************
//
// Flag that informs that date and time have to be set.
//
//*****************************************************************************
volatile bool g_bSetDate;
//*****************************************************************************
//
// Buffers to store display information.
//
//*****************************************************************************
char g_pcWakeBuf[40], g_pcHibBuf[40], g_pcDateTimeBuf[40];
//*****************************************************************************
//
// Buffer to store user command line input.
//
//*****************************************************************************
char g_pcInputBuf[40];
//*****************************************************************************
//
// Variables that keep track of the date and time.
//
//*****************************************************************************
uint32_t g_ui32MonthIdx, g_ui32DayIdx, g_ui32YearIdx;
uint32_t g_ui32HourIdx, g_ui32MinIdx;
//*****************************************************************************
//
// Variables that keep track of RTC counter mode and calculate drift
//
//*****************************************************************************
uint32_t hibRegister_seconds=0;// Array to hold time stamp values from RTC counter
uint32_t hibRegister_subseconds=0,hibRegister_subsecondsLast=0;
bool pps_flag=FALSE;
bool RTC_Flag = FALSE;
uint32_t MatchDollarCounter =0; // Counts from 0 to 9 for 10 HZ pulse
uint32_t hibernateRTCMatchValue = 0;
//uint32_t RTCTrim_Last = 0, RTCTrim_Current=0; // for RTC Trim registers
int RTCCount = 0,CountToSixtyFour=0;
uint32_t drift = 0;
//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
//*****************************************************************************
//
// This function reads the current date and time from the calendar logic of the
// hibernate module. Return status indicates the validity of the data read.
// If the received data is valid, the 24-hour time format is converted to
// 12-hour format.
//
//*****************************************************************************
bool
DateTimeGet(struct tm *sTime)
{
//
// Get the latest time.
//
HibernateCalendarGet(sTime);
//
// Is valid data read?
//
if(((sTime->tm_sec < 0) || (sTime->tm_sec > 59)) ||
((sTime->tm_min < 0) || (sTime->tm_min > 59)) ||
((sTime->tm_hour < 0) || (sTime->tm_hour > 23)) ||
((sTime->tm_mday < 1) || (sTime->tm_mday > 31)) ||
((sTime->tm_mon < 0) || (sTime->tm_mon > 11)) ||
((sTime->tm_year < 100) || (sTime->tm_year > 199)))
{
//
// No - Let the application know the same by returning relevant
// message.
//
return false;
}
//
// Return that new data is available so that it can be displayed.
//
return true;
}
//*****************************************************************************
//
// This function formats valid new date and time to be displayed on the home
// screen in the format "MMM DD, YYYY HH : MM : SS AM/PM". Example of this
// format is Aug 01, 2013 08:15:30 AM. It also indicates if valid new data
// is available or not. If date and time is invalid, this function sets the
// date and time to default value.
//
//*****************************************************************************
bool
DateTimeDisplayGet(char *pcBuf, uint32_t ui32BufSize)
{
static uint32_t ui32SecondsPrev = 0xFF;
struct tm sTime;
uint32_t ui32Len;
//
// Get the latest date and time and check the validity.
//
if(DateTimeGet(&sTime) == false)
{
//
// Invalid - Force set the date and time to default values and return
// false to indicate no information to display.
//
g_bSetDate = true;
return false;
}
//
// If date and time is valid, check if seconds have updated from previous
// visit.
//
if(ui32SecondsPrev == sTime.tm_sec)
{
//
// No - Return false to indicate no information to display.
//
return false;
}
//
// If valid new date and time is available, update a local variable to keep
// track of seconds to determine new data for next visit.
//
ui32SecondsPrev = sTime.tm_sec;
//
// Format the date and time into a user readable format.
//
ui32Len = usnprintf(pcBuf, ui32BufSize, "%s %02u, 20%02u ",
g_ppcMonth[sTime.tm_mon], sTime.tm_mday,
sTime.tm_year - 100);
usnprintf(&pcBuf[ui32Len], ui32BufSize - ui32Len, "%02u : %02u : %02u",
sTime.tm_hour, sTime.tm_min, sTime.tm_sec);
//
// Return true to indicate new information to display.
//
return true;
}
//*****************************************************************************
//
// This function writes the requested date and time to the calendar logic of
// hibernation module.
//
//*****************************************************************************
void
DateTimeSet(void)
{
struct tm sTime;
//
// Get the latest date and time. This is done here so that unchanged
// parts of date and time can be written back as is.
//
HibernateCalendarGet(&sTime);
//
// Set the date and time values that are to be updated.
//
sTime.tm_hour = g_ui32HourIdx;
sTime.tm_min = g_ui32MinIdx;
sTime.tm_mon = g_ui32MonthIdx;
sTime.tm_mday = g_ui32DayIdx;
sTime.tm_year = 100 + g_ui32YearIdx;
//
// Update the calendar logic of hibernation module with the requested data.
//
HibernateCalendarSet(&sTime);
}
//*****************************************************************************
//
// This function sets the time to the default system time.
//
//*****************************************************************************
void
DateTimeDefaultSet(void)
{
g_ui32MonthIdx = 7;
g_ui32DayIdx = 29;
g_ui32YearIdx = 13;
g_ui32HourIdx = 8;
g_ui32MinIdx = 30;
}
//*****************************************************************************
//
// This function updates individual buffers with valid date and time to be
// displayed on the date screen so that the date and time can be updated.
//
//*****************************************************************************
bool
DateTimeUpdateGet(void)
{
struct tm sTime;
//
// Get the latest date and time and check the validity.
//
if(DateTimeGet(&sTime) == false)
{
//
// Invalid - Return here with false as no information to update. So
// use default values.
//
DateTimeDefaultSet();
return false;
}
//
// If date and time is valid, copy the date and time values into respective
// indexes.
//
g_ui32MonthIdx = sTime.tm_mon;
g_ui32DayIdx = sTime.tm_mday;
g_ui32YearIdx = sTime.tm_year - 100;
g_ui32HourIdx = sTime.tm_hour;
g_ui32MinIdx = sTime.tm_min;
//
// Return true to indicate new information has been updated.
//
return true;
}
//*****************************************************************************
//
// This function returns the number of days in a month including for a leap
// year.
//
//*****************************************************************************
uint32_t
GetDaysInMonth(uint32_t ui32Year, uint32_t ui32Mon)
{
//
// Return the number of days based on the month.
//
if(ui32Mon == 1)
{
//
// For February return the number of days based on the year being a
// leap year or not.
//
if((ui32Year % 4) == 0)
{
//
// If leap year return 29.
//
return 29;
}
else
{
//
// If not leap year return 28.
//
return 28;
}
}
else if((ui32Mon == 3) || (ui32Mon == 5) || (ui32Mon == 8) ||
(ui32Mon == 10))
{
//
// For April, June, September and November return 30.
//
return 30;
}
//
// For all the other months return 31.
//
return 31;
}
//*****************************************************************************
//
// This function returns the date and time value that is written to the
// calendar match register. 5 seconds are added to the current time. Any
// side-effects due to this addition are handled here.
//
//*****************************************************************************
void
GetCalendarMatchValue(struct tm* sTime)
{
uint32_t ui32MonthDays;
//
// Get the current date and time and add 5 secs to it.
//
HibernateCalendarGet(sTime);
sTime->tm_sec += 5;
//
// Check if seconds is out of bounds. If so subtract seconds by 60 and
// increment minutes.
//
if(sTime->tm_sec > 59)
{
sTime->tm_sec -= 60;
sTime->tm_min++;
}
//
// Check if minutes is out of bounds. If so subtract minutes by 60 and
// increment hours.
//
if(sTime->tm_min > 59)
{
sTime->tm_min -= 60;
sTime->tm_hour++;
}
//
// Check if hours is out of bounds. If so subtract minutes by 24 and
// increment days.
//
if(sTime->tm_hour > 23)
{
sTime->tm_hour -= 24;
sTime->tm_mday++;
}
//
// Since different months have varying number of days, get the number of
// days for the current month and year.
//
ui32MonthDays = GetDaysInMonth(sTime->tm_year, sTime->tm_mon);
//
// Check if days is out of bounds for the current month and year. If so
// subtract days by the number of days in the current month and increment
// months.
//
if(sTime->tm_mday > ui32MonthDays)
{
sTime->tm_mday -= ui32MonthDays;
sTime->tm_mon++;
}
//
// Check if months is out of bounds. If so subtract months by 11 and
// increment years.
//
if(sTime->tm_mon > 11)
{
sTime->tm_mon -= 11;
sTime->tm_year++;
}
//
// Check if years is out of bounds. If so subtract years by 100.
//
if(sTime->tm_year > 99)
{
sTime->tm_year -= 100;
}
}
//*****************************************************************************
//
// This function does some application level cleanup and alerts the user
// before sending the hibernate request to the hardware.
//
//*****************************************************************************
void
AppHibernateEnter(void)
{
uint32_t ui32Status;
struct tm sTime;
//
// Print the buffer to the terminal.
//
UARTprintf("To wake, wait for 5 seconds or press WAKE or"
"RESET\n");
UARTprintf("See README.txt for additional wake sources.\n");
//
// Wait for UART transmit to complete before proceeding to
// hibernate.
//
UARTFlushTx(false);
//
// Get calendar match value to be 5 seconds from the current time.
//
GetCalendarMatchValue(&sTime);
//
// Set the calendar match register such that it wakes up from
// hibernation in 5 seconds.
//
HibernateCalendarMatchSet(0, &sTime);
//
// Read and clear any status bits that might have been set since
// last clearing them.
//
ui32Status = HibernateIntStatus(0);
HibernateIntClear(ui32Status);
//
// Configure Hibernate wake sources.
//
HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_GPIO |
HIBERNATE_WAKE_RESET | HIBERNATE_WAKE_RTC);
//
// Request Hibernation.
//
HibernateRequest();
//
// Wait for a while for hibernate to activate. It should never get
// past this point.
//
SysCtlDelay(100);
//
// If it ever gets here, store the text, that informs the user on
// what to do, into the respective widget buffers.
//
UARTprintf("The controller did not enter hibernate. Press RESET"
"button to restart example.\n");
//
// Wait here.
//
while(1)
{
}
}
//*****************************************************************************
//
// This function is the interrupt handler for the SysTick timer. It monitors
// both the USR_SW buttons on the board. If a button is pressed then we
// request a hibernate cycle.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
uint32_t ui32Buttons;
ui32Buttons = ButtonsPoll(0,0);
switch(ui32Buttons & ALL_BUTTONS)
{
//
// The user pressed USR_SW1.
//
case USR_SW1:
{
//
// Set the hibernate flag to request a system hibernate cycle.
//
g_bHibernate = true;
break;
}
//
// For all other cases do nothing.
//
default:
{
break;
}
}
}
//*****************************************************************************
//
// This is the handler for INT_GPIOF Pin 3. It triggers INT_GPIOA and saves the
// interrupt sequence number.
//
//*****************************************************************************
void
IntGPIOf_Pin3(void)
{
// set PPS flag = true for processing in main loop
// UARTprintf("$"); // 4.2uS delay, 550nS jitter @ 115200 baud
HWREG(UART0_BASE + 0) = '$'; // 400nS delay, 550nS jitter @ 115200 baud // UART send
// // Turn on the bit
// GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_PIN_0);
pps_flag = TRUE;
hibRegister_subseconds = HibernateRTCSSGet(); // HWREG(HIB_RTCSS);get subseconds alone here in ISR
// RTCTrim_Current = HibernateRTCTrimGet();
// UARTprintf("$"); // 250uS delay, 30uS jitter @ 115200 baud
// set both RTC counters to zero seconds and sub seconds
HibernateRTCSet(0);
GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_3);
}
//*****************************************************************************
//
// This is the handler for 10 HZ interrupt within each 1 pps interval.
// Use RTC Match value to generate interrupt 10 times within 1 sec
//
//*****************************************************************************
void Count10Hz_ISR(void) {
HWREG(UART0_BASE + 0) = '|'; // ###########
// Turn on the bit
// GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_PIN_0);
RTC_Flag = TRUE;
// hibRegister_seconds = HWREG(HIB_RTCC); //Get seconds count
// MatchDollarCounter++; // ###### moved to main loop
// MatchDollarCounter %= FREQ; // Automatically set this value to ZERO on reaching 10 HZ #######
// if (MatchDollarCounter == 0) {
HWREG(HIB_IC) |= HIBERNATE_INT_RTC_MATCH_0;
// HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0); // ######## added
// }
} // end ISR
//*****************************************************************************
//
// This is the function to caLCLULATE if RTC clock drift is there within 1 second
//
//*****************************************************************************
void CalculateRTClkDrift(void)
{
//drift = (hibRegister_subseconds - hibRegister_subsecondsLast) / 32768; //RTC clock Rate is 32.768 KHZ
} // end calc clock drift
//*****************************************************************************
//
// This example demonstrates the different hibernate wake sources. The
// microcontroller is put into hibernation by the user and wakes up based on
// timeout or one of the user inputs. This example also demonstrates the RTC
// calendar function that keeps track of date and time.
//
//*****************************************************************************
int
main(void)
{
uint32_t ui32SysClock;
//
// Run from the PLL at 120 MHz.
//
ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
//
// Configure the device pins.
// Configures the device pins for the standard usages on the EK-TM4C1294XL.
// No Ethernet or USB
PinoutSet(false, false);
// Enable the GPIO port that is used for the on-board LED.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
//
// Check if the peripheral access is enabled.
//
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION))
{
}
// Enable the GPIO pin for the LED (PN0). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
// Turn on the LED.
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
// Clear Arrays
/* for (index=0;index<CLKARRAYLEN;index++) {
hibRegister_seconds[index] = 0;
}
// reinitialize index
index = 0; */
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, ui32SysClock);
//discard any data in UART FIFO
UARTFlushTx(TRUE); // Discard UART Transmit Buffer
// Enable the hibernate module.
//
// SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
//
// Initialize these variables before they are used.
//
RTCCount = 0;
drift = 0;
CountToSixtyFour=0;
//
// Configure Hibernate module clock.
//
HibernateEnableExpClk(ui32SysClock);
// Enable RTC mode.
//
HibernateRTCEnable();
//
// Configure the hibernate module counter to 24-hour calendar mode.
//
// HibernateCounterMode(HIBERNATE_COUNTER_24HR);
// Configure the hibernate module counter to RTC counter mode.
HibernateCounterMode(HIBERNATE_COUNTER_RTC);
//
// Configure GPIOs used as Hibernate wake source. PK6 is configured as a
// wake source. It is available on EK-TM4C1294XL BoosterPack 2 (X7-17)
// and on the breadboard breakout connector (X11-63). Short to ground to
// generate a wake request.
//
// GPIOPadConfigSet(GPIO_PORTK_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA,
// (GPIO_PIN_TYPE_WAKE_LOW | GPIO_PIN_TYPE_STD_WPU));
// LaunchPad BoosterPack 1 Header for taking 1 PPS pulse configure pins
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_3); // Init PF3 as input
// GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_DIR_MODE_IN) ;
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
// Interrupt setup
GPIOIntDisable(GPIO_PORTF_BASE, GPIO_PIN_3); // Disable interrupt for PF4 (in case it was enabled)
GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_3); // Clear pending interrupts for PF4
// Register our handler function for port F pin 3
GPIOIntRegisterPin(GPIO_PORTF_BASE, GPIO_INT_PIN_3,IntGPIOf_Pin3);
GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_RISING_EDGE);
//
// Register the interrupt handler function for GPIO F pin 3
//
IntRegister(INT_GPIOF_TM4C129 , IntGPIOf_Pin3);
// Configure POrt P Pin 1 (PP1) on booster pack 2 header) for transmitting a bit --DEBUG purposes
// LaunchPad BoosterPack 1 Header for taking 1 PPS pulse configure pins
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
//
// Check if the peripheral access is enabled.
//
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOP))
{
}
GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_1); // Init PP1 as output
GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
// Initialize the buttons
//
// ButtonsInit();
//
// Initialize the SysTick interrupt to process user buttons.
//
// SysTickPeriodSet(SysCtlClockGet() / 30);
// SysTickEnable();
// SysTickIntEnable();
// Enable Hibernate Match Interrupt
HibernateRTCSet(0); // set RTC counter second to zero
// Clear pending interrupt from Hibernate Module
HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0);
// Diable interrupts for Hibernate module
HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_0);
// ######## moved HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0); // interrupt source for RTC interrupt
HibernateIntRegister(Count10Hz_ISR); // register handler for this interrupt
// Register the interrupt handler function for RTC Match 0
//
IntRegister(INT_HIBERNATE_TM4C129 , Count10Hz_ISR);
//
// Enable the interrupt for RTC Match 0 in the processor vector table
//
// IntEnable(INT_HIBERNATE_TM4C129); // moved to just before main loop
// Enable processor interrupts.
// Reset RTC counter seconds
HibernateRTCMatchSet(0,0);
// if (MatchDollarCounter == 0) {
// HibernateRTCSSMatchSet(0,6554); // Subseconds match value
// }
// should only be in PPS section HibernateRTCSSMatchSet(0,6554) ; // set to 100 milliseconds 6554 = 100 msec
UARTprintf("BEGIN PRINTING\n");
//
// Loop forever.
//
// Enable interrupts for the pin
GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_3); // ######### moved here
//
// Enable the interrupt for GPIO Port F pin 3
//
IntEnable(INT_GPIOF_TM4C129); // ######### relocated
IntMasterEnable(); // ###### relocated here so as not to cause interrupts before getting to main loop ############
while(1)
{
// spit out $ in an infinite loop
if (pps_flag == TRUE){
// reset pps flag
pps_flag = FALSE;
// UARTFlushTx(FALSE); // Flush UART Transmit Buffer ############
// Turn off the bit
// GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_PIN_1);
RTCCount++; // increment seconds count for RTC Trim
RTCCount %= FREQ;
MatchDollarCounter = 0; // ###############
// HibernateRTCSSMatchSet(0,(2*6554)) ; // reset to 100 milliseconds 6554 = 100 msec every second
// HWREG(0x400FC004) = 0x00000CCD;
HWREG(HIB_RTCSS) &= 0x0000FFFF; // retaining lower 16 bits as is
// GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1);
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write
// GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0); // measured ~90uS
HWREG(HIB_RTCSS) |= 0x0CCD0000; // ##### disassembled code shows that this does a read-modify-write over 4 instructions, which introduces a timing error ######
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write
// HibernateRTCSSMatchSet(0,0x0CCD0000) ; // ######## The four zeros will clear the Subsample Seconds, which we don't want to do! ########
HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0); // interrupt source for RTC interrupt
// do a few other things
// reset counter
/* if (MatchDollarCounter == 0) {
if ( RTCCount == 0) {
if (hibRegister_subsecondsLast)
// drift = abs((hibRegister_subseconds - hibRegister_subsecondsLast)) ; // 32768; //RTC clock Rate is 32.768 KHZ
hibRegister_subseconds < hibRegister_subsecondsLast ? (drift += hibRegister_subsecondsLast - hibRegister_subseconds) : (drift += hibRegister_subseconds - hibRegister_subsecondsLast);
hibRegister_subsecondsLast = hibRegister_subseconds; // save last accumulated value of subsecons for 1 second interval
// one needs to adjust the drift ticks into RTC TRIM as 64*this value as that will be reloaded once in 64 seconds only
if (CountToSixtyFour == (6)){
HibernateRTCTrimSet(drift*64);
drift = 0; // accumulate drift for 64 seconds
CountToSixtyFour %= (6);
}
CountToSixtyFour++;
}
HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0); // interrupt source for RTC interrupt
}
*/ } // end if pps flag
// Read RTC Match Value
else if (RTC_Flag == TRUE) { // #############
// UARTFlushTx(FALSE); // Flush UART Transmit Buffer #############
// Turn off the bit
// GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_PIN_1);
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1);
MatchDollarCounter++; // ##########
// hibernateRTCMatchValue = (HibernateRTCMatchGet(0) + 0x1000) << 16; // add 100 msec more each time. So zero is start of time ###############
hibernateRTCMatchValue = (0xCCD + 0xCCD*MatchDollarCounter) << 16; // add 100 msec more each time. So zero is start of time ###############
HWREG(HIB_RTCSS) &= 0x0000FFFF; // retaining lower 16 bits as is #################
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write (~90uS)
HWREG(HIB_RTCSS) |= hibernateRTCMatchValue; // ##### disassembled code shows that this does a read-modify-write over several instructions, which introduces a timing error ######
while(!(HWREG(HIB_CTL) & HIB_CTL_WRC)); // ###### needed before next write (~90uS)
// HibernateRTCSSMatchSet(0,hibernateRTCMatchValue); // ######## This will alter the Subsample Seconds, which we don't want to do! ########
RTC_Flag = FALSE;
if (MatchDollarCounter == 3)
HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_0);
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
}
// SysCtlDelay(20000000);
} // end while 1
} // end main