clearing flags by writing 1

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

Hi friends,

Can someone give me a pertinent explanation why AVR designers choose to clear important flags by writing 1 to them?

I faced recently a situation, trying to port some well good circular buffer serial port implementation to ATMega (from PIC24):

at transmit side, the natural way was to use UDRE vector but it's flag is read-only and default 1 at POR, so if enabled by UDRIE, you'll get stuck in tx interrupt. TXC is useless in this situation, will be 0 and become 1 just AFTER one byte was really serialized.

The only way was to manipulate UDRE by it's mask, enabling in putch() method and disabling in ISR vector, once no more chars to be sent. But disabling interrupts it's not a elegant way...

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

Wrong forum (unrelated to GCC), but the avr-libc manual contains
the answer:

http://www.nongnu.org/avr-libc/u...

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

I think you'll find nothing unusual about the way the AVR does things. Try a few different micros and you'll see what I mean. Disabling interrupts is very common.

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

Quote:
why AVR designers choose to clear important flags by writing 1 to them?
Not AVR designers ONLY, it's a widely used practice with other processors too...and no I can't move the thread... :? don't they trust me with the GCC forum or something.. :wink:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Quote:
why AVR designers choose to clear important flags by writing 1 to them?
Not AVR designers ONLY, it's a widely used practice with other processors too...and no I can't move the thread... :? don't they trust me with the GCC forum or something.. :wink:

I guess not, you being a ASM Freak for years can not be trusted with GCC stuff 8)

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

sorry for miss posting, I work in gcc.

dl8dtl, thanks for link, I see now the point unclear: this core shuts down IRQ's global automatically when serving vectors... hmm, quite nasty in my oppinion. Even older PIC18 don't do that, of course with the price of manual clearing INTF flags.

But example here http://www.nongnu.org/avr-libc/u... ... aq_intbits is still unconvincing... there are several MCU's out there who clears USART RX flag by just reading data register. Once in vector, this is atomic by definition!

This means if I have some SysTick implemented (tmr+compare) it may not be served at precise time :) obviously not on ATMega unless tmr vector is more prioritary than usart, with prio enabled + all context code overhead.

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

> there are several MCU's out there who clears USART RX flag by
> just reading data register.

AVRs, for example ...

Note that for actual interrupts, most of the IRQ flags are cleared
automatically anyway. (The notable exception is the TWI subsystem,
where clearing the interrupt flags means to start the next bus
transaction.)

> it may not be served at precise time

It's a controller, not an FPGA. *Nothing* is served at precise time, there's
always some latency. Nevertheless, if you design your ISRs to be short and
quick, the interrupt is usually served in a *reasonable* time, as the many
AVR projects on earth demonstrate.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Don't get me wrong, it's a very good core. I noticed features like PWRSAVE (cut clock on peripherals) which Atmel implemented long time ago than others, full USART like Cortex M0, PIC24 (only flow missing :)) linear mem access and many many others. I have to use to it at work, that's all. Btw, too bad that datasheets are not very carefully revised. In At2561 at WDT chapter, code is completely wrong.

Thanks all for comments,

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

Quote:

as the many
AVR projects on earth demonstrate.

Since the original topic is more or less dealt with, this leads to the somewhat interesting question about AVR projects in (outer) space... :D

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Don't get us wrong, but we believe you're doing something fundamentally
wrong with the way you approach that interrupt handling ... Can't help
though until you tell us more about your intentions.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Quote:
trying to port some well good circular buffer serial port implementation to ATMega (from PIC24):

That can cause problems. From what I recall with PC16's
the ISR did not clear flags by writing 1's to them?

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

zuzu wrote:
sorry for miss posting, I work in gcc.

dl8dtl, thanks for link, I see now the point unclear: this core shuts down IRQ's global automatically when serving vectors... hmm, quite nasty in my oppinion. Even older PIC18 don't do that, of course with the price of manual clearing INTF flags.


PIC18 has a multi-level interrupt priority system, where a low priority interrupt can be inetrrupted by a high-priority interrupt, but not by any other low-priority interrupt. And high priority interrupts cannot be interrupted by anything.

This is akin to the priority interrupt scheme in the XMEGA series of AVRs.

