Reply by Fırat Koçak January 31, 20112011-01-31
Hi David,

I now understand what you mean. I was expecting an adequate answer but
your is really huge. Thank you very very much. I am now more confident
with "volatile" and i will follow your recommendations. since this is my
first entry to using Msp430, for sure, i am not so much careful about
writing a good code, thus the code was a bit dirty. Since i am in the
beginning of the first phase of my learning curve, my intention is to
learn Msp430 peripherals, registers, memory, interrupts, timers, clock
setting and so on. After then i go in deep for a better code writing.
But with not forgetting your recommendations of a better code writing.

Writing a precise delay function is a big matter. Because i am not
writing a critical piece of code (at least not in the near future ) i
am OK and a rough C code will be enough.

David, thank you very much for your efforts helping me understand the
issue "volatile" and the other things. You are such a great friend!.

Best regards,

Firat

On 31.01.2011 10:35, David Brown wrote:
>
> On 31/01/2011 07:59, Fırat Koçak wrote:
> > Hi David,
> >
> > What i understand from what you have written is that Compiler, while
> > targeting the code, eliminates the piece of code which is unnecessary or
> > time consuming if that does not contain variable(s) declared as
> > volatile. Right ?
> > That's partly right. The compiler can eliminate code that is
> unnecessary. It has no concept of "time consuming", and even if it did,
> it certainly couldn't eliminate code just because it took time to run!
>
> The use of "volatile" in a case like the OP's, is to tell the compiler
> that the code is /not/ unnecessary even though it looks that way. If
> you make the index variable in a delay loop volatile, then the compiler
> is required to generate reads and writes to a storage space for that
> variable with the requested values, and in the requested order, with no
> assumptions as to what might happen to that storage space outside the
> compiler's control.
>
> void Delay( int dcount ) {
> volatile int iz;
> for( iz = 0; iz < dcount; iz ++ ){}
> }
>
> The compiler is still free to do some sorts of optimisations and code
> changes if it wants. For example, it can inline calls to Delay(), or
> could partially unroll the loop. It could even decide to calculate the
> first ten digits of pi inside the loop - as long as it didn't change the
> reads and writes to the volatile data.
>
> This is why such delay loops give only very rough timing - you have no
> guarantees. Different compilers, different versions of the same
> compiler, the same compiler with different flags, and the same compiler
> with the same flags but different calling code, can compile this loop in
> different ways and get different timings.
>
> There are several ways to get reliable timing in a microcontroller:
>
> 1. You make use of the hardware timers in some way, such as setting up
> an interrupt.
>
> 2. You poll hardware timers to check for elapsed time (this is often
> quite simple and a good choice).
>
> 3. You write the critical part of the code in assembly (typically using
> "asm volatile" statements - a good compiler can eliminate dead assembly
> code under certain circumstances). That way you know how many clock
> cycles each loop takes, and know exactly how it works.
>
> 4. You write the code in C, compile it with different flags and examine
> the generated assembly code. You can then be confident of how your
> Delay function works for that compiler - this can often be good enough
> for a given project, as long as you are aware of the portability issues.
>
> 5. You write the code in C, and use compiler-specific __attribute__'s or
> pragmas to force specific compilation or optimisation options for that
> function. You must still check the assembly, and consider the code
> non-portable, but you will have less risk of problems if you use
> different compiler flags for the rest of the project.
>
> 6. You use a Delay function of some sort provided by your toolchain
> vendor. These are often included as part of the library or as an
> intrinsic function. Then it is the toolchain vendor's responsibility to
> use assembly or C in a way that is independent of the compiler flags,
> and with a timing that is properly specified.
>
> Options 2 and 6 are typically the best choices. Option 4 sounds like a
> quick and easy solution, but beware that you can get a lot of variation.
> It might not matter if the time between your LED blinks is 400 ms or
> 600 ms, but it /will/ matter if it is 2000 ms.
>
> mvh.,
>
> David
>
> > In the meantime, thank you very much for the detailed information.
> >
> > Best regards,
> >
> > Firat
> >
> > On 31.01.2011 01:52, David Brown wrote:
> > >
> > > On 30/01/11 23:47, FIRAT KOCAK wrote:
> > > > Hi David,
> > > >
> > > > Honestly, after i read your message i said, "huh, that is it!" .
> thank
> > > > you very much. The problem has now gone. It runs well. I had
> read about
> > > > the issue "volatile" in the past messages but i have never
> thought it
> > > > will happen to me :) I am still struggling to understand why
> compiler
> > > > removes a local variable even though it is in use ?
> > > >
> > >
> > > "volatile" is very simple to understand once you realise that a
> compiler
> > > does not translate your source code into target code. A compiler reads
> > > your source code, and generates target code that has the same
> effect as
> > > though it had done a direct translation, but only in respect to
> reading
> > > and writing of volatile data.
> > >
> > > Re-read the previous paragraph, as it is a big step for many people.
> > >
> > > The compiler can totally disregard everything to do with local
> > > variables, global variables, functions, etc. All it is interested
> in is
> > > that every time your source code says it should read some volatile
> data,
> > > that data is read, and that every time your source code says it should
> > > write some volatile data, the correct value is written out.
> > >
> > > Typically, it will do this using a rough translation as a starting
> point
> > > - but only because that's the easiest way to handle the task.
> > >
> > > In particular, if the compiler can figure out that a piece of code has
> > > no effect on any volatile accesses, then it can remove it entirely.
> > >
> > > Also note that that the compiler has absolutely no sense of timing
> - the
> > > C language has no concept of time, only of the order of volatile
> > > accesses. So the correctness of the compiler's job is unchanged if it
> > > eliminates time-wasting code, or even if it adds time-wasting code
> > > (though compilers that add extra time-wasting code don't stay on the
> > > market very long).
> > >
> > > For hosted environments (such as on a desktop), calls to external
> > > library code also count as "volatile" for compilation purposes.
> > >
> > > Another common misconception is what "optimisation" flags do. They do
> > > /not/ enable or disable "optimisation", or command the compiler to
> > > generate different types of code. They are just hints as to how much
> > > effort the compiler should make in generating smaller and faster code,
> > > and sometimes they inform the compiler about assumptions it can make
> > > beyond the requirements of the C language (for example, you might
> > > promise to avoid aliasing data, and let the compiler take advantage of
> > > that promise to generate faster code).
> > >
> > > In particular, the compiler can remove useless code even with all
> > > optimisations disabled.
> > >
> > > > I think i need some time to better learn and read much about the
> > > > compiler behavior.
> > > >
> > > > Thank you and thanks to Bob and Dan.
> > > >
> > > > Firat
> > > >
> > > > On 31.01.2011 00:24, David Brown wrote:
> > > > >
> > > > > On 30/01/11 20:53, FIRAT KOCAK wrote:
> > > > > > Hi,
> > > > > >
> > > > > > I am a newbie to Msp430 and CCS. I installed CCS 4 and trying to
> > > learn
> > > > > > some coding Msp430 Launchpad. I modified original Launchpad code
> > > ( in
> > > > > > fact removed almost all code just adding led pins update in
> a loop
> > > > ). My
> > > > > > code is so simple and includes a few line codes.
> > > > > >
> > > > >
> > > > > If you are using CCS, I'd be sceptical of the compiler. Your code
> > > > > doesn't yet make use of your global variables like "BitCnt",
> but be
> > > > > aware that CCS does not initialise these to zero - in
> > contradiction to
> > > > > the C standards.
> > > > >
> > > > > > void Delay( int dcount )
> > > > > > {
> > > > > > int iz;
> > > > > >
> > > > > > for( iz = 0; iz < dcount; iz ++ ){}
> > > > > > }
> > > > > >
> > > > >
> > > > > You must declare "iz" to be volatile - if not, the compiler can
> > remove
> > > > > that loop entirely. It may well do so regardless of any
> optimisation
> > > > > settings you may have picked.
> > > > >
> > > > >
> > >
> > >
> >



