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.

TM4C123GH6PM: Tm4c123gh6pm systic reload value issue

Part Number: TM4C123GH6PM

I have written a code to make a pulse of 100ms at 5s intervals,If i load value of 100ms in systic timer doesnot produce correct result but if i insert value of 50 in load register accurate pulse is made.As far as i know while working with systic at 80MHz, we can  get interrupt at every 200ms(timer overflows every 200ms at max count).I cannot get correct value when 100 is put in this command (ROM_SysTickPeriodSet(SysCtlClockGet()*100/1000);) but if i put 50 i get correct result that is 50ms pulse. Following is the code.

/***********************************************************
This is Main program Application for Monitoring Pi status

Status from Pi is received by PD0 pin. On every toggle,
status is updated which is displayed by LED's. There are 4 states:
First status is for representing whether PI was restarted lately,
where as other 3 pins shows PI status. The status on which PI is currently at,
is represented by bliking of the respective LED
It utilizes WTimer0 of TM4C123G for its internal timing purposes.
If program doesn't receive any status from PI within 60 seconds,
program will re-initialize.

The system also gets the updated time every second with the help of GPS.
It is attached to UART1 and NMEA sentences are stored in ring buffer through
UART interrupt. Time information is extracted by data parsing when sentence
terminates.

It generates its own pulse to tell PI when to transmit data. It syncs itself
every 30 minutes with PPS of GPS to eliminate timer drifts. WTimer 1 is used
to monitor the resync timeout and Timer 1 is used to set the pulse to zero


Connections:
PD0 -> Pi status toggle Pin
PB1 -> LED1 (for representing whether Pi was restarted lately)
PB2 -> LED2
PB3 -> LED3
PB4 -> LED4
GND -> Pi Ground

PC4(U1RX)-> GPS TX
PC6 -> GPS PPS
PC7 -> pi GPIO pin (to tell pi to initiate transmission)
3.3V -> GPS VIN pin
GND -> GPS GND

***********************************************************/


#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
//#include "utils/uartstdio.c"
//void PWMint();
#include <String.h>
//#include "strfunc.h"
#include "inc/hw_ints.h"
#include "inc/hw_timer.h"
#include "inc/hw_gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.c"
#include "driverlib/sysctl.h"
#include "driverlib/Timer.c"
#include "driverlib/Timer.h"
#include "driverlib/gpio.c"
#include "driverlib/gpio.h"
#include "adafruitUltimateGPS.h"
#include <stdio.h>
#include "UART.h"
//#include "SysTickInts.h"
//#include "PLL.h"

bool isDeviceIDSyncPrepTime(char* currTimeString, uint8_t currDeviceID);

bool PPSInterruptOccured=false; //bool variable to store whether pps interrupt has occured or not after resync request
bool ResyncTimeout=false; //flag to state whether timeout for resync with PPS as occured or not
bool PPSTimerEnabled=false; //flag to store whether timer for PPS is enabled or not
uint32_t lastSyncWithPPS=0; //variable to store time elapsed after the last resync with PPS
int programState=0; //
const uint8_t device_id=1; // Device ID
int i=0;
int T_count=0;
int ResyncTime=720+1;
uint32_t g_ui32Flags;

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************


//*****************************************************************************
//
// Configure the UART and its pins. This must be called before UARTprintf().
//
//*****************************************************************************
void
ConfigureUART(void)
{
//
// Enable GPIO port A which is used for UART0 pins.
// TODO: change this to whichever GPIO port you are using.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//
// Configure the pin muxing for UART0 functions on port A0 and A1.
// This step is not necessary if your part does not support pin muxing.
// TODO: change this to select the port/pin you are using.
//
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);

//
// Enable UART0 so that we can configure the clock.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

//
// Use the internal 16MHz oscillator as the UART clock source.
//
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

//
// Select the alternate (UART) function for these pins.
// TODO: change this to select the port/pin you are using.
//
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, 16000000);
}


void configPiStatusGPIO()
{
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
//LED
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0x00);

}

int counter,i,j=0;

void configPPSGPIO()
{
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); //enabling PORTC peripherals
GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_6); //setting Port C pin 6 to input type
GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_6, GPIO_RISING_EDGE);//setting int to rising edge(will be called at from low to high change)

GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_7); //setting Port C pin 7 to output type
GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, 0x00); //writing 0 to PC7
}


void configPPSTimer()
{
ROM_SysTickPeriodSet(SysCtlClockGet()*100/1000); // 1ms period

ROM_IntMasterEnable();
ROM_SysTickIntEnable();
}

