Actions

EmSys

Difference between revisions of "Using Systick Timer with TM4C123GH6PM Launchpad"

From EdWiki

(One Second Delay)
m (Tasks)
 
(35 intermediate revisions by the same user not shown)
Line 31: Line 31:
 
#Systick Control and Status Register ('''STCTRL''')
 
#Systick Control and Status Register ('''STCTRL''')
 
#Systick Current Value ('''STCURRENT''')
 
#Systick Current Value ('''STCURRENT''')
 +
 +
=== Systick Reload Value Register ===
 +
 +
:This register acts like a bucket filled with a liquid that will be empty after some time duration and we will get acknowledgement by a change in flag bit in STCTRL Register. This register is 24 bit wide.
 +
 +
[[image:tm4c_systick_streload_r.png|center]]
 +
 +
Since this register is 24 bit wide it can store upto 0xFFFFFF or 16777215. when we load any value into this register and trigger the timer it starts to count down and when the value reaches to 0 it sets the COUNT FLAG. We will see how to reload and check flag bit in the next few steps.
 +
 +
=== Systick control and Status register ===
 +
:This register is shown in the following figure
 +
 +
[[image:tm4c_systick_stctl_r.png|center]]
 +
 +
{| class="wikitable" style="margin: auto; border-style: solid; border-width: 4px"
 +
|-
 +
! Bit !! Name !! Description
 +
|-
 +
| 0 || Enable || <u>Enable</u><br />0: the counter is disabled<br />1: enables SysTick to begin counting Down
 +
|-
 +
| 1 || INTEN || <u>Interrupt Enable</u><br />0: Interrupt generation is disabled<br />1: when SysTick counts to 0 an interrupt is generated
 +
|-
 +
| 2 || CLK_SRC || <u>Clock Source</u><br />0: Precision internal oscillator (PIOSC) divided by 4<br />1: System clock
 +
|-
 +
| 16 || COUNT || <u>Count Flag</u><br />0: the SysTick has not counted Down to zero since the last time this bit was read<br />1: the SysTick has counted Down to Zero<br />'''Note''': this flag is cleared by reading the STRCTL or writing to STCURRENT Register
 +
|}
 +
 +
We need to set our main clock to system clock by setting '''CLK_SRC''' to '''1'''. And we don’t want interrupt method so '''INTEN''' bit will be '''0'''. Now we are going to trigger our timer by writing '''ENABLE''' bit '''1''' so writing 0x5 will trigger our timer at the same time it will also set the configuration. Now the loaded value will be started to count down. When the timer gets rollover the bit 16 will set to one. hence we need to monitor 16th bit.
 +
 +
If INTEN=1, when the COUNT flag is set, it causes an interrupt via the NVIC. INTEN is D1 of the STCTRL register.
 +
 +
=== Systick Register Summary ===
  
 
{| class="wikitable"  
 
{| class="wikitable"  
Line 42: Line 74:
 
| $E000E018 || o || style="text-align:center;" colspan="6"|24-bit CURRENT value of SysTick counter || NVIC_ST_CURRENT_R
 
| $E000E018 || o || style="text-align:center;" colspan="6"|24-bit CURRENT value of SysTick counter || NVIC_ST_CURRENT_R
 
|}
 
|}
 
'''Systick Reload Value Register'''
 
 
:This register acts like a bucket filled with a liquid that will be empty after some time duration and we will get acknowledgement by a change in flag bit in STCTRL Register. This register is 24 bit wide.
 
 
[[image:tm4c123_systic_streload.png]]
 
 
Since this register is 24 bit wide it can store upto 0xFFFFFF or 16777215. when we load any value into this register and trigger the timer it starts to count down and when the value reaches to 0 it sets the COUNT FLAG. We will see how to reload and check flag bit in the next few steps.
 
  
 
== Delay time calculation ==
 
== Delay time calculation ==
  