Beginning Microcontrollers with the MSP430

Reply by David Brown January 31, 20112011-01-31
On 31/01/2011 02:50, Dan Bloomquist wrote:
> David Brown wrote:
> > On 31/01/11 00:10, Dan Bloomquist wrote:
> >
> >> Hi Firat,
> >>
> >> I just had to know. So I pasted your code into a default CCS project. It
> >> worked just as expected. I don't know why your build is optimized.
> >>
> >> Have your view/projects turned on. Right click the project and do 'Build
> >> properties'. Goto Compiler/optimizations and make sure nothing is
> >> checked. You don't need them to start with and it will keep your life
> >> simpler as you learn.
> >>
> >>
> > Absolutely wrong! You will /not/ make your life simpler by learning to
> > write bad code that only works with particular compiler flags - you will
> > make it simpler by learning to write correct code from the start. You
> > cannot do embedded programming until you understand "volatile".
> > "Learning" embedded programming with optimisations disabled "so that it
> > works" is like learning to drive a car in only first gear, because you
> > can't figure out how the brakes work, so you don't want to go too fast.
> >
> > Code whose correctness depends on the optimisation flags is broken code
> > (or a broken compiler), whether it works or not.
> >
> > Well, OK, if you say so...
>

I've been programming embedded systems for a /long/ time - using lots of
different tools of different qualities, and lots of different targets.
And perhaps more important than my own direct experience, I have
participated on mailing lists and newsgroups to help others since the
day our company got its first dial-up modem. I have seen a /lot/ of
examples of people having trouble because they don't understand about
"volatile" and optimisations, and find their code no longer works when
they enable optimisations, or when they move to a better compiler.