void syncWithGPSPPS()
{
UARTprintf("Waiting for PPS from GPS\r\n");
GPIOIntClear(GPIO_PORTC_BASE, GPIO_INT_PIN_6); //clear interrupt
ROM_IntEnable(INT_GPIOC);
GPIOIntEnable(GPIO_PORTC_BASE, GPIO_PIN_6); //enabling the interrupt


}

void PPSGPIOInterrupt()
{
GPIOIntClear(GPIO_PORTC_BASE, GPIO_INT_PIN_6); //clear interrupt


ROM_SysTickPeriodSet(SysCtlClockGet()*100/1000); // if i put 100 here i donot get correct time period,i get arroud 44ms time period
;
ROM_IntMasterEnable();
ROM_SysTickIntEnable();
ROM_SysTickEnable();
UARTprintf("\r\nShifting to State 2");
programState = 2;
counter=0;
T_count=0;
ROM_IntDisable(INT_GPIOC);
GPIOIntDisable(GPIO_PORTC_BASE, GPIO_PIN_6); //disabling the interrupt
//lastSyncWithPPS=0;
UARTprintf("PPS has occured and controller has been synced\r\n");
}

void TickHandler()
{
// if(counter>1){
GPIOPinWrite(GPIO_PORTC_BASE,GPIO_PIN_7,0x00);
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2,0x00);
// }
counter=counter+1;
if(counter==100){



GPIOPinWrite(GPIO_PORTC_BASE,GPIO_PIN_7,0xFF);
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2,0xFF);
counter=0;
T_count=T_count+1;
UARTprintf("HIGH PULSE= %i\n",T_count);
}
}

int main(void)
{


SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
ROM_FPULazyStackingEnable();


//configWatchDog(); //initialize watchdog - for testing comment it
ConfigureUART(); //initializing UART used by the application
//Uart_Init();
initGPS();
initStreamer();
UARTprintf("initialized\r\n");
//
configPiStatusGPIO();
//configPiStatusTimer();
configPPSGPIO();
configPPSTimer();


ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3); // PF1-3 as outputs


programState=1;
while (1)
{
//UARTprintf("d");

switch( programState)
{
case 0:
{
if (isGPSSentenceComplete() )
{
UARTprintf("\r\nShifting to State 1");
GPSGetData();
if (isGPSDataUpdated())
{
UARTprintf("\r\nShifting to State 1");
if(isDeviceIDSyncPrepTime((char*)GPSData->Time, device_id) == true)
{

UARTprintf(GPSData->Time);
UARTprintf("\r\n");
UARTprintf("\r\nShifting to State 1");
programState = 1;
UARTprintf("\r\n\n");
}
}
}
break;
}

case 1:
{


syncWithGPSPPS();


break;
}
case 2:
{
if(T_count==ResyncTime){
UARTprintf("Resynctimeout==true");
ROM_SysTickDisable();
programState = 1;
}

break;
}
default:
{
UARTprintf("Stuck at wrong program state...\r\nResetting to State 0...");
programState = 0;
}

}

}
}