Since we are working with external clock i.e. 16 MHz, each pulse generated by the clock source will have  
+
Since we are working with external clock i.e. 16 MHz, each pulse generated by the clock source will have:
  1/XTAL frequency = 1/(16*10^6) = 2.5 ns
+
  1/XTAL frequency = 1/(16*10^6) = 62.5ns time period.  
time period. so if we load 253 into the RELOAD register it and trigger the counter it will count down with next pulse and will take 2.5ns to change its value from 253 to 252. Hence, In order to generate the delay, we can calculate the approximate value that has to be loaded into this register by the formula-
+
So if we load 253 into the RELOAD register and trigger the counter it will count down with next pulse and will take 62.5ns to change its value from 253 to 252. Hence, In order to generate the delay, we can calculate the approximate value that has to be loaded into this register by the formula-
 
  Reload Value = XTAL*Time delay
 
  Reload Value = XTAL*Time delay
 
one extra clock delay is already included to set the flag for rollover, hence we get one extra clock delay. By subtracting by one will give exact time delay.
 
one extra clock delay is already included to set the flag for rollover, hence we get one extra clock delay. By subtracting by one will give exact time delay.
 
  Reload Value = (XTAL*Time Delay)-1
 
  Reload Value = (XTAL*Time Delay)-1
 
Remember that in one shoot, it can only take 0xFFFFFF maximum value. Therefore in one shoot, we can only generate maximum of Time delay
 
Remember that in one shoot, it can only take 0xFFFFFF maximum value. Therefore in one shoot, we can only generate maximum of Time delay
  TimeDelay = (ReloadValue +1)/XTAL= 16777215+(1/(16*10^6))
+
  TimeDelay = (ReloadValue+1)/XTAL=16777215+(1/(16*10^6))
  TimeDelay = 1.048 sec.
+
  TimeDelay = 1.048575937 sec.
  
'''Systick control and Status register'''
+
'''Example''': For generating 1 sec of delay the value that has to be loaded into the RELOAD Register
:This register is shown in the following figure
+
Reload Value = (XTAL*Time delay)-1
 +
Reload Value = (16*10^6*1)-1
 +
Reload Value = 15999999
  
[[image:tm4c123_systic_stctrl.png]]
+
== SysTick timer Initialization ==
 +
There are four steps to initialize the SysTick timer.
 +
# Clear the ENABLE (NVIC_ST_CTRL_R) bit to turn off SysTick during initialization.
 +
# Set the RELOAD (NVIC_ST_RELOAD_R) register.
 +
# Write to the NVIC_ST_CURRENT_R value to clear the counter.
 +
# Write the desired mode to the control register, NVIC_ST_CTRL_R.
 +
#* Set the CLK_SRC bit specifying the core clock will be used.
 +
#* We must set CLK_SRC=1 bit specifying the core clock will be used, because CLK_SRC=0 external clock mode is not implemented on the LM3S/TM4C family.
 +
#* Set INTEN (NVIC_ST_CTRL_R) to enable interrupts, but in this first example we clear INTEN so interrupts will not be requested.
 +
#* Set the ENABLE (NVIC_ST_CTRL_R) bit so the counter will run.
  
We need to set our main clock to external by setting '''CLK_SRC''' to '''1'''. And we don’t want interrupt method so '''INTEN''' bit will be '''0'''. Now we are going to trigger our timer by writing '''ENABLE''' bit '''1''' so writing 0x5 will trigger our timer at the same time it will also set the configuration. Now the loaded value will be started to count down. When the timer gets rollover the bit 16 will set to one. hence we need to monitor 16th bit.
+
When the CURRENT (NVIC_ST_CURRENT_R) value counts down from 1 to 0, the COUNT flag is set. On the next clock, the CURRENT is loaded with the RELOAD value. In this way, the SysTick counter (CURRENT) is continuously decrementing. If
 +
the RELOAD value is n, then the SysTick counter operates at modulo n+1 (...n, n-1, n-2 ... 1, 0, n, n-1, ...). In other words, it rolls over every n+1 counts.
  