I have no doubt whatsoever that the best answer is to learn to use
volatile correctly from day 1 when you are doing embedded programming.
It will be of great benefit later.

I don't know anything about your background except your mention of
having programmed with MS VS for over a decade as your "day job". It is
important to realise that there is a big difference here between
bare-metal embedded programming, and programming for an operating
system. When using an OS, the program interacts with the outside world
using system calls (generally via a library). These system calls take
the place of "volatile" in almost all cases - the compiler will always
make these calls as requested by the source code. But for bare-metal
programming, you don't have that - you use "volatile" accesses to
interact with the world. Often this is done using the hardware register
definitions in include files - these are invariably defined as
"volatile". But if you want to have interaction outside of these, you
need to use "volatile" yourself.

And once you start working with interrupt routines, you have no choice
but to get "volatile" correct. Regardless of your optimisation flags,
"volatile" is what makes the difference between the system working all
the time, or the system working all the time except for impossible to
reproduce bugs that turn up occasionally on the customer's system.
I am a professional embedded programmer. I want my code to be correct -
it is not enough for me that something happens to work under certain
artificially constrained circumstances. I know that these circumstances
change, and fragile code breaks. And I also know there are a lot of
programmers who get these things wrong, even people with long experience
and/or education. So I have no qualms about giving people helpful
advice about how to write better code - many people need that advice.
Of course, please let me know if you think I am wrong - either that
there are circumstances when it is appropriate for code correctness to
depend on optimisation flags, or perhaps that it is not something to
emphasize for newbies to the field. I have plenty to learn here,
regarding both programming and helping other programmers. And even if
it turns out that we don't agree, the discussion can be informative to
both ourselves and others reading the thread.

mvh.,

David
Reply by David Brown January 31, 20112011-01-31
On 31/01/2011 07:59, Fırat Koçak wrote:
> Hi David,
>
> What i understand from what you have written is that Compiler, while
> targeting the code, eliminates the piece of code which is unnecessary or
> time consuming if that does not contain variable(s) declared as
> volatile. Right ?
>

That's partly right. The compiler can eliminate code that is
unnecessary. It has no concept of "time consuming", and even if it did,
it certainly couldn't eliminate code just because it took time to run!

The use of "volatile" in a case like the OP's, is to tell the compiler
that the code is /not/ unnecessary even though it looks that way. If
you make the index variable in a delay loop volatile, then the compiler
is required to generate reads and writes to a storage space for that
variable with the requested values, and in the requested order, with no
assumptions as to what might happen to that storage space outside the
compiler's control.

void Delay( int dcount ) {
volatile int iz;
for( iz = 0; iz < dcount; iz ++ ){}
}

The compiler is still free to do some sorts of optimisations and code
changes if it wants. For example, it can inline calls to Delay(), or
could partially unroll the loop. It could even decide to calculate the
first ten digits of pi inside the loop - as long as it didn't change the
reads and writes to the volatile data.

This is why such delay loops give only very rough timing - you have no
guarantees. Different compilers, different versions of the same
compiler, the same compiler with different flags, and the same compiler
with the same flags but different calling code, can compile this loop in
different ways and get different timings.

There are several ways to get reliable timing in a microcontroller:

1. You make use of the hardware timers in some way, such as setting up
an interrupt.

2. You poll hardware timers to check for elapsed time (this is often
quite simple and a good choice).

3. You write the critical part of the code in assembly (typically using
"asm volatile" statements - a good compiler can eliminate dead assembly
code under certain circumstances). That way you know how many clock
cycles each loop takes, and know exactly how it works.