bool isDeviceIDSyncPrepTime(char* currTimeString, uint8_t currDeviceID)
{
char d_id[4];
strcpy(d_id, "1.000");
UARTprintf("\r\nDevice ID: ");
UARTprintf(d_id);
UARTprintf("\r\nDevice time: ");
UARTprintf(&currTimeString[5]);




if (strncmp(&currTimeString[5], "1.000", 3) == 0 || strncmp(&currTimeString[5], "6.000", 3) == 0){
UARTprintf("\r\nTriggered Time: ");
UARTprintf(&currTimeString[5]);
return true;
}
else{
return false;
}
}

 

  • The SysCtlClockGet() returns the clock rate of the processor clock. If you enable PLL then the SysCtlClockGet will return 80000000 which is 80MHz. The SysCtlClockGet does not return the number of cycles in one second.
  • ROM_SysTickPeriodSet(SysCtlClockGet()*100/1000); // if i put 100 here i donot get correct time period,i get arroud 44ms time period
    Isnt this command going to produce interrupt every 100ms ,Well this command accurately produces interrupts for any value equal to or less than 50.Above 50 i have only looked with 100 value.
  • Can you try SysTickPeriodSet((int)SysCtlClockGet()*100/1000); instead?
  • Hi,
    I have not heard back from you. I will assume the issue is resolved. I will close this thread for now. If you still have questions you can reopen this thread or open a new thread for new questions.
  • Sorry for late reply , i was struck in some other thing.Now i am getting period of 200ms .Its really strange.I should have got timeout at every 100ms.More ever using ROM_SysTickPeriodSet(SysCtlClockGet()*50/1000);, gives great accuracy of producing 50ms timeout, while on the other hand inserting 50 or 100 in your way of ROM_SysTickPeriodSet((int)SysCtlClockGet()*100/1000); gives 200 ms regardless of whether i put 100 or 50.

  • If you are getting a 'period' of 200ms then it means the interrupt is generated at 100ms, isn't? I assume you try to toggle a LED inside the ISR. Why don't you try to toggle a GPIO pin in the ISR and capture the signal in the scope? Measure the low phase and high phase of the signal and see if they are 100ms wide. If yes, then you are generating an interrupt at 100ms.
  • No this means interrupt is generated at every 200ms. I am using oscilloscope to observe the waveform.My code works like this when interrupt occurs at GPIO pin PC6, Systic timer is activated and loaded with value of 100ms. when systic timer overflows first time PC7 is made high,and then in the next overflow it is made low,the program remains low until 50 overflows,because i want to make high pulse of 100ms at every 5 seconds.So after every 50 overflows timer will be made high and then it will become low after next overflow.
    My algorithm gives correct result for period less than or equal to 50ms but as soon as i load 100ms or higher value problem occurs, it seems as if in systic i cant load value of 100ms or greater.I think reload value of 100ms is greater than systic register size, although it is contrary to what data sheet says.According to data sheet at 80MHz with 24bit systic register i can get interrupt at every 207ms.
  • Ok, let me know if this is the correct understanding. Your period on the PC7 is actually 5 seconds. The high phase on the PC7 is 100ms while the low phase is  (5s - 100ms) which is 4.9s.  If you are trying to load the counter with 4.9s worth of count then it certainly will overflow the 24-bit counter. But I guess you try to count 50 overflows with each overflow equals to 100ms which is supposed to give you 5s. Somewhere in your code you probably load a value that is is larger than what the 24-bit timer can take. Look at the NVIC_ST_RELOAD register in CCS register window and see if the value you preload the 24-bit timer is larger than 24 bits can hold.

    For your application, I think it maybe easier to use the GPtimer instead of the systick. The GPtimer is 32-bit and you can even concatenate two of them to form a 64-bit timer.

    Below simple

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/rom.h"
    
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup systick_examples_list
    //! <h1>Systick Interrupt (systick_int)</h1>
    //!
    //! This example shows how to configure the SysTick and the SysTick interrupt.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - NONE
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of
    //! Systick.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - SysTickIntHandler
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Counter to count the number of interrupts that have been called.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32Counter = 0;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    //*****************************************************************************
    //
    // The interrupt handler for the for Systick interrupt.
    //
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
        //
        // Update the Systick interrupt counter.
        //
        g_ui32Counter++;
    
        if ((g_ui32Counter % 2) == 0) {
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
    
        } else {
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    
        }
    
    }
    
    uint32_t i=0;
    int period_width=0;
    
    //*****************************************************************************
    //
    // Configure the SysTick and SysTick interrupt with a period of 1 second.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        uint32_t ui32PrevCount = 0;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_OSC), 25000000);
    #else
        //SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
        //               SYSCTL_XTAL_16MHZ);
        SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
    #endif
    
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PF2 & PF3).
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for Systick operation.
        //
        InitConsole();
    
        //
        // Display the setup on the console.
        //
        UARTprintf("SysTick Firing Interrupt ->");
        UARTprintf("\n   Rate = 0.1sec\n\n");
    
        //
        // Initialize the interrupt counter.
        //
        g_ui32Counter = 0;
    
        i = SysCtlClockGet();
    
        //
        // Set up the period for the SysTick timer.  The SysTick timer period will
        // be equal to the system clock, resulting in a period of 1 second.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        SysTickPeriodSet(ui32SysClock);
    #else
        SysTickPeriodSet((int)SysCtlClockGet()*100/1000);
    
    #endif
    
        //
        // Enable interrupts to the processor.
        //
        IntMasterEnable();
    
        //
        // Enable the SysTick Interrupt.
        //
        SysTickIntEnable();
    
        //
        // Enable SysTick.
        //
        SysTickEnable();
    
        //
        // Loop forever while the SysTick runs.
        //
        while(1)
        {
            //
            // Check to see if systick interrupt count changed, and if so then
            // print a message with the count.
            //
            if(ui32PrevCount != g_ui32Counter)
            {
                //
                // Print the interrupt counter.
                //
                UARTprintf("Number of interrupts: %d\r", g_ui32Counter);
                ui32PrevCount = g_ui32Counter;
            }
        }
    }

    code is just to demonstrate the interrupt is generated at 100ms. You can observe PF2 pin on the scope and measure it. 

  • Hi,
    Is your question resolved?
  • I Have used General purpose timers and they produce correct results.More ever through them i can generate interrupts for longer duration also.