How to configure and use SysTick Timer Interrupt in PSoC5?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
ShVy_264716
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Hi All.

I want to configure a SysTick Timer in such a way that the SysTick Timer Interrupt should invoke every 1 ms. I am using 

CY8CKIT-059 PSoC® 5LP Prototyping Kit. 

In PSoC 4, I did this same functionality by using the following code :

 

 

 

 

#define NO_OF_TICKS 24000u
int *tick_CM0_ENABLE = (int *) CYREG_CM0_SYST_CSR;
uint32  SysTick_value;
CY_ISR_PROTO(MySysTickHandler);
void SysTick_Timer_Enable(void);     //Enabling SysTick Timer
void SysTick_Timer_Disable(void);    //Disabling SysTick Timer

void SysTick_Timer_Enable(void){
    *tick_CM0_ENABLE |= 1; // For Enabling the Tick Counter
    /* Enable SysTick timer with desired period/number of ticks */
    SysTick_Config(NO_OF_TICKS);
}    

void SysTick_Timer_Disable(void){
    
    *tick_CM0_ENABLE &= (~1); // For Disabling the Tick Counter    
}    
void Initialize(void)
{
    CyGlobalIntEnable;                                              
    CyIntSetSysVector((SysTick_IRQn + 16u), MySysTickHandler);
    SysTick_value = 0;
}
void main(void)
{
    Initialize();
}
CY_ISR(MySysTickHandler)
{
    SysTick_value++;
    if(SysTick_value >= 1000u)
    {
        SysTick_value = 0;
        SysTick_Timer_Disable(); // Stop after 1000 ms
    }    
}

 

 

 

 

I do not know why but this method does not work for PSoC5. 

0 Likes
1 Solution
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

ShVy,

I haven't verified your code listed in your first post.   However, using the SysTick is fairly easy. 

Here is working SysTick code I use ALL the time on my PSo5LP projects:

uint32_t systick = 0;
uint32_t systick_prev = 0;
CY_ISR(isr_systick)
{
	systick++;
}
/* Your Application here vvvv */
main(void)
{
...
/* SysTick init */
  CySysTickStart();  /* Start the systick */
  CySysTickSetCallback(0, isr_systick);  /* Add the Systick callback */
      /* to the standard SysTick Int Vector */
/*****/
...   /* other stuff you need to init */
/* SysTick use in the Application */
  for(;;)
  {
/* Wait for the previous SysTick event plus a set delay */
    if(systick >= (systick_prev + 1000)) 
    {    /* SysTick event occurred.  Process SysTick event in the App. */
      systick_prev = systick;    /* Set the new previous SysTick count */
      ...
      /* go do something within the systick event */
      ...
    }
}

 

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

0 Likes
5 Replies
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

ShVy,

I haven't verified your code listed in your first post.   However, using the SysTick is fairly easy. 

Here is working SysTick code I use ALL the time on my PSo5LP projects:

uint32_t systick = 0;
uint32_t systick_prev = 0;
CY_ISR(isr_systick)
{
	systick++;
}
/* Your Application here vvvv */
main(void)
{
...
/* SysTick init */
  CySysTickStart();  /* Start the systick */
  CySysTickSetCallback(0, isr_systick);  /* Add the Systick callback */
      /* to the standard SysTick Int Vector */
/*****/
...   /* other stuff you need to init */
/* SysTick use in the Application */
  for(;;)
  {
/* Wait for the previous SysTick event plus a set delay */
    if(systick >= (systick_prev + 1000)) 
    {    /* SysTick event occurred.  Process SysTick event in the App. */
      systick_prev = systick;    /* Set the new previous SysTick count */
      ...
      /* go do something within the systick event */
      ...
    }
}

 

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
ShVy_264716
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Hi @Len

Thank you for your input. I took your code snippet as reference and built the following code which works to blink an LED at 1 s rate using Systick Timer :

#include "project.h"
uint32_t systick = 0;
CY_ISR(isr_systick)
{
	systick++;
    if(systick >= 1000)
    {
        Status_LED_Write(~Status_LED_Read());
        systick = 0;
    }
}
int main(void)
{
    Status_LED_Write(1);
    CySysTickStart();  /* Start the systick */
    CySysTickSetCallback(0, isr_systick);  /* Add the Systick callback */
    /* to the standard SysTick Int Vector */
    CyGlobalIntEnable; /* Enable global interrupts. */
    for(;;)
    {
    }
}

Still I do want to know why the Systick interrupt gets set to 1 ms time duration. Why is not there any method to configure for other time durations like we used to have in PSoC4 (You can refer my first post code)?

0 Likes

ShVy,

You can change the SysTick period if that's what you want.

You would use the API call:

CySysTickSetReload(uint32 newperiodcnt);

newperiodcnt can be any 24-bit number.  A number larger than 0x00FFFFFF will be truncated at the high bits.

The SysTick period is based on the Source clock selection to the SysTick counter.  The default is the BUS_CLK.  Therefore to get a SysTick of 1ms using a 24 MHz BUS_CLK, we would use newperiodncnt = BUS_CLK/SysTickPeriod = 24,000,000/.001 = 24,000

If you want a different SysTick period substitute your new value into  SysTickPeriod and make sure it doesn't exceed 24-bits.

Then issue the API call:

CySysTickSetReload(newperiodcnt);

Note:  There is a call to change the SysTick clock source to ILO @ 100KHz.

void CySysTickSetClockSource(CY_SYS_SYST_CSR_CLK_SRC_LFCLK)

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
ShVy_264716
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Thank you, so much, @Len_CONSULTRON . I finally got it working. Here is the code snippet that blinks an LED every 500 ms using Systick Timer Interrupt.

#include "project.h"
#define COUNTS 12000
uint32_t systick = 0;
CY_ISR(isr_systick)
{
    systick++;
    if(systick >= 1000)
    {
        Status_LED_Write(~Status_LED_Read());
        systick = 0;
    }
}
int main(void)
{
    Status_LED_Write(1);
    CySysTickStart();  /* Start the systick */
    CySysTickSetReload(COUNTS);
    CySysTickSetCallback(0, isr_systick);  /* Add the Systick callback */
    /* to the standard SysTick Int Vector */
    CyGlobalIntEnable; /* Enable global interrupts. */
    for(;;)
    {
    }
}

ShVy,

I'm glad it is working for you.

If the SysTick is ONLY used for the LED blink, you can try the following change to your code:

#include "project.h"
#define COUNTS 12000000u /* This value incorporates the systick >= 1000) */
/* systick var can be eliminated */

CY_ISR(isr_systick)
{  /* simplified */
  Status_LED_Write(~Status_LED_Read());
}
int main(void)
{
    Status_LED_Write(1);
    CySysTickStart();  /* Start the systick */
    CySysTickSetReload(COUNTS);
    CySysTickSetCallback(0, isr_systick);  /* Add the Systick callback */
    /* to the standard SysTick Int Vector */
    CyGlobalIntEnable; /* Enable global interrupts. */
    for(;;)
    {
    }
}
Len
"Engineering is an Art. The Art of Compromise."
0 Likes