4. You write the code in C, compile it with different flags and examine
the generated assembly code. You can then be confident of how your
Delay function works for that compiler - this can often be good enough
for a given project, as long as you are aware of the portability issues.

5. You write the code in C, and use compiler-specific __attribute__'s or
pragmas to force specific compilation or optimisation options for that
function. You must still check the assembly, and consider the code
non-portable, but you will have less risk of problems if you use
different compiler flags for the rest of the project.

6. You use a Delay function of some sort provided by your toolchain
vendor. These are often included as part of the library or as an
intrinsic function. Then it is the toolchain vendor's responsibility to
use assembly or C in a way that is independent of the compiler flags,
and with a timing that is properly specified.
Options 2 and 6 are typically the best choices. Option 4 sounds like a
quick and easy solution, but beware that you can get a lot of variation.
It might not matter if the time between your LED blinks is 400 ms or
600 ms, but it /will/ matter if it is 2000 ms.

mvh.,

David

> In the meantime, thank you very much for the detailed information.
>
> Best regards,
>
> Firat
>
> On 31.01.2011 01:52, David Brown wrote:
> >
> > On 30/01/11 23:47, FIRAT KOCAK wrote:
> > > Hi David,
> > >
> > > Honestly, after i read your message i said, "huh, that is it!" . thank
> > > you very much. The problem has now gone. It runs well. I had read about
> > > the issue "volatile" in the past messages but i have never thought it
> > > will happen to me :) I am still struggling to understand why compiler
> > > removes a local variable even though it is in use ?
> > >
> >
> > "volatile" is very simple to understand once you realise that a compiler
> > does not translate your source code into target code. A compiler reads
> > your source code, and generates target code that has the same effect as
> > though it had done a direct translation, but only in respect to reading
> > and writing of volatile data.
> >
> > Re-read the previous paragraph, as it is a big step for many people.
> >
> > The compiler can totally disregard everything to do with local
> > variables, global variables, functions, etc. All it is interested in is
> > that every time your source code says it should read some volatile data,
> > that data is read, and that every time your source code says it should
> > write some volatile data, the correct value is written out.
> >
> > Typically, it will do this using a rough translation as a starting point
> > - but only because that's the easiest way to handle the task.
> >
> > In particular, if the compiler can figure out that a piece of code has
> > no effect on any volatile accesses, then it can remove it entirely.
> >
> > Also note that that the compiler has absolutely no sense of timing - the
> > C language has no concept of time, only of the order of volatile
> > accesses. So the correctness of the compiler's job is unchanged if it
> > eliminates time-wasting code, or even if it adds time-wasting code
> > (though compilers that add extra time-wasting code don't stay on the
> > market very long).
> >
> > For hosted environments (such as on a desktop), calls to external
> > library code also count as "volatile" for compilation purposes.
> >
> > Another common misconception is what "optimisation" flags do. They do
> > /not/ enable or disable "optimisation", or command the compiler to
> > generate different types of code. They are just hints as to how much
> > effort the compiler should make in generating smaller and faster code,
> > and sometimes they inform the compiler about assumptions it can make
> > beyond the requirements of the C language (for example, you might
> > promise to avoid aliasing data, and let the compiler take advantage of
> > that promise to generate faster code).
> >
> > In particular, the compiler can remove useless code even with all
> > optimisations disabled.
> >
> > > I think i need some time to better learn and read much about the
> > > compiler behavior.
> > >
> > > Thank you and thanks to Bob and Dan.
> > >
> > > Firat
> > >
> > > On 31.01.2011 00:24, David Brown wrote:
> > > >
> > > > On 30/01/11 20:53, FIRAT KOCAK wrote:
> > > > > Hi,
> > > > >
> > > > > I am a newbie to Msp430 and CCS. I installed CCS 4 and trying to
> > learn
> > > > > some coding Msp430 Launchpad. I modified original Launchpad code
> > ( in
> > > > > fact removed almost all code just adding led pins update in a loop
> > > ). My
> > > > > code is so simple and includes a few line codes.
> > > > >
> > > >
> > > > If you are using CCS, I'd be sceptical of the compiler. Your code
> > > > doesn't yet make use of your global variables like "BitCnt", but be
> > > > aware that CCS does not initialise these to zero - in
> contradiction to
> > > > the C standards.
> > > >
> > > > > void Delay( int dcount )
> > > > > {
> > > > > int iz;
> > > > >
> > > > > for( iz = 0; iz < dcount; iz ++ ){}
> > > > > }
> > > > >
> > > >
> > > > You must declare "iz" to be volatile - if not, the compiler can
> remove
> > > > that loop entirely. It may well do so regardless of any optimisation
> > > > settings you may have picked.
> > > >
> > > >
> >
>

