AVR GCC Attiny85 increment in ISR PCINT0_vect not working?

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(Noob alert) I am trying to understand how to edit volatile variables in the ISR routine. (for pwm/ frequency counter, and hopefully to create an array of pulse width data from packets of different protocols)
I put together this simple program to test if the variables are being changed, but it does not seem to be editing the variable. Originally the code had a only led toggle in the pcint0 isr to confirm it was functioning correctly and that worked fine.

I have googled all over and all I have found is to make the variable volatile, which allows the code to compile, but doesn't seem to work or compile correctly.

I tried to increment the variable with X++; and X+=1;

 

Please excuse my ignorance in this subject.

Any help understanding this issue would be much appreciated! :)

 

On the input I have a 0.5 hertz square wave osc to test via another attiny85.

 

It compiles fine but does not flash the indicator at all.

 

Compiling with default settings on  Atmel Atudio 7.0.934 for an Attiny85

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>

 volatile int ttest = 0;

int main(void)
{
		
		DDRB &= ~(1 < PINB1); //Set pb1 to input
		DDRB |= 1 << PINB0; //pb0 output led pin
		PORTB |= 1 << PINB1; // input pb1 pullup resistor internal
		GIMSK = 0b01100000; //enable isr
		PCMSK = 0b00000010; //pin change mask for pcint1
		sei();
		
		PORTB &= ~(1 << PINB0); // set led pb0 low
    /* Replace with your application code */
    while (1) 
    {
		
		if(ttest == 4) //when count = 4 toggle led
		{
			ttest = 0;  // reset count
			PORTB ^= 1 << PINB0; // toggle indicator led when count is reached
			
		}
		
    }
}

ISR(PCINT0_vect)
{
	
ttest +=1; // increment count on pin change

}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

GIMSK = 0b00100000; //enable isr(PIIE only)

 

cli(); // atomic operation

int tmp = ttest;
sei()
if(tmp == 4) //when count = 4 toggle led

 

Please try it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This works fine thanks! :D

 

 I put...:

cli(); // atomic operation

int tmp = ttest;
sei()

 

...right above if(tmp ==4) in the while loop.

So from what I understand about this,
cei() clears the interrupt flag and prevents interrupts from occurring, then it writes the value of "ttest" to a non volatile variable, and then sei() to re enable interrupts. Then the if statement runs. So I guess I am required to disable interrupts to interact with variables that are in an isr routine? (To prevent an isr from corrupting the variable?)

A few questions if you don't mind helping me understand this. (1 more noob alert) thanks so much for your time! <3

 

Main question is, wont having cei() and sei() in the while loop mean a chance of missed interrupts, increased at higher frequencies?

Why does this work as apposed to having the if statement check the volatile variable?
 

Why do i have to temporarily disable interrupts to interact with the "ttest" volatile variable?

 

Thanks so much for the help! This has had me stumped for 2 days xD

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Int is a 2-byte variable.

 

In the while loop, read byte L and read byte H.
But what will happen if an interrupt occurs in the meantime?

 

When the value of int is 0x00FF, byte L (0xFF) is read in the while loop.
An interrupt is generated and the variable is updated to 0x0100.
Processing returns to the while loop and byte H (0x01) is read.

 

As a result, the while loop gets 0x01FF.
This is a very bad thing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kreetcha wrote:

 


int main(void)
{

                ...
		PCMSK = 0b00000010; //pin change mask for pcint1
		...

ISR(PCINT0_vect)
{

   ttest +=1; // increment count on pin change

}

 

 

You enable PCINT1 but your ISR is for PCINT0.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kreetcha wrote:

Main question is, wont having cei() and sei() in the while loop mean a chance of missed interrupts, increased at higher frequencies?

 

Even if the global interrupt is disabled with cli, the pin change flag will still be set and once global interrupts are enabled with sei,

the pin change ISR will run.  It will just be delayed for a few cpu cycles.

 

The sequence disable interrupts, copy var, enable interrupts will typically take less than one microsecond, so unless your input

frequency is greater than one megahertz, there won't be a problem.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just a side note: it is only a test code, and the applied frequency is quite low, but generally it is more safe to write if (temp >= 4) in such cases in order to avoid uncatched events.

BR,

M

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That won't avoid atomic problems.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

?? Of course not. That's why it was stated as a side note.

The atomic access of shared variables was explained by Kabasan and Chuck.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for late response, been quite busy >.<

@ Kabasan - Oh that makes sense, thanks 1 x 10^6 for not only solving the issue but helping me understand it! xD

@ Menahem - yes thank you, I had realized that after I had posted, this was just a short code to recreate the error.

@Chuck99 - Oh ok thats great! so i guess they wont miss an interrupt, they would just be a very slight delay. VERY helpful information, appreciate it.

                   There is no PCINT1 on the attiny85, PCINT0 has  the PORTB pins and you choose which pins enable the isr(pcint0_vec) with the pin change mask (PCMSK)

 - Thank you all so much for all the helpful information :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also to note, changing the count variable to a char to contain only 1 byte instead of having 16 bit integer with a high and low byte solves this issue entirely and removes the need to constantly disable the isr in the loop.
With a cost only having a max count value of 255 :)
(thanks kabasan!)

Guess it would just depend on the scenario.

 

Thanks again fellas <3 

 

Last Edited: Sat. Aug 12, 2017 - 12:51 AM