EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Functions not working after optimization in IAR

Started by merapcb February 8, 2012
> It is possible that the do {} while (0) is removed because the while(0) is
> never true. Just take out the do and while(0) leaving the braces and what is
> in the braces...

No. This advice is Very Bad. The do...while (0) is exactly right, and if
you can't figure out why then I suggest you use the power of Google to
understand why. It is important if you use macros.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426

Beginning Microcontrollers with the MSP430

OK. Back to square one. On my board I have three I/O lines that are used to configure a multiplexer. When no (low) optimization is applied, it works fine. What I am seeing when optimization is used is that their timing/duration is all messed up. The code has obviously not changed. So why would it behave like this? It is a simple matter of setting a port register.
> OK. Back to square one. On my board I have three I/O lines that are used to
> configure a multiplexer. When no (low) optimization is applied, it works fine.
> What I am seeing when optimization is used is that their timing/duration is
> all messed up. The code has obviously not changed. So why would it behave like
> this? It is a simple matter of setting a port register.

If your timing is not based on a hardware time, but is instead based on
software loops, of course your timing will be affected by compiler settings.
I will explain what I am doing. I am accessing a number of serial peripherals using the same UART, using a MUX. Code is something like this:

Set MUX to CH1
(do something)
Switch MUX to CH2
(do something else)
Switch MUX to CH3
(do another thing)

Why would compiler setting affect this logic? It is sequential, not time based.
> I will explain what I am doing. I am accessing a number of serial peripherals
> using the same UART, using a MUX. Code is something like this:
>
> Set MUX to CH1
> (do something)
> Switch MUX to CH2
> (do something else)
> Switch MUX to CH3
> (do another thing)
>
> Why would compiler setting affect this logic? It is sequential, not time
> based.

Then why say...

> > > What I am seeing when optimization is used is that their
> > > timing/duration is all messed up.

...? If you are seeing timing differences, you are seeing those because the
compiler has been asked to compile code, usually, to reduce code size or
increase execution speed. Both have effects on program execution timing.

Why do you think things should not change when you go from Debug to Release?
If it works in Debug mode, and that's what you're happy with, why not just
stay with that and get a bigger device if you are incapable of debugging the
release-mode software?

99.9% of the time, problems in user code are not problems in the compiler.
If you are seeing differences between Debug and Release configurations,
EXPECT YOUR CODE TO BE IN ERROR. Use the debugger, or as others have
suggested, a listing of the generated code. Don't hypothesize, you have
hardware, compiler, debugger, and an organic mass that is capable of
observation. Use those tools!

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426

Woh, Paul, I did not suggest there is a problem in the compiler. Yes it is more than likely there is a problem in the code. Just that I can't see it and can't understand what might be the cause for the different behavior (even with my compiler, debugger, and organic mass). Pardon me for seeking some direction from the group (other than "use those tools").

--- In m..., "Paul Curtis" wrote:
> 99.9% of the time, problems in user code are not problems in the compiler.
> If you are seeing differences between Debug and Release configurations,
> EXPECT YOUR CODE TO BE IN ERROR. Use the debugger, or as others have
> suggested, a listing of the generated code. Don't hypothesize, you have
> hardware, compiler, debugger, and an organic mass that is capable of
> observation. Use those tools!
>
Hi,

> Woh, Paul, I did not suggest there is a problem in the compiler. Yes it is
> more than likely there is a problem in the code. Just that I can't see it and
> can't understand what might be the cause for the different behavior (even with
> my compiler, debugger, and organic mass). Pardon me for seeking some direction
> from the group (other than "use those tools").

Why not go in and look at the code generated by the compiler, or identify
the issue using the debugger to single step? You have all the tools
necessary!

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426

On 08/02/2012 09:28, distantship101 wrote:
> --- In m... <mailto:msp430%40yahoogroups.com>, "Steve
> Mayfield" wrote:
> >
> > It is possible that the do {} while (0) is removed because the
> while(0) is
> > never true.
>
> That would be a major bug in the optimizer / compiler ! The "do" part in
> such construct is always executed at least once, since the test is not
> performed until after the first iteration.
>
> > Just take out the do and while(0) leaving the braces and what is
> > in the braces...
>
> Not a good idea. Code such as :
>
> if ( test )
> SWITCH_CH1();
> else
> ..
>
> will generate
>
> if ( test )
> { };
> else
> ..
>
> which is incorrect (two statements, { } and ; before "else"). You would
> need to write
>
> if ( test )
> SWITCH_CH1() // no ;
> else
> ..
>
> for it to compile, which is not intuitive.
>
> The do / while( 0 ) construct is needed to make multi-statement macro
> behave like real function calls.
>

That is why any sane coding standard will insist you write:

if (test) {
SWITCH_CH1();
} else {
...
}

The do/while(0) trick is an ugly hack to deal with people who can't
write code properly. Just because C /allows/ you to omit the brackets
in an "if" statement, does not mean it is a good idea!

In almost all cases, of course, it is better to define a function rather
than a function-like macro. If you particularly want it to be generated
inline rather than having a function call, then make it a "static
inline" function. Then it gives code as small (or big) and as fast as
the macro, but is typesafe, has better error checking, avoids the risk
of forgetting the "\" on multi-line macros, etc.
Of course, you are absolutely write about the reasons for having the
do/while(0), and how the compiler treats it.
On 08/02/2012 11:05, merapcb wrote:
>
> I will explain what I am doing. I am accessing a number of serial
> peripherals using the same UART, using a MUX. Code is something like this:
>
> Set MUX to CH1
> (do something)
> Switch MUX to CH2
> (do something else)
> Switch MUX to CH3
> (do another thing)
>

The most like source of the problem, I think, is not this sequence, but
the code that calls it. But until you actually /look/ at your code, and
the generated listings, then anything anyone says here is just
guesswork. There are a lot of very experienced developers here, but
none of us are mind readers.

We also get quite frustrated giving the same advice repeatedly and
having it ignored.

So once you have looked at the map file and studied the listing files,
start trimming out the code until you have minimal code that exhibits
the symptoms. Usually by this time you will have found the problem - if
not, you'll have more useful results to share here for more advice.

The general rule is that if code malfunctions when you use more
optimisation, /your/ code is wrong. And you should fix it - leaving
optimisation disabled is /not/ a fix. It will just delay your problem
until a later date when you have more code and it's harder for find the
problem.

mvh.,

David
Have you tried changing the macros to inline functions instead?

The 2024 Embedded Online Conference