Why are all interrupt flags cleared by writing a logical 1?

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

Hi all,

I have gone thru the FAQ list of AVR-LIBC. There i found some explanation for using 1 to clear the interrupt. But i don't get the point clearly.

That doc says that the following method of clearing a interrupt is wrong

TIFR |= _BV(TOV0); /* wrong! */

and they refer that the following one is the right way of clearing the interrupt

TIFR = _BV(TOV0);

Please explain it to some more extent and also please clarify me the point for using logic 1 rather than using logic 0 to clear a interrupt.

Thanks in advance to everyone

Regards
Barani

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
TIFR |= _BV(TOV0);

This statement first reads TIFR, then ORs in the value, then writes it back to TIFR. But what if, for example, the OCF0 flag is also set. In the mega32, the TOV0 flag is bit 0 and the OCF0 flag is bit 1. So when you read TIFR you will get the value 0x03. ORing in 0x01 (for the TOV0 flag), you still get 0x03 (so the OR really got you nowhere). But more important, when you write this value back to the register you clear both flags, not just the one that you wanted to clear.

With using logic 1 to clear a flag, it allows you to clear only the flag you want without affecting the other flags in the register (since writing a 0 to a bit does nothing). Atmel could have done the reverse and had a 0 clear the flag and a 1 do nothing, but then you would have statements like:

TIFR = ~_BV(TOV0);

Which is probably less intuitive.

Regards,
Steve A.

The Board helps those that help themselves.

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

Hi,

Thanks for your valuable input on this. Now i understood the side effects caused by the statement

TIFR |= _BV(TOV0); 

But why did ATMEL preferred the way of setting the bit to 1 to clear the interrupt? I hope that there should be some logical reason behind that like for the following one.

Quote:

Why have "programmed" fuses the bit value 0?
Basically, fuses are just a bit in a special EEPROM area. For technical reasons, erased E[E]PROM cells have all bits set to the value 1, so unprogrammed fuses also have a logical 1. Conversely, programmed fuse cells read out as bit value 0.

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

Quote:
But why did ATMEL preferred the way of setting the bit to 1 to clear the interrupt?
It is NOT just Atmel. Other processors (Motorola/Freescale I know of) do it the same way too for the same reason explained by Steve above.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Hi,

I agree with your point that all other uC's follow the same procedure.Then if i use the following statement to clear only OCF1A, then it will write 0 to other bit locations right? In that state what is the effect(Will i loose the interrupts)?

TIFR1 = (1<<OCF1A);

Before execution if TIFR1 = 0x07;
After execution TIFR1 = 0x02;

Will it not discard the other interrupts?

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

Quote:
After execution TIFR1 = 0x02;
What makes you think that? It will be 0x05 as you have just cleared OCF1A which is bit 1.
Quote:
will write 0 to other bit locations right?
No it doesn't as you will have to write a 1 to the other flags also in order to clear them.

0 has no effect which is the purpose of the exercise.. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Hi,

I got your point, but how would a assignment statement will preserve the contents of all other bits?

I might be silly, but still i am not convinced that how come the above statement is not writing 0 to all other bit locations!...

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

Quote:
how come the above statement is not writing 0 to all other bit locations!...
Because writing a zero to the flag bits does NOTHING, so even though you are writing a zero, the logic to clear the flags ignores it so it does not clear them.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Hi,

Thanks a lot for you valuable input. If i understood your point correctly, then here is my learning

Only for Interrupt Flag registers alone AVR architecture implemented this kind of register handling to discard writing 0 to the bit fields of the register.

Thanks to everyone.

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

You have to clear the interrupt flag in one instruction - otherwise an interrupt might occur between multiple instructions which would cause undesirable side effects.

Consider the following sequence:

1.read TIFR
2.and with bitmask to clear a bit
3.write value back to TIFR

what would happen to any other bits that get set before operation #3?

As mentioned by others, it is common practice to clear an interrupt flag by writing a '1'. LPC2xxx series do it also as do many others. Technically, how else would you do it??

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

Some processors need to be write 0 to clear interrupt flag, but they allow to access interrupt flag register by bit operation. So, never found this problem.

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

In the case of 8051, yes.

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

There would be nothing wrong with clearing the bits by writing a 0. But it would not be simpler, just everything inverted.

Clearing the interrrupt flags by writing a 1 is also handy to clear any old pending interrupt when you change the interrut mask. You can just write the same value to the flag and mask register.

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

I remember running across this in the datasheet some time ago, but couldn't remember the specifics, so I thought I'd do a little reading and bone up. Problem is, I can't find where this is mentioned in the ATMega168 datasheet. I know it's there, just have no idea where to look. Can anyone point me in the right direction? Thanks!

Michael

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

baranikumarhtsl wrote:

I have gone thru the FAQ list of AVR-LIBC. There i found some explanation for using 1 to clear the interrupt. But i don't get the point clearly.

Yes, thats a crazy thing, maybe to give a personal note from a developer.
Thats a pitfall where traps absolutely every AVR beginner in (me too) :cry:

In opposition the Atmel 8051 are a straight forward architecture, which handles interrupt bits like any other bits also.
On the 8051 you can simple clear a bit to clear it.
Furthermore you can set an interrupt bit to generate a software interrupt.
E.g. it is common practice to put some bytes onto a buffer for UART transmission and set the TI bit finally to fire the interrupt to put the bytes out.
Its a clean and logical approach, but only allowed on the 8051, not on the AVR.

Peter

P.S.:
There is only one special case, if you read and write back an interrupt register you can clear all pending interrupts simultaneously, but I can never think any practial usage of it.

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

Usually writing a one is only for edge/toggle triggered external interrupts and specific internal interrupts like the timer/counters, etc. Level triggered external interrupts typically disable the interrupt flag function (the actual external input interrupt level, not the interrupt flag is in total control of the interrupt).

The above is true for most AVR interrupt flags. One common type of exception is the USART RXC bit. Although the RXC bit can be used with the RXCIE interrupt enable, only the USART hardware or a full chip reset can clear the RXC bit (the actual RXC bit is specified as read only with an initial value of zero in the data sheet, so you cannot write anything to a read only bit).

Another exception is the CANSTMOB register in AVR chips with a CAN module. The data sheet specifies the interrupt flags in these registers are cleared with a read, modify then write instruction sequence (as Kartman pointed out above, there are some specific conditions that makes clearing these flags more complicated). These interrupt flags are not even cleared by a full chip reset or a CAN reset (the data sheet shows the CANSTMOB register has no initial value).

Keep in mind the writing a one to clear an interrupt flag only works when and how the data sheet specifies it works.

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

It's Sunday morning, so my brane is moving slow. I forgot to mention the following.

Some chips have both interrupt flag bit or bits mixed in with normal control bits. In this case writing a one to clear the interrupt flag is not always as easy/useful.

For example, the ATmega48 chip UCSR0A register TXC0 interrupt flag bit can be cleared by writing a one to it. However, if you do write a one to TXC0 you will need to preserve the current value in the other read/write (R/W) U2X0 and MPCM0 bits. Because there is only one single writable interrupt flag in the entire UCSR0A register, the |= operation will work. In C this would be a simple UCSR0A register |= with the TXC0 bit value type of operation. However, as Koshchi explained above, in a different register that has multiple read/write (R/W) interrupt flag bits, a simple |= is not the correct solution.