In this respect, the pre-XMEGA families of AVRs are more similar to the PIC16, PIC14, and PIC12 families, (as well as other common microprocessor systems such as the 8086) with a single priority interrupt scheme (at the CPU level -- there may be multi-level priority interrupt systems on x86-based computer systems, but they are actually emulated by external hardware. The CPU itself has only one interrupt priority, and it does, indeed, disable all interrupts globally as soon as any single interrupt handler begins to be serviced).

If nested interrupts are desired, then the software must manually re-enable the global interrupt mask, along with any potential housekeeping required to maintain a stable system, inside the ISR.

Quote:
But example here http://www.nongnu.org/avr-libc/u... ... aq_intbits is still unconvincing... there are several MCU's out there who clears USART RX flag by just reading data register.

This is true of the AVR's USART.

Quote:
Once in vector, this is atomic by definition!

Not at all. If your USART has a multi-byte receive FIFO (the AVR does), it's perfectly possible that more than one byte might be waiting to be received. But many people code their receive interrupt handler to only pull one byte out of the FIFO at a time.

In this case, in order to get all the bytes out of the FIFO, it is necessary for the receive interrupt flag to remain set even after the interrupt service routine has been executed the first time, to reflect the fact that there is still a second data byte in the receive FIFO waiting to be processed. The interrupt flag is only cleared after all of the bytes have actually been successfully pulled out of the FIFO.

Quote:
This means if I have some SysTick implemented (tmr+compare) it may not be served at precise time :) obviously not on ATMega unless tmr vector is more prioritary than usart, with prio enabled + all context code overhead.

That's why it's important in a system such as a non-XMEGA AVR, to keep the time spent inside an ISR to an absolute minimum, so that other interrupts aren't starved.

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

Quote:

Can someone give me a pertinent explanation why AVR designers choose to clear important flags by writing 1 to them?

There was a recent argument...errr, discussion...on that. Search it out.

Ummm--it was in the thread that >>you<< started and participated in:
https://www.avrfreaks.net/index.p...

I'm out.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I didn't want to be a firestarter :)

Quote:
Not at all. If your USART has a multi-byte receive FIFO (the AVR does), it's perfectly possible that more than one byte might be waiting to be received.

Hmm.. perhaps only in bad practice UART code. In my opinion, user should write minimum ISR code, and calculate such as next hit will never be possible. For example my cbuff rx handler (including push/pop/reti )has ~62 tcy so quite impossible @ my 16MIPS even at 921Kbps, when a byte has ~10uS.

Quote:
PIC18 has a multi-level interrupt priority system, where a low priority interrupt can be inetrrupted by a high-priority interrupt, but not by any other low-priority interrupt. And high priority interrupts cannot be interrupted by anything.

If I understand right AVR concept... core needs to shuts off GIE in non-nested interrupts mode because it's vectors are mapped at different address (on PIC18 they pinpoint at one an only, so serving is indeed atomic) and arbitration (by IVT entry) is off in non-nested. Much powerful is PIC24 implementation or Cortex M0, but I think it's not fair to compare with ATMega :)

Quote:
This is akin to the priority interrupt scheme in the XMEGA series of AVRs.
I heard it's powerful, but never worked on any. In fact at our company we'd like to port to XMega some projects last year but at that time Atmel couldn't provide us some samples (some 8 usart, I cannot remember which one) so we choose SmartFusion by Actel (ARM). An if I remember well, compiler availability was with question mark too at that time.

Quote:
That can cause problems. From what I recall with PC16's
the ISR did not clear flags by writing 1's to them?
Nope, doesn't have this nice feature :) But I was speaking about 24 series, much more close to AVR core and different than 12,14, 16 and 18 series.

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

Quote:
in order to get all the bytes out of the FIFO...

One more thing...with all do respect, FIFO is too much... saying double buffered is more adequate. This AVR has only 1 byte "FIFO" not including TSR or RSR, quite the same as many it's class competitors :)

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

zuzu wrote:
I didn't want to be a firestarter :)

Quote:
Not at all. If your USART has a multi-byte receive FIFO (the AVR does), it's perfectly possible that more than one byte might be waiting to be received.

