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