I want to write a C code firmware for Atmel AVR microcontrollers. I will compile it using GCC. Also, I want to enable compiler optimizations (-Os
or -O2
), as I see no reason to not enable them, and they will probably generate a better assembly way faster than writing assembly manually.
But I want a small piece of code not optimized. I want to delay the execution of a function by some time, and thus I wanted to write a do-nothing loop just to waste some time. No need to be precise, just wait some time.
/* How to NOT optimize this, while optimizing other code? */ unsigned char i, j; j = 0; while(--j) { i = 0; while(--i); }
Since memory access in AVR is a lot slower, I want i
and j
to be kept in CPU registers.
Update: I just found util/delay.h and util/delay_basic.h from AVR Libc. Although most times it might be a better idea to use those functions, this question remains valid and interesting.
Related questions:
Use the command-line option -O0 (-[capital o][zero]) to disable optimization, and -S to get assembly file. Look here to see more gcc command-line options. Show activity on this post.
GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff. As compared to -O , this option increases both compilation time and the performance of the generated code.
The compiler optimizes to reduce the size of the binary instead of execution speed. If you do not specify an optimization option, gcc attempts to reduce the compilation time and to make debugging always yield the result expected from reading the source code.
Compiler specific pragma gcc provides pragma GCC as a way to control temporarily the compiler behavior. By using pragma GCC optimize("O0") , the optimization level can be set to zero, which means absolutely no optimize for gcc.
I developed this answer after following a link from dmckee's answer, but it takes a different approach than his/her answer.
Function Attributes documentation from GCC mentions:
noinline
This function attribute prevents a function from being considered for inlining. If the function does not have side-effects, there are optimizations other than inlining that causes function calls to be optimized away, although the function call is live. To keep such calls from being optimized away, putasm ("");
This gave me an interesting idea... Instead of adding a nop
instruction at the inner loop, I tried adding an empty assembly code in there, like this:
unsigned char i, j; j = 0; while(--j) { i = 0; while(--i) asm(""); }
And it worked! That loop has not been optimized-out, and no extra nop
instructions were inserted.
What's more, if you use volatile
, gcc will store those variables in RAM and add a bunch of ldd
and std
to copy them to temporary registers. This approach, on the other hand, doesn't use volatile
and generates no such overhead.
Update: If you are compiling code using -ansi
or -std
, you must replace the asm
keyword with __asm__
, as described in GCC documentation.
In addition, you can also use __asm__ __volatile__("")
if your assembly statement must execute where we put it, (i.e. must not be moved out of a loop as an optimization).
Declare i
and j
variables as volatile
. This will prevent compiler to optimize code involving these variables.
unsigned volatile char i, j;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With