Hmm.. perhaps only in bad practice UART code. In my opinion, user should write minimum ISR code, and calculate such as next hit will never be possible. For example my cbuff rx handler (including push/pop/reti )has ~62 tcy so quite impossible @ my 16MIPS even at 921Kbps, when a byte has ~10uS.


Agreed, it shouldn't be necessary most of the time, as long as you can guarantee that your interrupt response time will be fast enough. But the hardware capability is there, and it would be foolish not to anticipate that somewhere, somebody is eventually going to take advantage of it. So Atmel had to make sure that whatever interrupt flagging system they implemented, was able to accommodate it.

Quote:
Quote:
PIC18 has a multi-level interrupt priority system, where a low priority interrupt can be inetrrupted by a high-priority interrupt, but not by any other low-priority interrupt. And high priority interrupts cannot be interrupted by anything.

If I understand right AVR concept... core needs to shuts off GIE in non-nested interrupts mode because it's vectors are mapped at different address (on PIC18 they pinpoint at one an only, so serving is indeed atomic) and arbitration (by IVT entry) is off in non-nested. Much powerful is PIC24 implementation or Cortex M0, but I think it's not fair to compare with ATMega :)

I don't think the address to which the MCU vectors when an interrupt occurs has anything to do with the decision to inhibit interrupts globally when any interrupt occurs. I think it was done as a primitive way of protecting against CPU starvation and excessive stack usage due to a cascade of multiple interrupts being marked as pending simultaneously.

Certainly there are many ways to go about protecting against this situation. But it seems to me that Atmel chose the one it did because it was simple to implement in silicon, and it was sufficient for satisfying most non-complicated situations.

Of course, it's a trade-off. As you have noted, the AVR's way of doing things increases the complexity when you want to design a system where some form of interrupt nesting is required to satisfy timing requirements. That's why Atmel improved the mechanism when it introduced the XMEGA line.

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

zuzu wrote:
Quote:
in order to get all the bytes out of the FIFO...

One more thing...with all do respect, FIFO is too much... saying double buffered is more adequate. This AVR has only 1 byte "FIFO" not including TSR or RSR, quite the same as many it's class competitors :)

True, that is all a matter of semantics. Either way, though, the simple fact that you've vectored into the receive interrupt handler is not an adequate reason for the hardware to automatically clear the receive interrupt bit. It must be done after the buffer has actually been drained -- which is exactly what happens on the AVR.

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

Quote:

This AVR has only 1 byte "FIFO" not including TSR or RSR, quite the same as many it's class competitors

If you are going to argue semantics, then you should probably tell us which model "this" AVR is.

Modern models have

Quote:
The receive buffer consists of a two level FIFO.
plus the character being received. Yes, two levels is a somewhat degenerate FIFO queue but using the term makes it clear the ordering.

If interrupt handling and U(S)ART circular buffers is so difficult in AVRs, why don't I have any problems with them in scores of production apps over the years? I've never yet seen the necessity to nest interrupts. My stack requirements are thus quite minimal. While an e.g. RTOS timer tick may suffer a bit of latency the CTC feature allows things to catch up and not suffer accumulated timing errors. I've never seen the need for a pre-emptive RTOS setup in an AVR8 anyway, but again I generally work with the smaller (<32k) models; normally too SRAM-impaired for an RTOS. My larger apps would have many many "tasks" and though I might have enough SRAM on e.g. Mega640, I want it for other purposes such as SD-card sector buffers.

Certainly an AVR8 isn't suitable for all applications. I enjoy applying them to microcontroller applications, even given the design approach that is too simple-minded for your sensibilities. If you want to continue railing about AVR8 architecture, then use a different architecture that does not offend you.

"Engineering is the art of making what you need from what you have." I have an AVR8. I make what I need.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:

"Engineering is the art of making what you need from what you have."

Oh, (temporarily?) in again, are you? :wink:

That was rather beautiful, Lee! Goes hand in hand with "making it good enough" (i.e. not necessarily perfect). And there's always the joke that I picked up in the movie "A Beautiful Mind" about the mathematician and the engineer deciding to close in on a pair of persons, of a sex desirable to them, at the local waterhole, by repeatedly halving the distance.. :D [Note: I hope I got that so gender-neutral for political correctness :D]

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:
"Engineering is the art of making what you need from what you have."
Absolutely beautiful, no comments :) Thanks all for valuable comments. I have to live with 2561 on some existing design and improve some things. Indeed, datasheet specifies 2 level FIFO but my guess (unless Atmel will make more precise documents) was "including" serializer.

I don't know what "modern" MCU you ment but I setup a simple test few days ago (16MIPS, no interrupts):

UDR0 = 'a';
UDR0 = 'b';
UDR0 = 'c'; <- this isn't sent

Obviously, first goes to TSR, second to shaddow and third have no room anymore. If it was 2 level FIFO + serializer, USART should send 3 chars. I hope I'm not wrong.

Another thought... for two level FIFO it would be nice to have IRQ's once at 2 bytes (FIFO depth) so core will be twice free. I saw interrupts at each byte only, both on Rx and Tx.

Quote:
If interrupt handling and U(S)ART circular buffers is so difficult in AVRs
Not at all, I've done it and it's working quite nice, I just had to use to AVR concept. Well, I have some 485 Tx switching problems at last byte :) but I'll solve them today.

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

zuzu wrote:
Can someone give me a pertinent explanation why AVR designers choose to clear important flags by writing 1 to them?

I assume, its a joke from the developer to give it a personal note.

I trapped also in this pitfall.
Since most other µc clears every bit in the obvious way, e.g. the 8051.

Unfortunately this crazy method has serious side effects!

E.g. if you want to change any bit in the TWCR register, you must additional mask out the TWINT bit, otherwise the TWI interrupt state was released accidentally.
So you should not write to the TWCR directly.
You must establish a TWCR-shadow variable and do any changes on it.
And only on the end of the TWI interrupt write back this variable to do the changes and TWI release together.

The same care must be taken on all registers, which contain such crazy bits together with others.

Peter

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

> If it was 2 level FIFO + serializer, USART should send 3 chars.

Tx is usually not in much need of a FIFO, so yes, it's two-level only.

Rx is triple-buffered in recent AVRs.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Quote:
Since most other µc clears every bit in the obvious way, e.g. the 8051
For the past 20 years I have cleared bits in the HC11 by writing a 1 to them so when this happened with the AVR I did not even think about it. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

The chip designers have provided a guaranteed-atomic manipulation mechanism that will still work on I/O registers outside the limited range of the SBI/CBI instructions. It's a beautiful thing.

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

> ... that will still work on I/O registers outside the limited range
> of the SBI/CBI instructions.

Besides, CBI is *not* atomic, it has one read and one write cycle. Thus,
using it to clear an interrupt flag would still open a race condition
of unintionally clearing a flag that just triggered between the read and
the write cycle.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Levenkay wrote:
The chip designers have provided a guaranteed-atomic manipulation mechanism that will still work on I/O registers outside the limited range of the SBI/CBI instructions. It's a beautiful thing.

That's another story.
If you have such special bits inside bit addressable register, then the SBI/CBI has unexpected effects.
E.g. if you change a bit inside ADCSRA (ATmega8), then this instruction clears the ADIF bit also.

Data sheet:
"Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt can be disabled.
This also applies if the SBI and CBI instructions are used."

Peter

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

danni wrote:
Levenkay wrote:
The chip designers have provided a guaranteed-atomic manipulation mechanism that will still work on I/O registers outside the limited range of the SBI/CBI instructions. It's a beautiful thing.

That's another story.
If you have such special bits inside bit addressable register, then the SBI/CBI has unexpected effects.
E.g. if you change a bit inside ADCSRA (ATmega8), then this instruction clears the ADIF bit also.

Data sheet:
"Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt can be disabled.
This also applies if the SBI and CBI instructions are used."

Peter

That was a design defect in many of the AVRs released before around 2004, and it has resulted in lots of headaches for designers.

Fortunately, Atmel eventually realized their mistake. They corrected this defect in their newer parts. Most AVRs released after around 2004, have fixed the SBI and CBI instructions to make them truly only affect one single bit, without having any side-effects on any surrounding bits in the register.