'''Example''': For generating 1 sec of delay the value that has to be load into the RELOAD Register
+
The COUNT flag could be configured to trigger an interrupt. However, in this first example interrupts will not be generated.
= (XTAL*Time delay)-1
+
= (16*10^6*1)-1
+
= 15999999
+
So our code for generating delay of one second will looks like
+
  
== SysTick timer Initialization ==
+
== Source Code ==
  
There are four steps to initialize the SysTick timer:
+
=== Delay in 62.5ns units ===
# Clear the ENABLE bit to turn off SysTick during initialization.
+
<syntaxhighlight lang="c" line start="1">
# Set the RELOAD register.
+
/* delay is in 62.5ns units */
# Write to the NVIC_ST_CURRENT_R value to clear the counter.
+
void SysTick_Wait(uint32_t delay)
# We write the desired mode to the control register, NVIC_ST_CTRL_R. We set the CLK_SRC bit specifying the core clock will be used. CLK_SRC=0 internal oscillator mode.
+
{
 +
    NVIC_ST_CTRL_R = 0;            /* (1) disable SysTick during setup */
 +
    NVIC_ST_RELOAD_R = delay-1;    /* (2) number of counts to wait */
 +
    NVIC_ST_CURRENT_R = 0;        /* (3) any value written to CURRENT clears */
 +
    NVIC_ST_CTRL_R |= 0x5;        /* (4) enable SysTick with core clock */
 +
   
 +
    while((NVIC_ST_CTRL_R&0x00010000)==0) {
 +
        ;                          /* wait for COUNT flag */
 +
    }
 +
}
 +
</syntaxhighlight>
  
There are four steps to initialize the SysTick timer. First, we clear the ENABLE bit to turn
+
<!--
off SysTick during initialization. Second, we set the RELOADregister. Third, we write to
+
=== Delay in 10ms units ===
the NVIC_ST_CURRENT_R value to clear the counter. Lastly, we write the desired
+
<syntaxhighlight lang="c" line start="1">
mode to the control register, NVIC_ST_CTRL_R . We set the CLK_SRC bit specifying
+
/* Delay is in 10ms units */
the core clock will be used. We must set CLK_SRC=1
+
void SysTick_Wait10ms(uint32_t delay)
 +
{
 +
    uint32_t i;
  
== One Second Delay ==
+
    for(i=0; i<delay; i++) {
 +
        SysTick_Wait(160000);      /* 160000*62.5ns equals 10ms */
 +
    }
 +
}
 +
</syntaxhighlight>
 +
-->
 +
 
 +
=== One Second Delay ===
 
<syntaxhighlight lang="c" line start="1">
 
<syntaxhighlight lang="c" line start="1">
 
void One_Second_Delay(void)
 
void One_Second_Delay(void)
 