Reply by David Brown January 31, 20112011-01-31
On 31/01/11 02:49, Dan Bloomquist wrote:
> David Brown wrote:
> >
> > In particular, the compiler can remove useless code even with all
> > optimisations disabled.
> >
> > Hi David,
> And the confusing part. On my box his code ran like expected, (the leds
> are still flashing). I'm using the latest CCS4. I do not see gcc remove
> code what so ever without optimization; at least, so far. As I have the

gcc doesn't remove normally dead code if optimisation is disabled. But
the point is, it is allowed to do so if it (i.e., the compiler writers)
wanted to. In fact, if you use the -ffunction-sections option, which
technically is not an optimisation, then functions that are unused are
removed at link time. And perhaps future versions of gcc will remove
dead code even without optimisation.

> source on my machine I'll know better as time goes. But I would expect
> all code to make it to the target without optimization. I know for sure
> it is the case with microsoft, It has been my day job for over a decade
> to code with VS and I put all kinds of useless code in during

Temporary test code added during development is fine. Useless code in a
shipping version is not fine. It might be common in the world of
Windows programming with VS, but it is /not/ common in the embedded
development world. Bloated code means larger devices with more memory,
and higher costs - no serious embedded developer will do that on typical
projects (on hobby projects, or low-volume projects, the code efficiency
versus developer efficiency tradeoffs are different).

> development. It is always there. Several years ago I had a bug because
> MS optimized out some important code. I have yet to enable any
> optimization since. It doesn't make a lot of sense to optimize most box
> code anyway.
>

It makes no sense whatsoever to have a good compiler that generates
small and fast code, then cripple it by not using optimisation. It
makes no sense to produce target code that is much larger and slower
than it need be when the compiler can make huge improvements just by
adding a "-O2" switch. That's just money down the drain.

It may be that MS' compiler has a bug in its optimiser - I have seen
optimiser bugs in poor quality compilers on occasion. But without
knowing anything else about the compiler, the code, or the programmer, I
would guess the likely cause is a bug in your source code.

mvh.,

David
> It would have been insightful to know what Firat saw in the disassembly.
>
> Best, Dan.
Reply by Fırat Koçak January 31, 20112011-01-31
Hi David,

What i understand from what you have written is that Compiler, while
targeting the code, eliminates the piece of code which is unnecessary or
time consuming if that does not contain variable(s) declared as
volatile. Right ?

In the meantime, thank you very much for the detailed information.

Best regards,

Firat

