Incrementing variable is not zeroing during interrupt

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

cross mob
lock attach
Attachments are accessible only for community members.
AlRu_4725236
Level 1
Level 1
First like received First reply posted First question asked

Hello

I am having an issue where part of my interrupt code is seemingly not executing consistently. In the main loop, I have a variable called sample that is incrementing by .0001 every pass. I also have a PWM component running that fires an interrupt at its terminal count. When the interrupt is fired, I set the sample variable to zero (the code is just sample = 0;). I also have another variable called test that alternates between 0 and 1 every interrupt (the code is just test = !test;).

I am sending the PWM counter value, the sample variable, and the test variable to the Bridge Control Panel so I can watch them. The issue I am having is, the sample variable is only being set to 0 at seemingly random interrupts, and I can't figure out why. I know for a fact that the interrupt is firing consistently at every terminal count, because the test variable is alternating consistently.

I've attached a picture of the results I am seeing from the Bridge Control Panel. Blue is the PWM counter value, red is the value of sample, green is the value of test. As you can see, test = !test; executes at every terminal count with no issue, but sample = 0; does not. Why? Clearly I am not understanding interrupts properly when it comes to changing an incrementing variable during an interrupt. I've attached my project.

0 Likes
1 Solution
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I think that you need to declare a variable which is supposed to be updated inside an ISR as "volatile"

(A) So please change line 15

from

float sample = 0 ;

to

volatile float sample = 0.0 ;

(B) But also your method of using the ISR to set a flag seems to be better.

This way, we can avoid possible racing condition of assigning different value(s) to sample in the same time.

With this approach the following two assignments never happen at once.

sampe = 0 ;

and

sampe = sampe + .001 ;

Still please remember to declare the flag as volatile, though.

Something like

volatile int TC_flag = 0 ;

(A)

=================

#include "project.h"

uint8 i2cbuf[3];

volatile float sample = 0.0; // <----

volatile uint8 test = 0; // <----

CY_ISR(pwm_interrupt_handler){

    sample = 0;

    test = !test;

   

    PWM_ClearInterrupt(PWM_INTR_MASK_TC); 

}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

   

    isr_StartEx(pwm_interrupt_handler);

    PWM_Start();

   

    I2C_Start();

    I2C_EzI2CSetBuffer1(sizeof(i2cbuf), 0, i2cbuf);

   

    for(;;)

    {

        sample = sample + .0001;

       

        i2cbuf[0] = sample;

        i2cbuf[1] = PWM_ReadCounter();

        i2cbuf[2] = test;      

    }

}

=================

(B)

=================

#include "project.h"

volatile int TC_flag = 0 ; // <----

volatile uint8 test = 0; // <----

uint8 i2cbuf[3];

float sample = 0;

CY_ISR(pwm_interrupt_handler){   

    sample = 0.0;

    test = !test;   

    PWM_ClearInterrupt(PWM_INTR_MASK_TC);

}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

   

    isr_StartEx(pwm_interrupt_handler);

    PWM_Start();

   

    I2C_Start();

    I2C_EzI2CSetBuffer1(sizeof(i2cbuf), 0, i2cbuf);

   

    for(;;)

    {

        if (TC_flag) {

            sample = 0.0 ;

            TC_flag = 0 ;

        } else {

            sample = sample + .0001;

           

            i2cbuf[0] = sample;

            i2cbuf[1] = PWM_ReadCounter();

            i2cbuf[2] = test;

        }

    }

}

=================

moto

View solution in original post

3 Replies
AlRu_4725236
Level 1
Level 1
First like received First reply posted First question asked

I found a solution, though I'm not 100% it's the proper way.

Instead of running sample = 0; in the interrupt routine, I set a bit called TC_flag. Then, in the main loop, when TC_flag = 1, I run sample = 0; and then reset TC_flag to 0.

This works, but I am still confused about why I was seeing intermittent behavior with my previous attempt.

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I think that you need to declare a variable which is supposed to be updated inside an ISR as "volatile"

(A) So please change line 15

from

float sample = 0 ;

to

volatile float sample = 0.0 ;

(B) But also your method of using the ISR to set a flag seems to be better.

This way, we can avoid possible racing condition of assigning different value(s) to sample in the same time.

With this approach the following two assignments never happen at once.

sampe = 0 ;

and

sampe = sampe + .001 ;

Still please remember to declare the flag as volatile, though.

Something like

volatile int TC_flag = 0 ;

(A)

=================

#include "project.h"

uint8 i2cbuf[3];

volatile float sample = 0.0; // <----

volatile uint8 test = 0; // <----

CY_ISR(pwm_interrupt_handler){

    sample = 0;

    test = !test;

   

    PWM_ClearInterrupt(PWM_INTR_MASK_TC); 

}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

   

    isr_StartEx(pwm_interrupt_handler);

    PWM_Start();

   

    I2C_Start();

    I2C_EzI2CSetBuffer1(sizeof(i2cbuf), 0, i2cbuf);

   

    for(;;)

    {

        sample = sample + .0001;

       

        i2cbuf[0] = sample;

        i2cbuf[1] = PWM_ReadCounter();

        i2cbuf[2] = test;      

    }

}

=================

(B)

=================

#include "project.h"

volatile int TC_flag = 0 ; // <----

volatile uint8 test = 0; // <----

uint8 i2cbuf[3];

float sample = 0;

CY_ISR(pwm_interrupt_handler){   

    sample = 0.0;

    test = !test;   

    PWM_ClearInterrupt(PWM_INTR_MASK_TC);

}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

   

    isr_StartEx(pwm_interrupt_handler);

    PWM_Start();

   

    I2C_Start();

    I2C_EzI2CSetBuffer1(sizeof(i2cbuf), 0, i2cbuf);

   

    for(;;)

    {

        if (TC_flag) {

            sample = 0.0 ;

            TC_flag = 0 ;

        } else {

            sample = sample + .0001;

           

            i2cbuf[0] = sample;

            i2cbuf[1] = PWM_ReadCounter();

            i2cbuf[2] = test;

        }

    }

}

=================

moto

Thanks for the information on the volatile keyword, I wasn't aware of that.