Go Down

Topic: While loop preventing ISR from working (Read 10270 times) previous topic - next topic

wanderson



Did a quick search of the web and found that it seems possible with AVR-GCC,  What are the potential drawbacks to that approach?


That it won't work.

By making the variable volatile you are saying "don't keep it in a register". There is no atomic increment/decrement of a memory location, so the data has to go from variable, to register, back to variable. If you make it "register" that is completely incompatible with "volatile".


I haven't run any tests, but this thread seemed to indicate that the behavior has changed?

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17336

michael_x

That link has one remarkable sentence:
Quote
As a result, volatile register variables won't work the way you expect.


No matter what you expect ;)

Being a kind of contradiction, I think they fixed the bug that "volatile" was ignored for register variables before.

GoForSmoke

I guess you could write machine code that keeps a register reserved just for one variable. It's not what I would expect a compiler to do. Would it be worth the trouble? For me the answer is @&$% no but your mileage may vary.


Quote
I don't remember seeing "you have to" so much as "you need to be careful" over and over.


The more important question is "why bother".  We're talking about...

Is the difference in speed or a very few less extra lines of code worth it?


One line of C or three assembly instructions compiled to three one cycle machine instructions.  In other words, six bytes of Flash that take 0.1875 microseconds to execute.

Which is why I am willing to answer your question but not participate in the futile discussion.



I was never so good at putting hard logic into soft English.  :P I look at the examples provided and see enough of the actual workings to know your advice is good and solid.

As for the futile discussion it reminds me of "tobacco, is it really harmful?" and the now popular "global warming is not real".
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

nickgammon


That link has one remarkable sentence:
Quote
As a result, volatile register variables won't work the way you expect.


No matter what you expect ;)


Yes, very amusing. I expected the cat to meow, but it didn't. Strange.

I have added a post to my thread here:

http://www.gammon.com.au/interrupts

That discusses in some detail the pitfalls of not making access to shared variables atomic.

As for the Bugzilla post, no matter what they say, I don't see any way you can have a "volatile register". Obviously registers are volatile. The compiler know what registers it uses and when. What it can't know, unless you tell it, is that you are planning to share a variable between an ISR, and the main code, in such a way that needs extra code. It might conceivably be able to work it out in a single compilation unit, but once you start linking in other files, that would become nigh impossible.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

JChristensen


As for the Bugzilla post, no matter what they say, I don't see any way you can have a "volatile register". Obviously registers are volatile.


Not sure I understand everything in that Bugzilla post, but I think there are some odd assumptions being made there. Did some reading and found that the meaning of "register" was perhaps just a little different from what I thought.

It seems that there is no requirement that says a "register" variable has to have any special relationship to an actual hardware register. Stroustrup says, "Declaring a variable register is a hint to the compiler to optimize for frequent access; doing so is redundant with most modern compilers."  K&R says, "A register declaration is equivalent to an auto declaration, but hints that the declared objects will be accessed frequently. Only a few objects are actually placed into registers, and only certain types are eligible; the restrictions are implementation-dependent."

As for volatile, Stroustrup says, "A volatile specifier is a hint to the compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided." K&R says, "The purpose of volatile is to force an implementation to suppress optimization that could otherwise occur. For example, for a machine with memory-mapped I/O, a pointer to a device register might be declared as a pointer to volatile, in order to prevent the compiler from removing apparently redundant references through the pointer."

K&R further says, "The auto and register specifiers give the declared objects automatic storage class, and may only be used within functions." So I would think that the global declaration in the Bugzilla example,

Code: [Select]
register volatile unsigned char flags asm("r16");

should give an error, but it does not. However, either of the the following global declarations will give an error:

Code: [Select]
register volatile unsigned char foo;
register unsigned char bar;


Although using register and volatile together seems legal, it still does seem like an odd combination. I think I would avoid register altogether unless I had a good reason to use it. Most likely such a reason would be machine dependent and so possibly not portable, and would also require understanding the assembly-level consequences.


Coding Badly


The AVR processor can only store-to and load-from memory.  To do any meaningful work the data has to be in a register.  The compiler keeps as much data as it can in registers and minimizes memory access as much as possible.  In other words, register for an auto variable is pointless and is very likely ignored.

As far as I know, the compiler has assigned purposes for all of the AVR registers.  The SuperFFT module can't use R16 (or any other register) as a global variable because the compiler used R16 to pass parameters when HardwareSerial was compiled.  In other words, register for global variables is dangerous and is very likely ignored.

JChristensen


In other words, register for global variables is dangerous and is very likely ignored.


Indeed, according to K&R, illegal.

Go Up