{
 
{
     NVIC_ST_RELOAD_R = 15999999;    // Reload Value goes here
+
    NVIC_ST_CTRL_R = 0;            /* disable SysTick during setup */
     NVIC_ST_CTRL_R |= 0x5;          // Triggering with external clock
+
     NVIC_ST_RELOAD_R = 15999999;    /* Reload Value goes here */
 +
     NVIC_ST_CTRL_R |= 0x5;          /* enable SysTick with core clock */
 
     while( (NVIC_ST_CTRL_R & (1<<16) ) == 0)
 
     while( (NVIC_ST_CTRL_R & (1<<16) ) == 0)
         ;                          // Monitoring bit 16 to be set
+
         ;                          /* Monitoring bit 16 to be set */
     NVIC_ST_CTRL_R = 0;            //Disabling SysTick Timer
+
     NVIC_ST_CTRL_R = 0;            /* Disabling SysTick Timer */
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 171: Line 223:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
-->
 
-->
 +
 +
== See Also ==
 +
* [[EmSys:TM4C123 Using SysTick with Interrupt | Using SysTick with Interrupt]]

Latest revision as of 04:50, 3 March 2020

Using Systick Timer with TM4C123GH6PM Launchpad

So far we have learned that how to program general purpose input output(GPIO) of ARM Cortex M-4. But we have not generated the delay in micro controller. In this section we will generate delay using different methods and blink on board LEDs. There are two types of delays that can be generated by our program:

  1. Software delay
  2. Hardware delay

Software delay

This type of delay is nothing but making the controller busy, doing the task which will occupy a certain duration. For example if we want our friend to wait for us then instead of telling him to wait we can simply engage him in other task. But the generated time may or may not be so accurate.

Example: In C code if we can use this for loop for generating a delay of 1 second.

  1.  void delay_1sec(void)
  2.  {
  3.     for( unsigned long i = 0; i <= 3000000; i++ )
  4.         ;
  5.  }

This method doesn’t generate the accurate time delay, but approximate. For generation of accurate delay in microsecond we prefer hardware delay.

Hardware delay

The hardware delay is most precise method to generate delay. In this method we use timer which is the most popular and useful feature of microcontrollers. Generally delay with timer is like waiting a bucket to be empty if we make a small hole to leak its filled liquid more the liquid more time it will take to empty the bucket. In this article, we are going to use a special timer called systick timer. In our micro controller we have six 64 bit and six 32 bit timer excluding systick timer. This timer is very useful and plays very important role in RTOS design. We will see other timers later. In our micro controller, Systick timer is 24 bit wide. For the generation of delay, at first we need to make sure that our controller is working on the clock frequency as we are expecting. This step is required to select the clock source only at external crystal without PLL.

SysTick Timer

SysTick is a simple counter that we can use to create time delays and generate periodic interrupts. It exists on all Cortex-M microcontrollers, so using SysTick means the system will be easy to port to other microcontrollers.

SysTick Timer Internal Structure

As we learned earlier that modifying registers are the key for configuration and desired functionality. Hence systick timer can be used by modifying these registers.

  1. Systick Reload value (STRELOAD)
  2. Systick Control and Status Register (STCTRL)
  3. Systick Current Value (STCURRENT)

Systick Reload Value Register

This register acts like a bucket filled with a liquid that will be empty after some time duration and we will get acknowledgement by a change in flag bit in STCTRL Register. This register is 24 bit wide.
Tm4c systick streload r.png

Since this register is 24 bit wide it can store upto 0xFFFFFF or 16777215. when we load any value into this register and trigger the timer it starts to count down and when the value reaches to 0 it sets the COUNT FLAG. We will see how to reload and check flag bit in the next few steps.

Systick control and Status register

This register is shown in the following figure
Tm4c systick stctl r.png
Bit Name Description
0 Enable Enable
0: the counter is disabled
1: enables SysTick to begin counting Down
1 INTEN Interrupt Enable
0: Interrupt generation is disabled
1: when SysTick counts to 0 an interrupt is generated
2 CLK_SRC Clock Source
0: Precision internal oscillator (PIOSC) divided by 4
1: System clock
16 COUNT Count Flag
0: the SysTick has not counted Down to zero since the last time this bit was read
1: the SysTick has counted Down to Zero
Note: this flag is cleared by reading the STRCTL or writing to STCURRENT Register

We need to set our main clock to system clock by setting CLK_SRC to 1. And we don’t want interrupt method so INTEN bit will be 0. Now we are going to trigger our timer by writing ENABLE bit 1 so writing 0x5 will trigger our timer at the same time it will also set the configuration. Now the loaded value will be started to count down. When the timer gets rollover the bit 16 will set to one. hence we need to monitor 16th bit.

If INTEN=1, when the COUNT flag is set, it causes an interrupt via the NVIC. INTEN is D1 of the STCTRL register.

Systick Register Summary

Address 31-24 23-17 16 15-13 2 1 0 Name
$E000E010 o 0 COUNT 0 CLK_SRC INTEN ENABLE NVIC_ST_CTRL_R
$E000E014 o 24-bit RELOAD value NVIC_ST_RELOAD_R
$E000E018 o 24-bit CURRENT value of SysTick counter NVIC_ST_CURRENT_R

Delay time calculation

Since we are working with external clock i.e. 16 MHz, each pulse generated by the clock source will have:

1/XTAL frequency = 1/(16*10^6) = 62.5ns time period. 

So if we load 253 into the RELOAD register and trigger the counter it will count down with next pulse and will take 62.5ns to change its value from 253 to 252. Hence, In order to generate the delay, we can calculate the approximate value that has to be loaded into this register by the formula-

Reload Value = XTAL*Time delay

one extra clock delay is already included to set the flag for rollover, hence we get one extra clock delay. By subtracting by one will give exact time delay.

Reload Value = (XTAL*Time Delay)-1

Remember that in one shoot, it can only take 0xFFFFFF maximum value. Therefore in one shoot, we can only generate maximum of Time delay

TimeDelay = (ReloadValue+1)/XTAL=16777215+(1/(16*10^6))
TimeDelay = 1.048575937 sec.

Example: For generating 1 sec of delay the value that has to be loaded into the RELOAD Register

Reload Value = (XTAL*Time delay)-1
Reload Value = (16*10^6*1)-1
Reload Value = 15999999

SysTick timer Initialization

There are four steps to initialize the SysTick timer.

  1. Clear the ENABLE (NVIC_ST_CTRL_R) bit to turn off SysTick during initialization.
  2. Set the RELOAD (NVIC_ST_RELOAD_R) register.
  3. Write to the NVIC_ST_CURRENT_R value to clear the counter.
  4. Write the desired mode to the control register, NVIC_ST_CTRL_R.
    • Set the CLK_SRC bit specifying the core clock will be used.
    • We must set CLK_SRC=1 bit specifying the core clock will be used, because CLK_SRC=0 external clock mode is not implemented on the LM3S/TM4C family.
    • Set INTEN (NVIC_ST_CTRL_R) to enable interrupts, but in this first example we clear INTEN so interrupts will not be requested.
    • Set the ENABLE (NVIC_ST_CTRL_R) bit so the counter will run.

When the CURRENT (NVIC_ST_CURRENT_R) value counts down from 1 to 0, the COUNT flag is set. On the next clock, the CURRENT is loaded with the RELOAD value. In this way, the SysTick counter (CURRENT) is continuously decrementing. If the RELOAD value is n, then the SysTick counter operates at modulo n+1 (...n, n-1, n-2 ... 1, 0, n, n-1, ...). In other words, it rolls over every n+1 counts.

The COUNT flag could be configured to trigger an interrupt. However, in this first example interrupts will not be generated.

Source Code

Delay in 62.5ns units

  1. /* delay is in 62.5ns units */
  2. void SysTick_Wait(uint32_t delay)
  3. { 
  4.     NVIC_ST_CTRL_R = 0;            /* (1) disable SysTick during setup */
  5.     NVIC_ST_RELOAD_R = delay-1;    /* (2) number of counts to wait */
  6.     NVIC_ST_CURRENT_R = 0;         /* (3) any value written to CURRENT clears */
  7.     NVIC_ST_CTRL_R |= 0x5;         /* (4) enable SysTick with core clock */
  8.  
  9.     while((NVIC_ST_CTRL_R&0x00010000)==0) {
  10.         ;                          /* wait for COUNT flag */
  11.     }
  12. }


One Second Delay

  1. void One_Second_Delay(void)
  2. {
  3.     NVIC_ST_CTRL_R = 0;            /* disable SysTick during setup */
  4.     NVIC_ST_RELOAD_R = 15999999;    /* Reload Value goes here */
  5.     NVIC_ST_CTRL_R |= 0x5;          /* enable SysTick with core clock */
  6.     while( (NVIC_ST_CTRL_R & (1<<16) ) == 0)
  7.         ;                           /* Monitoring bit 16 to be set */
  8.     NVIC_ST_CTRL_R = 0;             /* Disabling SysTick Timer */
  9. }


See Also