On 31.01.2011 01:52, David Brown wrote:
>
> On 30/01/11 23:47, FIRAT KOCAK wrote:
> > Hi David,
> >
> > Honestly, after i read your message i said, "huh, that is it!" . thank
> > you very much. The problem has now gone. It runs well. I had read about
> > the issue "volatile" in the past messages but i have never thought it
> > will happen to me :) I am still struggling to understand why compiler
> > removes a local variable even though it is in use ?
> > "volatile" is very simple to understand once you realise that a compiler
> does not translate your source code into target code. A compiler reads
> your source code, and generates target code that has the same effect as
> though it had done a direct translation, but only in respect to reading
> and writing of volatile data.
>
> Re-read the previous paragraph, as it is a big step for many people.
>
> The compiler can totally disregard everything to do with local
> variables, global variables, functions, etc. All it is interested in is
> that every time your source code says it should read some volatile data,
> that data is read, and that every time your source code says it should
> write some volatile data, the correct value is written out.
>
> Typically, it will do this using a rough translation as a starting point
> - but only because that's the easiest way to handle the task.
>
> In particular, if the compiler can figure out that a piece of code has
> no effect on any volatile accesses, then it can remove it entirely.
>
> Also note that that the compiler has absolutely no sense of timing - the
> C language has no concept of time, only of the order of volatile
> accesses. So the correctness of the compiler's job is unchanged if it
> eliminates time-wasting code, or even if it adds time-wasting code
> (though compilers that add extra time-wasting code don't stay on the
> market very long).
>
> For hosted environments (such as on a desktop), calls to external
> library code also count as "volatile" for compilation purposes.
>
> Another common misconception is what "optimisation" flags do. They do
> /not/ enable or disable "optimisation", or command the compiler to
> generate different types of code. They are just hints as to how much
> effort the compiler should make in generating smaller and faster code,
> and sometimes they inform the compiler about assumptions it can make
> beyond the requirements of the C language (for example, you might
> promise to avoid aliasing data, and let the compiler take advantage of
> that promise to generate faster code).
>
> In particular, the compiler can remove useless code even with all
> optimisations disabled.
>
> > I think i need some time to better learn and read much about the
> > compiler behavior.
> >
> > Thank you and thanks to Bob and Dan.
> >
> > Firat
> >
> > On 31.01.2011 00:24, David Brown wrote:
> > >
> > > On 30/01/11 20:53, FIRAT KOCAK wrote:
> > > > Hi,
> > > >
> > > > I am a newbie to Msp430 and CCS. I installed CCS 4 and trying to
> learn
> > > > some coding Msp430 Launchpad. I modified original Launchpad code
> ( in
> > > > fact removed almost all code just adding led pins update in a loop
> > ). My
> > > > code is so simple and includes a few line codes.
> > > >
> > >
> > > If you are using CCS, I'd be sceptical of the compiler. Your code
> > > doesn't yet make use of your global variables like "BitCnt", but be
> > > aware that CCS does not initialise these to zero - in contradiction to
> > > the C standards.
> > >
> > > > void Delay( int dcount )
> > > > {
> > > > int iz;
> > > >
> > > > for( iz = 0; iz < dcount; iz ++ ){}
> > > > }
> > > >
> > >
> > > You must declare "iz" to be volatile - if not, the compiler can remove
> > > that loop entirely. It may well do so regardless of any optimisation
> > > settings you may have picked.
> > >
> > >



Reply by Dan Bloomquist January 30, 20112011-01-30
David Brown wrote:
> On 31/01/11 00:10, Dan Bloomquist wrote:
>
>> Hi Firat,
>>
>> I just had to know. So I pasted your code into a default CCS project. It
>> worked just as expected. I don't know why your build is optimized.
>>
>> Have your view/projects turned on. Right click the project and do 'Build
>> properties'. Goto Compiler/optimizations and make sure nothing is
>> checked. You don't need them to start with and it will keep your life
>> simpler as you learn.
>>
>>
> Absolutely wrong! You will /not/ make your life simpler by learning to
> write bad code that only works with particular compiler flags - you will
> make it simpler by learning to write correct code from the start. You
> cannot do embedded programming until you understand "volatile".
> "Learning" embedded programming with optimisations disabled "so that it
> works" is like learning to drive a car in only first gear, because you
> can't figure out how the brakes work, so you don't want to go too fast.
>
> Code whose correctness depends on the optimisation flags is broken code
> (or a broken compiler), whether it works or not.
>
>

Well, OK, if you say so...

Reply by Dan Bloomquist January 30, 20112011-01-30
David Brown wrote:
>
> In particular, the compiler can remove useless code even with all
> optimisations disabled.
>
>

Hi David,
And the confusing part. On my box his code ran like expected, (the leds
are still flashing). I'm using the latest CCS4. I do not see gcc remove
code what so ever without optimization; at least, so far. As I have the
source on my machine I'll know better as time goes. But I would expect
all code to make it to the target without optimization. I know for sure
it is the case with microsoft, It has been my day job for over a decade
to code with VS and I put all kinds of useless code in during
development. It is always there. Several years ago I had a bug because
MS optimized out some important code. I have yet to enable any
optimization since. It doesn't make a lot of sense to optimize most box
code anyway.

It would have been insightful to know what Firat saw in the disassembly.

Best, Dan.

Reply by old_cow_yellow January 30, 20112011-01-30
Another phenomenal I observed is: people often "Release" what they did not "Debug" and "Debug" what they do not intend to "Release".

Just as puzzling as "vaporized" when not "volatile".

