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.

TM4C123GH6PGE: Timer delay function

Part Number: TM4C123GH6PGE
Other Parts Discussed in Thread: TMP20

Good afternoon every one,

                                          I want to use timer for creating the delay function for 10 minutes in tm4c123gh6pge microcontroller. I request you to please suggest me how to write simple delay function by using below clock frequency. 

SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);

 


Thanks,

Regards,

Srinu.V

 

  • Hello Srinu,

    I'll try to make a generic guide: here's a brief summary of how to organize things for your goal:

    1) The timers on TM4C MCU counts internal "clicks", or clock cycles. Normally, these clicks come from the main processor's clock. So basically, counting time (waiting 10 minutes) is a matter of waiting for a certain amount of cycles to happen. There is a "special way" of using the timer, in which the clicks come from the slow crystal (32768Hz), but that won't be the case unless you specifically configure the timer for such.

    2) You need to know how many clock cycles happens in your CPU in one second. The function you mentioned, SysCtlClockSet(), is used to configure that. For the TM4C123 family, there is one function that reads such value, which is SysCtlClockGet().

    3) During your program, you will probably need the system clock value several times. So it is a good idea to read it and store in a global variable.

    uint32_t mySystemClock;

    mySystemClock = SysCtlClockGet();

    4) So let's say now, for example, that your clock was configured to 50MHz, and the value of your variable is 50 000 000. That's the quantity of clock cycles your timer will count in ONE SECOND.

    5) You want to count to 10 minutes... That is 10 x 60 seconds, or 600 seconds. Easy enough. How many clock cycles does that refer to?

    600 x mySystemClock = 30 000 000 000.

    If you can configure your timer load with that amount of cycles, mission accomplished.

    6) Problem: the "normal" timers for ARM M4 are 32 bits. That means the maximum number it can count is 2^32 - 1, or 4 294 967 295. Counting CPU clocks for 10 minutes need a number bigger than that, as you noted. Here are two options:

    7) OPTION1: Accumulate an auxiliary counter. You can, for example, use the timer to trigger once a second, and count the seconds in an external variable. That would mean to configure your timer to trigger after 50 000 000 cycles pass (and automatically start over from zero), and inside the timer interrupt routine, add one second:

    void interruptRoutineWhenTimer1Triggers(void)

    {

    globalElapsedSeconds++;

    if (globalElapsedSeconds >= 600)

     {

     globalElapsedSeconds = 0;

     doSomething();

     }

    }

    Still, note that even 50 million is a big number. Some timers (or actually "half-timers") can count only to 2^16 - 1, so if this is your strategy, make sure you use a 320bit timer.

    8) OPTION2: Particularly for the TM4C123 family, there are WIDE Timers, which can count to 2^64 -1, and that is a huge number. If using a wide timer, you can simply load your timer to that big number that refers to 10 minutes.

    9) Either way, you need to configure the timer once. Here's a configuration example for a 32-bit timer:

       TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);

       TimerLoadSet(TIMER1_BASE, TIMER_A, 50000000);

       TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

       TimerEnable(TIMER1_BASE, TIMER_A);

    (This example will repeatedly call the ISR, once every second)

    10) A few more pointers:

    - Your TIMER1 peripheral must be enabled before trying to configure it.

    - Your system interrupts must be enabled.

    - You need to edit your project's Startup file, so that the interruptRoutineWhenTimer1Triggers() is set as the TIMER1 ISR.

    - Inside your interrupt routine (ISR), you need to clear the interrupt flag (that is true for most of the peripheral interrupt types).

    - It is not good practice to call doSomething() from inside the ISR. The best way is just to set a flag, for example thingCanHappen = TRUE; and on your main loop, constantly check if that thing can happen (don't forget to set thingCanHappen to FALSE after you run it).

    - There is a particularly different way of time scheduling: a simpler ARM Timer called SysTick is configured to trigger every 1 milisecond, and a global variable accumulates the elapsed ms. Whenever you need something to happen at a given moment in the future, calculate which msCounter value will that be, and periodically check that this "time limit" has been reached, then call your event.

    Hope this basic guide is useful for yourself and others.

    Bruno

  • Thank you sir for your valuable suggestion.
    from above your suggestion, i want to use below lines
    TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);

    TimerLoadSet(TIMER1_BASE, TIMER_A, 50000000);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER1_BASE, TIMER_A);


    my code is ---------------

    main()
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);

    TimerLoadSet(TIMER1_BASE, TIMER_A, 50000000);

    IntEnable(INT_TIMER1A);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER1_BASE, TIMER_A);

    while(1)
    {
    led = on;
    led = off;
    }
    }

    from the above code i want to insert the timer delay 10 minutes between led = on; and led = off;
    I request you to please suggest me how to insert timer in between the two instructions.


    Thanks,
    Regards,
    Srinu.
  • Srinu

    I see you did not create the interrupt service routine for the timer. Look at your TIVAWARE example folders, you have to understand how interrupts work, and you need to be able to include a working ISR in your code. Do you know how to import examples from Tivaware? Study the interrupts example (and the timer examples as well, while you are at it).

    I cannot check you code for details, but to achieve your goal, you need to first determine if this is a continuous cycle (10 minutes on, 10 minutes off), or is it a one time only?

    A suggestion for a 1 time only:

    - Execute whatever is "led = on" only once, before the while(1) routine.
    - Increment a "secondsCounter" global variable by 1 every time the timer triggers.
    - Inside the while(), check something like:
    if (secondsCounter >= 600) { LedOff(); }

    Regards

    Bruno

  • Damn Bruno, this needs a Like
  • Thanks, Robert!
    I hope Srinu get backs to us with a successful implementation!
  • In the hope of,  "Speeding, Easing, & (even) Enhancing" such "successful implementation" - the following observation is presented.

    My belief is that a  useful/eased  simplification results from a "simpler" (7 counts vs.  600) recognition.      (post  "3 up" listed 6000 counts - 600 was meant.)

    Seven (7) simple, "roll-overs" of a 32 bit counter produces a ten minute timed duration with  "0.22%" Accuracy!     Such should prove, "Good for G'ovt Work - at least for, "Proof of Concept!"     (and that's always a good idea...)

    Earlier - in another post - word usage arose.     ("some" - for any who care.)

    An earlier post - this thread - listed,   "7) OPTION1:  Accumulate an auxiliary counter"

    Now I fully agree w/Robert's assessment - our poster Bruno has done a very nice job - here.    Yet - "accumulate - as used here - better describes the "CHOSEN Timer's FUNCTION" - the auxiliary counter should - more properly - be "Chosen and/or employed" - its job then - is to  "Accumulate the (other) Timer's  (ideally a  32 bit Timer's) Over-Flows."      

  • One thing that should be taken into account that's not in your proof of concept illustration is that Srinu will not want the function to simply not return for 10 minutes. I can think of no SW where that would be a reasonable action. There will almost certainly need to to be some ability to perform other tasks while this wait is happening and it's very nearly certain there will need to be some ability to abort the wait.

    Robert
  • As you note Robert - poster's always stress their issue as, "simple" - yet that's almost always - FAR from the case!

    What IS simple is posters', "too basic, too limited - grasp of ALL of the impinging issues" - which usually is gleaned through long periods of progressive effort, trial & "hard knocks" experience...

  • Dear sir,

    Thanks for your suggestion.

    In previous code, i just told you example by taking led on and off, actually my application is execute two functions one after another with exact delay of every 10 minutes. I am writing the below code


    main()
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);

    TimerLoadSet(TIMER1_BASE, TIMER_A, 50000000);

    IntEnable(INT_TIMER1A);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER1_BASE, TIMER_A);

    while(1)
    {
    function_1();
    function_2();
    delay (10 minutes); -----------i want to timer delay here for 10 minutes and continue the two functions repeatedly in while loop.
    }
    }

    Here i am not understand how to create timer interrupt for 10 minutes delay for the above code. I know how to add that in startup_ccs.

    I request you to Please send me a sample code for timer interrupt for 10 minutes .



    Thanks,
    Regards,
    Srinu.
  • Hello Srinu,

    If you could provide more details on exactly what you are unclear about, we may be able to guide you further, but right now I am not certain what part of Bruno's very detailed offerings are unclear.

    As far as providing a sample code, we have many TivaWare examples for both timers and interrupts to help facilitate all users in achieving their goals, but we aren't in a position to make unique examples for every use case that comes across through the forums. The same goes for our generous community members who have other responsibilities and likely can't generate such collateral for you as well.

    There is plenty of advice to go from here (hence why I hadn't commented sooner), but again if there are unclear parts, please do ask for clarity on them and we can try and shed further light to assist.
  • Hai sir,

    main()
    {
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);

    TimerLoadSet(TIMER1_BASE, TIMER_A, 50000000);

    IntEnable(INT_TIMER1A);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER1_BASE, TIMER_A);

    while(1)
    {
    function_1();
    function_2();
    delay (10 minutes); -----------i want to timer delay here for 10 minutes and continue the two functions repeatedly in while loop.
    }
    }


    from the above code i want to execute function_1() and function_2() , after execution of two functions then i want to wait my execution of the code in while loop 10 minutes delay and after 10 minutes delay, again goes to function_1() and function_2(); again goes to 10 minutes delay. I want to repeat this continuously.

    In previous i am using for loop like below

    int di;
    for(di = 0; di<600;di++)
    {
    SysCtlDelay(SysCtlClockGet() / 3); // 1 sec delay for 50MHZ clock
    }

    But now i want to use timer interrupt for delay using below lines

    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);

    TimerLoadSet(TIMER1_BASE, TIMER_A, 50000000);

    IntEnable(INT_TIMER1A);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER1_BASE, TIMER_A);


    Here i am not able to understand how to write interrupt code for delay in timer function for 10 minutes.


    I request to you to please suggest me.


    Thanks,
    Regards,
    Srinu.
  • Bravo Ralph!     SO needed to be said.    

    Posters must accept (some) responsibility - and COMMIT to their own, "focused work!"     Such "practice" - often "Trial & Error" - even many such trials - are the pathways to REAL LEARNING.

    Bruno's detailed posts covered "exactly" what poster seeks.    And the added/linked code guidance you supplied - surely - "well guide & direct!"

    Several "Bruno post re-reads" by poster - followed by  "HIS OWN" coding attempts - prove the best means (really the ONLY means) to, "Raise Poster Understanding" - and enable  REAL LEARNING! 

    "Never/Ever achieved"  via the (requested cookbook) [effort-lite]  - "Cut n Paste!"

  • Ralph needs a Like

    Robert
  • This

    Srinu Vakada said:
    while(1)
    {
    function_1();
    function_2();
    delay (10 minutes); -----------i want to timer delay here for 10 minutes and continue the two functions repeatedly in while loop.
    }

    contradicts this

    Srinu Vakada said:
    But now i want to use timer interrupt for delay

    For what you say you want, what would be the advantage of an interrupt?

    BTW you almost certainly do not want the processor to stop responding for 10 minutes but that is what you say you want.

    Robert

  • Dear Sir,

    Actual my application is send the data to server by using GSM module. So here I am using two functions for Data sending to server and another function for read the data from server.so I want to perform this application for every 10 minutes in while loop. That's why I want to create a exact 10 minutes delay by using the timer.

    while(1)
    {
    Data_send();
    Data_Receive();
    delay (10 minutes); -----------i want to timer delay here for 10 minutes and continue the two functions repeatedly in while loop.
    }

    I request you to please suggest me.
  • Srinu Vakada said:
    Actual my application is send the data to server by using GSM module. So here I am using two functions for Data sending to server and another function for read the data from server.

    That nothing else will be needed for 10 minutes seems highly unlikely.

    Srinu Vakada said:
    while(1)
    {
    Data_send();
    Data_Receive();
    delay (10 minutes); -----------i want to timer delay here for 10 minutes and continue the two functions repeatedly in while loop.
    }

    I request you to please suggest me.

    Bruno did that in his first response.

    You could hire a consultant.

    Robert

  • Robert Adsett said:
    You could hire a consultant.

    Do realize - today our Vendor supplied,  "TMP20"  Temp. sensor - reports  Chicago  @  49.4°F.       And ... when reading your (quoted suggestion) ...  "Lightning Flashed  -  Thunder roared!"      (crack weekend staff & cb1 "ducked for cover"  ...    while clutching (more) tightly - our wallets...)

  • Hai sir,


    Thanks to all of your valuable suggestions,
    From all of your suggestions I learned how to develop the code for 1 second delay by using timer. I am getting exact 1 second delay and also i increased the delay up to 1 minute.I am getting exact 1 minute also.I tested this by taking simple LED and tested my code. Now i will put this delay 10 minutes delay into my application code and i will check if it send the data with every 10 minutes or not.


    Thanks,
    Regards,
    Srinu.
  • Do recall - "Just SEVEN "Roll-Over - Interrupts" of a 32bit timer - comes w/in 0.22% of (exactly) TEN Minutes!

    And so much faster/easier than counting 600 "Roll-Over - Interrupts" from 16bit timer...

    Realize too - ALL of those "EXCESS" Interrupt Services will ADD ERROR to your result - "SEVEN Roll-Overs IS - by far - the WAY to GO!"
  • Careful with that route...
    If for some reason you change the CPU clock configuration, your timer goes to buggers.
    If, on the other hand, you configure your counters considering the current clock, you don't rely on a "magic" roll over amount (that may no longer exist).
  • Should poster change MCU clock config - ALL Bets are OFF - unless adjustments are properly made.

    Do not the additive "time costs" extracted by "600" ISRs (not the 6000, most recently posted) become reduced by the factor 600/7 - via the "smaller number of roll-overs?"

    Why would you believe that 7 roll-overs requires (greater) care than 600?
  • cb1_mobile said:
    Why would you believe that 7 roll-overs requires (greater) care than 600?

    Because once you create a solution for waiting for X seconds, you can immediately use it whenever you need.

    On the other hand, when you create a solution for waiting for 10 minutes, you can only use that for waiting 10 minutes, and more specifically, just when the clock is set at 50MHz (which is not even the fastest clock available on this MCU).

    So if I were to count seconds, I'd rather have a global variable counting those seconds, implement a simple ISR called once a second incrementing such variable. The timeout control itself would simply be a comparison to the time limit value, which would be useful for any amount of seconds. Of course the timer load for 1 second verifies the CPU clock during the initial configuration, so the tool will still be good while you are running a TM4C123 at 16MHz or a faster TM4C at 120MHz...

    But to make life simpler and even "less efficient" than the above description: there are MANY MORE things happening in a typical project, lots of them depending on elapsed time - so the basis of any project done here includes a 1ms granularity counter incremented by SysTick rather then by timer (SysTick does not need that the interrupt flags be cleared, which simplifies the ISR content). For easier coding, a macro SYSTEM_COUNTER_MS points to that global variable.

    OP's mission would be accomplished by the following piece of code:

    {

    uint32_t timeExpire = 0;

    DataSend();

    DataReceive();

    timeExpire = SYSTEM_COUNTER_MS + 600000;

    while(SYSTEM_COUNTER_MS < timeExpire){}

    }

    Running a CPU @50MHz, we have 50,000 cycles every mili-second. "Wasting" some 30 cycles to detour/increment a global counter represents 0.06% of the processing power in exchange of having permanent ms counting in the system! Good or bad?

    Regards

    Bruno

  • My friend - we stand in "High Disagreement" - proceed as you wish.

    As to your Systick suggestion (over a regular Timer) - is not Systick subject to "unavoidable time variations" - which "Argue against its use" when "critical timing IS required?"

    Your description of my "suggested method" enforces "limitations" - never constrained by such method. Being trained in logic & argumentation - I am not overly impressed w/the "evidence" you present.

    You have "well assisted" this poster - but the "support" now presented is outside my interest...
  • Greetings cb1

    cb1_mobile said:
    is not Systick subject to "unavoidable time variations"

    What do you mean???

    SysTick is driven by system clock - so as the regular timers.

    A SysTick configured to generate an interrupt every 50,000 cycles will generate an interrupt after... well... 50,000 cycles. Not one more, not one less. And it is by default set at a higher priority, so whatever happens inside its ISR is even more likely to be "real time".

    Maybe you were thinking of SysCtlDelay()?

    Bruno

  • We noted such SysTick issue in an ARM document - millennial staff searching now.

    We confirmed such upon another's ARM M7 - w/in the past 2 months - which is how I "recalled." I'll post when the crüe locate - and can present their findings...

    I'm home w/injured foot - "under the influence" but alert enough to "not" confuse w/"SysCtlDelay()!"    (Maybe, one hopes ... I am warned, "Not to operate heavy machinery" (like anyone of sound mind would trust moi - w/heavy machinery) yet your suggestion of the similarly named, "SysCtlDelay()" WAS inspired...)       ***  LIKE  ***

  • Appreciated the ***LIKE***

    SysTick is really "deep in the core" of these silicons, not even implemented by TI but rather by the ARM "part" of our MCU's. A failure in such a basic hardware implemented counter is highly unexpected. A (non-conclusive but suggestive) search for Systick Errata or Systick Issue returns nothing factual. SysTick has been counting pulses for decades and it does a good job at it - again, natively with higher priority over all the TI's peripherals, and without the need for clearing a flag inside the ISR, two attractive reasons for its use.

    Je suis desolee, but your millennial crüe won't be able to get your back on this one, mon ami.

    For those paying attention, don't get too excited to use SysTick for "all my upcoming delay projects" - the maximum load value is 2^24, which is not even a second in a slowly configured TM4C123. It is better served with an incrementing global variable.

    Bruno
  • Sir,

    Here may i know what is the initial value of SYSTEM_COUNTER_MS ??


    Regards,
    Srinu.
  • Srinu,
    I'm not sure if I understand the relevance of this question, but the initial value is zero. That's a variable we use to count elapsed miliseconds from power up.
    Regards
    Bruno
  • Sir,

    I am implemented this code from the example for glowing LED ON/ OFF for every 10 minutes.


    volatile uint32_t millis = 0;


    void SysTickInt(void)
    {
    uint32_t status=0;

    status = TimerIntStatus(TIMER0_BASE,true);
    TimerIntClear(TIMER0_BASE,status);
    millis++;
    }

    void Wait (uint32_t number)
    {
    volatile uint32_t temp = millis;
    while ( (millis-temp) < number);
    }


    int main()

    {
    SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlDelay(3);

    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, 50000000);

    TimerIntRegister(TIMER0_BASE, TIMER_A, SysTickInt);

    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER0_BASE, TIMER_A);

    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2);

    while(1)
    {
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, GPIO_PIN_1);
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2, ~GPIO_PIN_2);

    Wait(600); // for 600 seconds delay

    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2, GPIO_PIN_2);
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, ~GPIO_PIN_1);

    Wait(600); // for 600 seconds delay
    }
    }


    Is it fine to use in my application sending and receiving data with delay of 10 minutes.


    Regards,
    Srinu.
  • Srinu,

    While I can see your code works, here are some suggestions to refine it:

    - Do not name your Timer0 ISR "SysTickInt()". That name suggests a different timer. You should name it something like Timer0ISR().
    - Do not name your seconds variable counter "millis". Such variable is counting seconds, not miliseconds, so the chosen name ain't that convenient.
    - Do not use SysCtlDelay after SysCtlPeripheralEnable. It is true that a peripheral needs some time to be ready, but the proper way of waiting for it to be ready is by using while(SysCtlPeripheralReady()).
    - On your TimerLoadSet you are using a hard coded value of 50000000. That number is correct for your particular clock setting, but it is more elegant if you store the clock setting in a variable at the beginning of your code (something like systemClockHz), and use the variable on your timer load (again, it makes no functional difference - but if you decide to reconfigure your CPU to work at 80MHz, the code will still work perfectly without any further concerns).
    - Inside your wait function, you could make the calculation just once, before the while. Something like "expireTime = millis + temp", and then "while(millis < expireTime)". Also it makes no difference here, because your MCU is not doing anything else, but it is just a "good practice" that requires much less processing, and the calculated value won't need to be volatile.

    Regards

    Bruno

  • Sir,

    Thank you so much for all your suggestions. I developed the code for LED ON and OFF for every 10 minutes delay by using timer .Now i applied to my main application its working fine, Data is sending to server with exact delay of every 10 minutes.
    I developed by learning your valuable suggestions from you all and examples from tiva tutorials.

    Regards,
    Srinu.
  • Thank you for the feedback and for your kind words.
    Bruno
  • There are a few questions that you have to answer first.

    For example if you anticipate the code to be blocking. It seems yes but blocking for so long isn't terribly wise.

    Then you have a question of which times to use. In my applications I typically have systick running to provide a free time stamp. That can be used here.

    You also have 16 or 32 or 64bit timers, with prescalers. The task is simple with a 32 or more bit timers. With 16 bit timers it needs a little bit programming. But nothing fancy.

    Then you have dwt - a 32bit free running counter. Rarely used by folks but exceedingly useful.

    Then you have a question of how much jitter you need. You can program a cycle precise delay. Alternatively, you can build your code on smaller delays. For example, you can write a piece that delays a second. From that, write a piece that delays a minute, and from that get your 10 delays...

    Happy to provide some code examples to get you going.

  • here is what I would do, to implement a "blocking" delay routine over a 16-bit split timer (TIMER2 in this particular case.

    1. initialize timer2 into a 16-bit split timer. I picked 1x prescaler and top at 0xffff - it doesn't matter for our application.

    //global defines
    #define TMRx				TIMER2					//we use timer2 as timebase
    
    //global variables
    
    //reset timer2a - split timer
    //16/32-bit timer: 8-bit prescaler, 16-bit period register
    void tmr2a_init(uint32_t ps, uint32_t pr) {
    	//_isrptr_tmra = empty_handler;
    
    	//route the clock
    	SYSCTL->RCGCTIMER |= (1<<2);					//1->route clock. TIMER0/1/2/3/4/5
    
    	//stop the timer
    	TMRx->CTL &=~(1<<0);							//0->disable timer, 1->enable timer
    	//configure the timer, split, upcounter
    	TMRx->CFG  = 0x04;								//0x00->32/64bit, 0x01->rtc, 0x02-0x03->reserved, 0x04->16/32bit split timers
    	TMRx->TAMR = 	(0<<11) |						//0->legacy ops
    					(0<<10) |						//0->update match register on the next cycle, 1->update match register now
    					(0<< 9) |						//0->pwm interrupt disabled, 1->pwm interrupt enabled
    					(0<< 8) |						//0->update load register ont he next cycle; 1->update load register now
    					(0<< 7) |						//0->disable snap shot, 1->enable snap shot
    					(0<< 6) |						//0->timer counts right away; 1->timer waits on trigger before counting
    					(0<< 5) |						//0->match interrupt disabled, 1->match interrupt enabled
    					(1<< 4) |						//0->counts down, 1->counts up
    					(0<< 3) |						//0->capture / compare enabled 1->pwm enabled
    					(0<< 2) |						//0->edge count for capture; 1->edge time for capture
    					(0x02) |						//0x00->reserved, 0x01->one shot, 0x02->periodic, 0x03->capture
    					0x00;
    
    	//set the prescaler
    	TMRx->TAPR = (ps - 1) & 0xff;							//set the prescaler
    	TMRx->TAILR= (pr - 1) & 0xffff;							//set the top
    	//reset counter
    	TMRx->TAR = 0;
    
    	//clear ISR flags, disable isr
    	//disable all interrupt
    	TMRx->IMR &=~(0x1f << 0);						//0->disable time-out interrupt, 1->enable time-out interrupt
    	TMRx->ICR |= (0x1f << 0);						//1->clear interrupt flag, 0->no effect
    
    	//start the timer
    	TMRx->CTL |= (1<<0);							//0->disable timer, 1->enable timer
    }
    

    2. delay64() provide a cycle-accurate delay, with a 64-bit parameter. Practically limit less.

    //user tmrx to delay 64-bit
    //timebase specified by TMRx above
    //assume initialized as a 16-bit timer
    char delay64(uint64_t ticks) {
    	TMRx->TAR = 0;									//reset timer counter
    	TMRx->TAILR= (ticks & 0xffff);					//set the top
    	TMRx->ICR = (1<<0);								//reset interrupt flag
    	while ((TMRx->RIS & 0x01) == 0) continue;		//wait for the timer to overflow
    	ticks = ticks &~0xffff;							//mask off the lowest 16-bit
    	TMRx->TAILR= 0xffff;							//top at 0x10000
    	while (ticks -= 0x10000ul) {
    		TMRx->ICR = (1<<0);							//clera the flag
    		while ((TMRx->RIS & 0x01) == 0) continue;	//wait for the timer to overflow
    	};
    	return 1;
    }
    

    3. Passing a 64-bit parameter to delay64() will provide the desired delay. Each "SystemCoreClock" equates to 1 second of delay. "SystemCoreClock" is defined as part of the CMSIS framework.

    //example: delay 2.5 seconds
    #define LED_DLY				(SystemCoreClock * 2.5)	//long delay cycle count, 1 SystemCoreClock = 1 second
    
    //main loop
    
    	//configure tmrx
    	tmr2a_init(1, 0xffff);							//initialize tmr2a as 16-bit split timer
    
    	//ei();											//enable interrupts
    	while(1) {
    		IO_FLP(LED_PORT, LED);						//flip the led
    		delay64(LED_DLY);							//waste sometime
    	}
    
    

    tested to work on LM4F120.

  • You have made a good effort here - thanks for that.     In this thread's  (now 35 post deep) case though - poster has,  "Signaled his acceptance" of  "fellow poster Bruno's direction" - even awarding the "Resolved my Issue"  post highlight.

    May it be noted that you (properly, I believe) appeared to challenge the "blocking delay" (unacceptable in most any "real-world" App.) - yet then proceeded to present (another) blocking code example.    

    Much of your code employs the,  "Long out of favor here/elsewhere - "DRM" coding method" - which is noted as inefficient & error inducing.      And certainly never as useful as this vendor's  expansive and,  "TRIED, TRUE,  Terrifically TESTED"  API.     (while you note "your test" (upon an EOL MCU) such "one person test"  - cannot  "hope to compare" -  w/the test by "thousands" (perhaps tens of thousands) as experienced by the vendor's (extensive) API.   

    Your expertise & "desire to assist" are noted - yet there (Do exist) multiple "Unanswered Posts" - which would appear to "better warrant attention..."      (again - this thread had been (long marked) "Resolved!")

  • Hai sir,
    According to suggestions and tiva tutorial, I made my code like below for 600 seconds.


    volatile uint32_t sec = 0;


    void timer0intHandler(void)
    {
    uint32_t status=0;

    status = TimerIntStatus(TIMER0_BASE,true);
    TimerIntClear(TIMER0_BASE,status);
    sec++;
    }

    void Wait (uint32_t number)
    {
    volatile uint32_t temp = sec;
    while ( (sec-temp) < number);
    }


    int main()

    {
    SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, system clockGet());

    TimerIntRegister(TIMER0_BASE, TIMER_A, timer0intHandler);

    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    TimerEnable(TIMER0_BASE, TIMER_A);

    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2);

    while(1)
    {
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, GPIO_PIN_1);
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2, ~GPIO_PIN_2);

    Wait(600); // for 600 seconds delay

    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2, GPIO_PIN_2);
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, ~GPIO_PIN_1);

    Wait(600); // for 600 seconds delay
    }
    }


    Regards,
    Srinu.
  • your approach will work, conceptually - i didn't actually test your code.

    Note, however, the timing will have jitter: +/- about 1 second, at maximum.

    One way to reduce that is to advance at a faster pace. for example, interrupts at "SystemClockGet() / 10" (100ms), or even "SystemClockGet() / 100" (10ms).

    with that said, I would strongly suggest a SysTick-based approach, or a DWT based approach, even if those chips have a gazillion of timers. or a 64-bit timer based approach for simplicity.
  • a quick follow-up on the use of DWT of a timer here:

    //use DWT for timing
    //return a flag: 1-> time is up, 0-> time not exhausted yet
    char delay64DWT(uint64_t ticks64) {
    	static uint64_t ticks64_prev = 0;				//previous coreticks, 64-bit
    	static uint64_t ticks64_now = 0;				//64-bit ticks
    	static uint32_t ticks_prev=0;					//previous coreticks, 32-bit
    	uint32_t ticks_now;								//32-bit ticks
    
    	//time stamp current ticks - 32-bit
    	ticks_now = DWT->CYCCNT;						//coreticks();				//read off DWT cycle counter (32-bit)
    	ticks64_now += (ticks_now > ticks_prev)?(ticks_now - ticks_prev):((0x1ull << 32) - (ticks_prev - ticks_now));		//for 32-bit roll-over
    	//alternative 1: this will work if 16-bit timer2a is used as time base
    	//ticks_now = TMRx->TAR;						//16-bit timer2a as time base
    	//ticks64_now += (ticks_now > ticks_prev)?(ticks_now - ticks_prev):((0x1ull << 16) - (ticks_prev - ticks_now));		//for 32-bit roll-over
    	//alternative 2: use systick (24-bit
    	//ticks_now = SysTick->VAL;						//24-bit systick as time base
    	//ticks64_now += (ticks_now > ticks_prev)?(ticks_now - ticks_prev):((0x1ull << 24) - (ticks_prev - ticks_now));		//for 32-bit roll-over
    
    	//time stamp current ticks - 64-bit
    	ticks_prev = ticks_now;							//update ticks_prev
    	if ((ticks64_now - ticks64_prev) < ticks64) return 0;
    	else {ticks64_prev = ticks64_now; return 1;}		//time is up
    }
    

    the above code provides three alternatives:

    1. use DWT as a counter. it is a 32-bit counter;

    2. use a 16-bit timer as a counter; code commented out

    3. use systick as a conter; 24-bit wide.

    the function returns 1 when the desired time (measured in ticks) has passed. 0 otherwise.

    		if (delay64DWT(LED_DLY)) IO_FLP(LED_PORT, LED);						//flip the led
    

    in this case, it flips an led when LED_DLY has expired.

    tested to work on LM4F120. and should work on any CM3/4/4F/7 chips with DWT, or any CMx chips if Systick is used as the timebase.

    The point is to show that there are many ways of doing the same thing. No reason to restrict yourself to one particular approach.