--- In m..., FIRAT KOCAK wrote:
>
> Hi OCS,
>
> Yes, as David and you suggested, volatile declaration did the job.
>
> Thank you very much.
>
> Firat
>
> On 31.01.2011 00:49, old_cow_yellow wrote:
> >
> > Some of your code may have vaporized because your variables are not
> > volatile.
> >
> > --- In m... , FIRAT
> > KOCAK wrote:
> > >
> > > Hi,
> > >
> > > I am a newbie to Msp430 and CCS. I installed CCS 4 and trying to learn
> > > some coding Msp430 Launchpad. I modified original Launchpad code ( in
> > > fact removed almost all code just adding led pins update in a loop
> > ). My
> > > code is so simple and includes a few line codes.
> > >
> > > My problem is, i successfully build the project and start debugger
> > and i
> > > am able to execute the code step by step. It works as expected. But
> > > after closing the debugger and resetting the board( simply remove the
> > > usb cable and then reconnect it ) leds are always lit. My code is below
> > >
> > > #include "msp430x20x2.h"
> > >
> > > #define LED0 BIT0
> > > #define LED1 BIT6
> > > #define LED_DIR P1DIR
> > > #define LED_OUT P1OUT
> > >
> > >
> > >
> > > #define BUTTON BIT3
> > > #define BUTTON_OUT P1OUT
> > > #define BUTTON_DIR P1DIR
> > > #define BUTTON_IN P1IN
> > > #define BUTTON_IE P1IE
> > > #define BUTTON_IES P1IES
> > > #define BUTTON_IFG P1IFG
> > > #define BUTTON_REN P1REN
> > >
> > > #define TXD BIT1 // TXD on P1.1
> > > #define RXD BIT2 // RXD on P1.2
> > >
> > > #define APP_STANDBY_MODE 0
> > > #define APP_APPLICATION_MODE 1
> > >
> > > #define TIMER_PWM_MODE 0
> > > #define TIMER_UART_MODE 1
> > > #define TIMER_PWM_PERIOD 2000
> > > #define TIMER_PWM_OFFSET 20
> > >
> > > #define TEMP_SAME 0
> > > #define TEMP_HOT 1
> > > #define TEMP_COLD 2
> > >
> > > #define TEMP_THRESHOLD 5
> > >
> > > // Conditions for 9600/4$00 Baud SW UART, SMCLK = 1MHz
> > > #define Bitime_5 0x05*4 // ~ 0.5
> > > bit length + small adjustment
> > > #define Bitime 13*4//0x0D
> > >
> > > #define UART_UPDATE_INTERVAL 1000
> > >
> > >
> > > unsigned char BitCnt;
> > >
> > >
> > > unsigned char applicationMode = APP_STANDBY_MODE;
> > > unsigned char timerMode = TIMER_PWM_MODE;
> > >
> > > unsigned char tempMode;
> > > unsigned char calibrateUpdate = 0;
> > > unsigned char tempPolarity = TEMP_SAME;
> > > unsigned int TXByte;
> > >
> > > /* Using an 8-value moving average filter on sampled ADC values */
> > > long tempMeasured[8];
> > > unsigned char tempMeasuredPosition=0;
> > > long tempAverage;
> > >
> > > long tempCalibrated, tempDifference;
> > >
> > >
> > >
> > > void InitializeLeds(void);
> > > void InitializeButton(void);
> > > void InitializeClocks(void);
> > >
> > > void InitializeClocks(void)
> > > {
> > >
> > > BCSCTL1 = CALBC1_1MHZ; // Set range
> > > DCOCTL = CALDCO_1MHZ;
> > > BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO / 8 = 1MHz
> > > }
> > >
> > > void InitializeButton(void) // Configure Push Button
> > > {
> > > BUTTON_DIR &= ~BUTTON;
> > > BUTTON_OUT |= BUTTON;
> > > BUTTON_REN |= BUTTON;
> > > BUTTON_IES |= BUTTON;
> > > BUTTON_IFG &= ~BUTTON;
> > > BUTTON_IE |= BUTTON;
> > > }
> > >
> > >
> > > void InitializeLeds(void)
> > > {
> > > LED_DIR |= LED0 + LED1;
> > > LED_OUT &= ~(LED0 + LED1);
> > > }
> > >
> > > void Delay( int dcount )
> > > {
> > > int iz;
> > >
> > > for( iz = 0; iz < dcount; iz ++ ){}
> > > }
> > >
> > >
> > > void main(void)
> > > {
> > > WDTCTL = WDTPW + WDTHOLD; // Stop WDT
> > >
> > > InitializeClocks();
> > > InitializeLeds();
> > >
> > > while( 1 )
> > > {
> > > LED_OUT &= ~( LED0 + LED1 );
> > > Delay( 10000 );
> > > LED_OUT |= ( LED0 + LED1 );
> > > Delay( 10000 );
> > > }
> > >
> > > }
> > >
> > >
> > > Changing the delay count does not help. Changing build type from debug
> > > to release does not help. Probably i forget or miss something but i
> > > could not find out it.
> > >
> > > Any help is appreciated.
> > >
> > >
> > > Best regards,
> > >
> > > Firat
> > >
> > >
> > >
> > >
> >
> >
>

Reply by David Brown January 30, 20112011-01-30
On 31/01/11 00:10, Dan Bloomquist wrote:
> Hi Firat,
>
> I just had to know. So I pasted your code into a default CCS project. It
> worked just as expected. I don't know why your build is optimized.
>
> Have your view/projects turned on. Right click the project and do 'Build
> properties'. Goto Compiler/optimizations and make sure nothing is
> checked. You don't need them to start with and it will keep your life
> simpler as you learn.
>

Absolutely wrong! You will /not/ make your life simpler by learning to
write bad code that only works with particular compiler flags - you will
make it simpler by learning to write correct code from the start. You
cannot do embedded programming until you understand "volatile".
"Learning" embedded programming with optimisations disabled "so that it
works" is like learning to drive a car in only first gear, because you
can't figure out how the brakes work, so you don't want to go too fast.

Code whose correctness depends on the optimisation flags is broken code
(or a broken compiler), whether it works or not.
Reply by David Brown January 30, 20112011-01-30
On 30/01/11 23:47, FIRAT KOCAK wrote:
> Hi David,
>
> Honestly, after i read your message i said, "huh, that is it!" . thank
> you very much. The problem has now gone. It runs well. I had read about
> the issue "volatile" in the past messages but i have never thought it
> will happen to me :) I am still struggling to understand why compiler
> removes a local variable even though it is in use ?
>

"volatile" is very simple to understand once you realise that a compiler
does not translate your source code into target code. A compiler reads
your source code, and generates target code that has the same effect as
though it had done a direct translation, but only in respect to reading
and writing of volatile data.

Re-read the previous paragraph, as it is a big step for many people.

The compiler can totally disregard everything to do with local
variables, global variables, functions, etc. All it is interested in is
that every time your source code says it should read some volatile data,
that data is read, and that every time your source code says it should
write some volatile data, the correct value is written out.

Typically, it will do this using a rough translation as a starting point
- but only because that's the easiest way to handle the task.

In particular, if the compiler can figure out that a piece of code has
no effect on any volatile accesses, then it can remove it entirely.

Also note that that the compiler has absolutely no sense of timing - the
C language has no concept of time, only of the order of volatile
accesses. So the correctness of the compiler's job is unchanged if it
eliminates time-wasting code, or even if it adds time-wasting code
(though compilers that add extra time-wasting code don't stay on the
market very long).

For hosted environments (such as on a desktop), calls to external
library code also count as "volatile" for compilation purposes.

Another common misconception is what "optimisation" flags do. They do
/not/ enable or disable "optimisation", or command the compiler to
generate different types of code. They are just hints as to how much
effort the compiler should make in generating smaller and faster code,
and sometimes they inform the compiler about assumptions it can make
beyond the requirements of the C language (for example, you might
promise to avoid aliasing data, and let the compiler take advantage of
that promise to generate faster code).

In particular, the compiler can remove useless code even with all
optimisations disabled.
> I think i need some time to better learn and read much about the
> compiler behavior.
>
> Thank you and thanks to Bob and Dan.
>
> Firat
>
> On 31.01.2011 00:24, David Brown wrote:
> >
> > On 30/01/11 20:53, FIRAT KOCAK wrote:
> > > Hi,
> > >
> > > I am a newbie to Msp430 and CCS. I installed CCS 4 and trying to learn
> > > some coding Msp430 Launchpad. I modified original Launchpad code ( in
> > > fact removed almost all code just adding led pins update in a loop
> ). My
> > > code is so simple and includes a few line codes.
> > >
> >
> > If you are using CCS, I'd be sceptical of the compiler. Your code
> > doesn't yet make use of your global variables like "BitCnt", but be
> > aware that CCS does not initialise these to zero - in contradiction to
> > the C standards.
> >
> > > void Delay( int dcount )
> > > {
> > > int iz;
> > >
> > > for( iz = 0; iz < dcount; iz ++ ){}
> > > }
> > >
> >
> > You must declare "iz" to be volatile - if not, the compiler can remove
> > that loop entirely. It may well do so regardless of any optimisation
> > settings you may have picked.
> >
> >