Reply by Preston Gurd June 1, 20042004-06-01
Hello Dirk,

I have just finished reading, with great interest, your comments about
your experience with using the AQ430 C compiler for your application.
I have also looked at Wolfgang Reich's practical suggestions and your
response to them, and at Anders Lindgren's comments, as well.

I gather that you try to inline just about every function call in your
application and that the AQ430 C compiler is not as good at handling your
code as the IAR compiler, although you can get pretty close.

First of all, I should point out that, in AQ430 C, any inline function
which is only ever called to be expanded inline (as opposed to calling
it externally or indirectly) should be declared as static. If you do not
declare it as static, then the compiler emits a function body, taking up
more space. So you should use

	static __inline__ 

Since the "embedded C" standard appears to say that you should only
get a function body if you say "extern inline", the default behavuour
of the compiler may change sometime soon, but "static __inline__" will
always do what is reasonable to expect.

You noted that the compiler does not appear to do dead code elimination.
This is not quite true! The compiler does in fact do dead code elimination
*most* of the time!
However, If a function is expanded inline and one of the variables
in the expansion is replaced by a constant argument, then the compiler
does not by default look to eliminate any dead code introduced as
a result of the substitution of the variable by the constant. 

However, if you turn on the global optimizer (by using "+O" C
compiler
command line option), then you will get a much higher level of optimization
(but you will lose the ability to symbolically debug the code thus optimized).
For the following code sample, based on the one which you posted:

#define __AQCOMPILER__
#define inline __inline__
#include "msp430x14x.h"

static inline int IsVoltageAboveTheshold(void)
{
    CACTL1 = 2;   // set up the comparator
    _NOP();                 // wait for settling
    return (!(CACTL1 & CAOUT));
}


static inline int Signal(int state)
{
    if ( state == -1 )
       P1OUT &= ~ BIT2;
       
    if ( state == 1 )
       P1OUT |= BIT2;
       
    return ( P1OUT & BIT2 );
}

void main(void)
{
    if ( IsVoltageAboveTheshold() )
      Signal( 1 );
}


The code size with default optimization was 56 bytes. With +O, it is
30 bytes. Among other things, it eliminates the redundant compares
of 1 ("state") to 1 and -1 in the inline expansion of Signal().

You also mentioned a problem with starting by double clicking the project
file. This is now fixed and will be in the next release. If you would
like to obtain a fixed version earlier, please send email to
aq430support@aq43... .
 
I appreciate your taking the time to study this issue and for sharing
what you found with the msp430 community. It had not occurred to me that
people might want to use inline functions in the way you have done. As a
result of your comments, I will be looking into ways to improve AQ430 C's
handling of inline functions.

If you have any other suggestions for improvement of the AQ430 C code generator,
please do not hesitate to get in touch with me directly. 

All the best,

Preston Gurd
(the AQ430 C compiler guy)

Beginning Microcontrollers with the MSP430

Reply by onestone June 1, 20042004-06-01
Hi Kris.

As we've discussed often before it's very much horses for courses. I 
NEVER expect to have to port anything I design to another micro. Even if 
I do the time taken is trivial. Not as fast as porting using compilers 
from the same vendor perhaps, but almost certainly faster than porting 
using a new compiler. My own course through programming was rather odd. 
Not counting the valve circuit that added two unitary numbers and gave 
the result on nixie tubes which I built around 1965. Staring around 
1970, and in the following approximate order:-

custom binary with LOGIC GATE BASED computers of my own design.
hexa decimal with early micros (4004/8008)
Custom medium level language for military digital radar
6800 asm
128bit mainframe binary
128 bit micro-code (Eureka! moment when I discovered this)
COBOL
6502 asm
8048 hex
6809 asm
8080 asm
8085 asm
BASIC
8051 asm
LISP
Modula (can't remember I or II)
PROLOG
C
80x86 asm & C
8087 asm
ADA
Relay ladder
Pascal (yeuk)
PIC asm (pre-microchip)
C++ (a JOKE)
68k asm & C
ADSP21XX	(THE BEST LANGUAGE OF THEM ALL)
68HC various & C
ADSP SHARC asm & C
TMS 320C3x asm
FAIRCHILD ASM
AVR ASM
OTHER TMS320FXXXX ASMS
MSP430
56F800 ASM
ARM ASM

As you know, I'm the opposite, even though we work in similar areas. I 
too do a lot of designs with a wide variety of sibngle chip 
transceivers. I can't imagine doing my designs without asm. It's okay 
writing a HAL that is all singing all dancing, but its very abstraction 
will usually, in my experience, force compromise on the  actaul hardware 
interface level which I'm not prepared to accept. Rather I have 
configuration libraries for various different parts, and a common 
protocol library, thus I'm implicitly NOT abstracting the hardware,
I'm 
getting very close up and personal to it, but I am, to some degree 
abstracting the higher level functions, again almost the opposite to 
yourself and Dirk.

Perhaps this is because my original interest was hardware, and my 
preference for many years was hardware. Software was merely something 
the hardware used to give itself adaptive functionality. Once hardware 
became, to some extent, boring, or less challenging, software in and of 
itself became more interesting., however, since I still believe that 
better designs are created when both areas are well understood, I have 
never been attracted to the idea of hardware abstraction, in fact it is 
anathema to me.

cheers

Al




microbit wrote:
> Hi Dirk,
> 
> 
>>I could think in asm, and I absolutely have to at least when I design
>>the HAL.
>>But in all layers above that I don't want to care at all, if this
>>algorithm is run on an MSP, a PC, my coffee-machine or fed into
"The
>>Matrix".
> 
> 
> I've been following part of this thread with interest, and I agree
here 100%,
> regardless of any other moot issues.
> I work a lot with single chip RF transceivers.
> Now, I've written a Hardware Abstraction Library for many different RF
parts.
> 
> One client has moved on to 3 different RF parts : in each case it took me
< 20 mins.
> to bolt on the existing complete C coded DLL + network application to the
new HAL.
> He's moved from IAR EW90 (on 8535 AVR) to ICC-AVR : it took me < 5
mins to
> recompile the project, no bugs, no side effects, no HW problems.
> At one stage I've actually even debugged a new HAL on MSP430 RF
Hardware with
> RAL CW430, and then ported it back to ICC-AVR and recompiled it,
effortlessly.
> The API only has a few simple user calls for the APP, and - admittedly - it
is a 
> relatively simple application.
> But the point is that porting the whole application code from MSP430 ->
AVR and 
> AVR-> MSP430 took < 5 mins. I'd HATE to do this in ASM !!!!
> (of course you'd only have to do this once !)
> This client id considering going to ARM. When he does it will again take me
> little effort to rebuild the machine code on ARM.
> 
> This is of course a specific example, but I'm from the other
"school" :
> I wrote solely in ASM for quite a few years, and since about 6 years I
couldn't
> imagine running a business efficiently without the use of C and respective
compilers.
> 
> The rest is indeed moot. Just like the issue of C++ and OOP is.
> OOP is a programming concept, not a language. I'm actually trying to
write more
> and more in what I guess is called "C+" rather than C if
it's worth it.
> Eventually I'd like to learn more about EC++.
> 
> B rgds
> Kris
> 
> 
> 
> 
> 
> 
> 
> .
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 
> 


Reply by Andreas Schwarz June 1, 20042004-06-01
Dirk Reymann wrote:
> So my wish would be:
> 
> IAR - please add a register feature like QA430 does.
> 
> Quadravox - please improve your optimizer  (inlining, dead-code).
> 
> If both of you did so, we had two extremely effective compilers for
> our MSP430.

Did you try MSPGCC? In my experience it generates much better code than 
IAR in some cases. Just post a piece of code and let's see what the 
different compilers make out of it.


Reply by Anders Lindgren June 1, 20042004-06-01
Dirk Reymann <d.reymann@d.re...> writes:

> inline int IsVoltageAboveTheshold(void)
> {
>     CACTL = SOME_PATTERN;   // set up the comparator
>     _NOP();                 // wait for settling
>     return (!(CACTL & CAOUT));
> }
>
>
> inline int Signal(int state)
> {
>     if ( state == -1 )
>        P1OUT &= ~ BIT2;
>
>     if ( state == 1 )
>        P1OUT |= BIT2;
>
>     return ( P1OUT & BIT2 );
> }
>
> void main(void)
> {
>     if ( IsVoltageAboveTheshold() )
>       Signal( 1 );
> }

> --------------------------------
> I'm looking forward to any suggestions how to "improve" the
inlined
> functions above.
> Do NOT change main().
> --------------------------------

In the example above the Signal function returns a value.  This value
contains a read from a volatile.  Since volatile accesses musn't be
changed all compiler must generate code to perform this access, even
if your code ignores the return value from Signal.

You can see this in the generated code:

     29                Signal( 1 );
         \\ This performs the side-effects.
   \   000010   E2D22100             BIS.B   #0x4, &0x21

         \\ This is the remainder of the return statement of Signal.
   \   000014   C2932100             CMP.B   #0x0, &0x21

What you could do is to redefine Signal so that it doesn't return a
value at all, and implement a second function that does, for example
(using a ridiculously long name for the new function):


inline void Signal(int state)
{
    if ( state == -1 )
       P1OUT &= ~ BIT2;

    if ( state == 1 )
       P1OUT |= BIT2;
}

inline int SignalAndReturnStatus(int state)
{
   Signal(state)
   return ( P1OUT & BIT2 );
}


The effect is a four byte reduction for each call site where the
return value of Signal is discarded.

I would guess that you would get an improvment for this on all
compilers on the market, not just when using our tools.

    -- Anders Lindgren, IAR Systems
-- 
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.

Reply by microbit June 1, 20042004-06-01
Hi Dirk,

> I could think in asm, and I absolutely have to at
least when I design
> the HAL.
> But in all layers above that I don't want to care at all, if this
> algorithm is run on an MSP, a PC, my coffee-machine or fed into "The
> Matrix".

I've been following part of this thread with interest, and I agree here
100%,
regardless of any other moot issues.
I work a lot with single chip RF transceivers.
Now, I've written a Hardware Abstraction Library for many different RF
parts.

One client has moved on to 3 different RF parts : in each case it took me <
20 mins.
to bolt on the existing complete C coded DLL + network application to the new
HAL.
He's moved from IAR EW90 (on 8535 AVR) to ICC-AVR : it took me < 5 mins
to
recompile the project, no bugs, no side effects, no HW problems.
At one stage I've actually even debugged a new HAL on MSP430 RF Hardware
with
RAL CW430, and then ported it back to ICC-AVR and recompiled it, effortlessly.
The API only has a few simple user calls for the APP, and - admittedly - it is a

relatively simple application.
But the point is that porting the whole application code from MSP430 -> AVR
and 
AVR-> MSP430 took < 5 mins. I'd HATE to do this in ASM !!!!
(of course you'd only have to do this once !)
This client id considering going to ARM. When he does it will again take me
little effort to rebuild the machine code on ARM.

This is of course a specific example, but I'm from the other
"school" :
I wrote solely in ASM for quite a few years, and since about 6 years I
couldn't
imagine running a business efficiently without the use of C and respective
compilers.

The rest is indeed moot. Just like the issue of C++ and OOP is.
OOP is a programming concept, not a language. I'm actually trying to write
more
and more in what I guess is called "C+" rather than C if it's
worth it.
Eventually I'd like to learn more about EC++.

B rgds
Kris





Reply by onestone May 31, 20042004-05-31
Of course you know that this could be an endless debate ;@}

Dirk Reymann wrote:
> Hi Al!
> 
> 
>>And you would prefer to rely on the compiler vendors skills than your
>>own? personally I have more trust in what I create than how others might
>>  choose to interpret it.
> 
> 
> No, not at all.  If I'd rely on them I'd not post on this board.
:-)
> Actually half the time writing code is spent having an eye on the
> compiler's output.
> But I never claimed writing C to be fast.

I noticed, unusually so, this is often one of the claims made for using 
it over asm.

> 
>>Seemingly making it hard for you to relate the concept to the practical
>>implementation?
>>[...]
>>Well of course, that is the intention. I WANT to get what I wrote, that
>>way I know it will function correctly.
>>
>>>[optimizer transforms programs]
>>
>>This is not a great achievement, it is a diabolical disaster. Why do I
>>want it to give me b if I wrote a. Had I wanted b I would have written
>>it in the first place.
> 
> 
> YESSS!    That exactly is my point.
> I'm human.  I think human.
> The MSP is a machine!

And the compiler writers are human, (well some of them are ;@} ) and 
therefore equally prone to error. The MSP doesn't think, only the 
programmer does. The MSP is created by humans, and therefore, one would 
think, constructed in a manner simply understood by humans, such that 
its operational processes may become clear and obvious with a little 
study. A car is not human, but it is a simple task to learn to control 
one. (However, just like in programming, there are many who believe they 
are in control of the car, when they are clearly driving beyond their 
abilities ;@} ) You seem to have adopted the rather odd position of 
wanting to be chauffeur driven, ie relying upon soeone else to provide 
the necessary control.


> 
> Why the heck should I have to adapt to an entirely different world?
> Of course I can do, but this is just an extra risk of making errors
> or at least to be inefficient.

Of course it isn't a different world, the micro is simply a human 
construct, designed by human minds, to simplify human bound tasks. At 
the end of the day it "knows" only two things, on and off, thus anyone

who can differentiate these two things can become a master of the machine.

> 
> I'm German.  I've learnt English.

I'm English, I lived in Germany, and found that my skill at speaking 
German increased alongside my consumption of alcohol, unlike my 
programming, which suffers as my alcohol intake increases. Thus 
comparing the two 'languages' is invalid ?

> But if wanted to write a great poem I'd never
dare to try this in
> English.  I'd do it in my mother-tongue and rely on an expert to
> translate it.

But this is the exact point, no matter how great the outside expert the 
poem simply wouldn't translate, and be as great. Poetry derives its 
essence from many things, including rhyme, or a set cadence, or a set 
pattern, it rarely, if ever translates across language barriers. For 
example the poem

The boy stood on the burning deck
Playing with fire crackers
One flew up his trouser leg
and blew off both his knackers

Simple ceases to rhyme in German, and thus loses its point.

> 
> I've heard of people having invented something called
> "object oriented programming" for exactly this reason:
> A human describes a problem and it's solution in a human way
> from a human perspective.  Afterwards a proven and optimized
> machine transforms this description to something a machine can
> work with.

Objected oriented programming is about as far from this description as 
you can get. It takes something as elegant as the human thought process 
and churns it into an elephant. (an elephant being a mouse designed by a 
committee)

> 
>>>I have many KiloBytes of C-source-code and get 800 bytes after
>>>compilation.
>>>If I had written the same API, HAL and so on in assembler, the
program
>>>would be at least 2000 bytes.
> 
> 
>>Please don't be offended, but this is probably more a personal
thing
>>than a technical issue, some people cannot think in asm, even if they
>>can write it, to write good asm I believe you need to not only think in
>>it, but to think in terms of the physical hardware function as well, ie
>>what else is happening, what side effects might be useful to me, how can
>>I use that to my advantage. I like hardware, I don't want to
abstract
>>myself from it.
> 
> 
> I could think in asm, and I absolutely have to at least when I design
> the HAL.
> But in all layers above that I don't want to care at all, if this
> algorithm is run on an MSP, a PC, my coffee-machine or fed into "The
> Matrix".
> ;-)  BTW:  Why would the machines have had to build The Matrix?
> They could have fed the humans in their breeding tanks with opcodes
> as well?  But for some reason this seems not to have worked.  :-)
> 
> 
> If I reduce the problem to just two layers.
> One is the HAL. The other is my application-layer which shall
> know nothing of any hardware.   Writing in C I would put them into
> two different files.
> I can do so in asm as well.  But is this really a good idea.
> 
> Al, please have a look at my posting to Wolfgang.
> Imagine main() in one file,  IsVoltageAboveTheshold() and Signal() in
> a different file.
> How do you want to achieve such an architecture with pure asm code?
> How would such asm-code react on changes?
> 

I wouldn't. By the time I sit and write ANY code I have already 
determined the relevant parameters of my design. There is nothing 
abstract, or unknown, or to be discovered. I find this approach a little 
like stepping off a cliff and hoping to hell that my arms flap fast 
enough. If you simply wanted to implement the logic of this without 
commiting speciifc resources that is an easy enough thing to do, but I 
simply never approach this phase of a design with any abstraction in 
mind. This has all been filtered out at the designstage, which is 
largely cerebral, but which also contains notes on any critical factors, 
such as timing, or signal levels.

> 
>>>The compiler then shrinks all this to pure spaghetti-code with only
>>>one single CALL statement left (where it really is more effective to
>>>leave the CALL).
> 
> 
>>And you enjoy debugging this?
> 
> 
> OK!   That's a drawback.
> Debugging actually is a pain in the ass.  Simply because the
> compiler's output has nothing to do with it's input any more.

Not at all. The "no notes, top down, figure it out as I go along" 
approach will inherently lead to difficult to debug code, since nothing 
has been pre-planned, including the most crucial part of the system 
functional verification, or spec compliance. How can this be planned for 
when the program itself has not been designed, simply brewed up from a 
hodge podge of vague notions.

Effective debugging requires effective design and pre-planning. It is 
nothing to do with the compiles output. Pre-designing for test can be 
done in any language. This usually results in pain free debugging, and 
design verification.

> 
> On the other hand, I can switch of optimization and use a larger
> flash during development.  This again leads to the old problem,
> that the debug-build works fine and the final release-build is
> buggy.
> 
> 
> Regards,
> Dirk
> 
> PS:  Two things to add:
> 
> You're right in one point.  If the compiler is poor all I've
written
> is useless.  Fortunately there ARE good compilers.
> 
> I believe our main difference in this discussion is that you think in
> registers and bits and aim to a concrete realization of a program.
> I think more of an abstract description of what the system shall do,
> without caring where what signal is going to be connected.

I believe that we have intrinsically different design philosophies. I 
think about as abstractly as it gets but ultimately thought without 
purpose is wasted thought. The very early stages of solving a problem 
may be abstract, but defining the solution can never be.

Cheers

Al


Reply by Wolfgang Reich May 30, 20042004-05-30
Ok, you asked for it ;-)

> inline int IsVoltageAboveTheshold(void)
> {
>     CACTL = SOME_PATTERN;   // set up the comparator
>     _NOP();                 // wait for settling
>     return (!(CACTL & CAOUT));
> }

#define IsVoltageAboveTheshold() ( \
     CACTL = SOME_PATTERN, \
     _NOP(), \
     !(CACTL & CAOUT))

BTW: are you sure that one _NOP() is enough for comparator settling?


> inline int Signal(int state)
> {
>     if ( state == -1 )
>        P1OUT &= ~ BIT2;
>        
>     if ( state == 1 )
>        P1OUT |= BIT2;
>        
>     return ( P1OUT & BIT2 );
> }

#define Signal(state) ((state==-1 ? P1OUT &= ~BIT2 : (state==1 ? 
P1OUT |= BIT2 : P1OUT)) & BIT2)

I don't claim that this is readable - not at all. I'd rather say
it's 
terrible. But I like it.

> void main(void)
> {
>     if ( IsVoltageAboveTheshold() )
>       Signal( 1 );
> }

<snip>

> --------------------------------
> I'm looking forward to any suggestions how to "improve" the
inlined
> functions above.

Don't know if it's an improvement. It's different.

> Do NOT change main().
> --------------------------------

I didn't :-)

Wolfgang



Reply by Dirk Reymann May 30, 20042004-05-30
Hi Al!

> And you would prefer to rely on the compiler
vendors skills than your
> own? personally I have more trust in what I create than how others might
>   choose to interpret it.

No, not at all.  If I'd rely on them I'd not post on this board. :-)
Actually half the time writing code is spent having an eye on the
compiler's output.
But I never claimed writing C to be fast.


>> Then comes the compiler, or better to say, the
optimizer in place.
>> It recognizes, that most of these constructs are very ineffective from
>> the machines point of view.  So it throws all my layers and functions
>> away  and leaves only the necessary code.

> Seemingly making it hard for you to relate the
concept to the practical
> implementation?
> [...]
> Well of course, that is the intention. I WANT to get what I wrote, that
> way I know it will function correctly.
>> [optimizer transforms programs]
> This is not a great achievement, it is a diabolical disaster. Why do I
> want it to give me b if I wrote a. Had I wanted b I would have written
> it in the first place.

YESSS!    That exactly is my point.
I'm human.  I think human.
The MSP is a machine!

Why the heck should I have to adapt to an entirely different world?
Of course I can do, but this is just an extra risk of making errors
or at least to be inefficient.

I'm German.  I've learnt English.
But if wanted to write a great poem I'd never dare to try this in
English.  I'd do it in my mother-tongue and rely on an expert to
translate it.

I've heard of people having invented something called
"object oriented programming" for exactly this reason:
A human describes a problem and it's solution in a human way
from a human perspective.  Afterwards a proven and optimized
machine transforms this description to something a machine can
work with.

>> I have many KiloBytes of C-source-code and get
800 bytes after
>> compilation.
>> If I had written the same API, HAL and so on in assembler, the program
>> would be at least 2000 bytes.

> Please don't be offended, but this is
probably more a personal thing
> than a technical issue, some people cannot think in asm, even if they
> can write it, to write good asm I believe you need to not only think in
> it, but to think in terms of the physical hardware function as well, ie
> what else is happening, what side effects might be useful to me, how can
> I use that to my advantage. I like hardware, I don't want to abstract
> myself from it.

I could think in asm, and I absolutely have to at least when I design
the HAL.
But in all layers above that I don't want to care at all, if this
algorithm is run on an MSP, a PC, my coffee-machine or fed into "The
Matrix".
;-)  BTW:  Why would the machines have had to build The Matrix?
They could have fed the humans in their breeding tanks with opcodes
as well?  But for some reason this seems not to have worked.  :-)


If I reduce the problem to just two layers.
One is the HAL. The other is my application-layer which shall
know nothing of any hardware.   Writing in C I would put them into
two different files.
I can do so in asm as well.  But is this really a good idea.

Al, please have a look at my posting to Wolfgang.
Imagine main() in one file,  IsVoltageAboveTheshold() and Signal() in
a different file.
How do you want to achieve such an architecture with pure asm code?
How would such asm-code react on changes?

>> The compiler then shrinks all this to pure
spaghetti-code with only
>> one single CALL statement left (where it really is more effective to
>> leave the CALL).

> And you enjoy debugging this?

OK!   That's a drawback.
Debugging actually is a pain in the ass.  Simply because the
compiler's output has nothing to do with it's input any more.

On the other hand, I can switch of optimization and use a larger
flash during development.  This again leads to the old problem,
that the debug-build works fine and the final release-build is
buggy.


Regards,
Dirk

PS:  Two things to add:

You're right in one point.  If the compiler is poor all I've written
is useless.  Fortunately there ARE good compilers.

I believe our main difference in this discussion is that you think in
registers and bits and aim to a concrete realization of a program.
I think more of an abstract description of what the system shall do,
without caring where what signal is going to be connected.


Reply by onestone May 30, 20042004-05-30
Dirk Reymann wrote:
> Hi Al!
> 
> [Al wrote:]
> 
>>Having read this rather lengthy post the only comment I have is that it
>>reinforces my personal beliefe that C is no faster than asm. You state
>>that you went through several optimisation cycles with C, then tried
>>Quadravox, and again jumped throughb hops trying to optimise it.
> 
> 
>>Your reason that C is 'a must' is given as the need to
implement an OS,
>>HAL and API. Sorry, these are just fancy acronyms for stuff that we do
>>all the time, nothing hard about creating these in ANY language. The
>>time you wasted optimising your C source would have taken far longer
>>than writing the original in asm.
>>[...]
>>Of course I'm well known as a neanderthal.
> 
> 
> :-)
> Of course, I already noticed, that you are one of the assembler-guys.

Not strictly true, I've written code in juts about every HLL going, any 
many long since gone. I use C predominantly on Pc's, but just do less PC 
based work these days. I have yet, after well over 30 years, to find a 
good reason to use C on small (sub 64k) embedded systems. I have done so 
in the past, but found the gains to be far outweighed by the negatives.

> 
> Furthermore, you are absolutely right.  Generally, C is slower (writing and
> executing) than asm, as well as C++ is slower than C.
> 
> One of the reasons is that the higher evolved language (if you
> *really* utilize the additional features) requires writing much more
> text to achieve the same result.  I think, C++ is the best example:
> You can produce KB's of source-code without generating a single
> opcode.
> 
> The very good reason for this is, that you give a lot more information
> about what you are going to achieve to the compiler, so it can check
> by itself if you did it correctly.

And you would prefer to rely on the compiler vendors skills than your 
own? personally I have more trust in what I create than how others might 
  choose to interpret it.

> E.g. variable types (unsigned int, const int,
etc.)  are entirely
> superfluous, if you just want to get your program up and running
> quickly.  But it is an enourmous help to ensure that you did not make
> any errors in your concept.
> (BTW:  In my opinion EVERY type-case in your program is an indicator
> that your concept is inconsistent!)

And I consider them an extremely powerful tool. I regularly utilise a 16 
bit value, then treat it a byte at a time. I ahve several algorithms I 
use which rely on this, and which, without this simple artefact would 
take longer to process than I can afford. This isn't inconsistency, it 
is simply recognising at design time that there is a very valuable short 
cut to be gained by NOT using rigid type casting (a thing I truly 
detest). I have a very compute intensive application, for example that 
uses only integer logic, but the format of the calculations differs 
regularly, for example I might use 1:15 format in one place , pull a 
result in 3:29 format, then grab a slice from that which is effectively 
a different format. Why, well, instant scaled calculation, filters in a 
single clock, etc etc.

> 
> 
> It's the same with my OS, HAL and API.  These are just constructs to
> partition my thoughts.   I write the C code exactly this way, i.e. in
> a way that directly represents my abstract view of the system.

I partition my thoughts somewhat differently, I simply use separate 
modules for each code'entity'. Everything to do with LCD graphics sits

in GRAPHICS.s43, whereas the low level handling of the LCD panel sits in 
LCD.s43. Crude, simple, and extremely effective for many years. I now 
pull LCD.s43 from project XYZ-1997, and bolt it into project 123-2004, 
make the slight changes needed to handle a colour panel instead of a 
black and white panel, and I have 80% pre-tested code ready to roll. it 
now becomes CLCD.s43. next I took Graphics.s43 and created CGraphics.s43 
(took under an hour to modify both, and worked beautifully first shot)

Each module is VERY tight, adequately commented, easily modified, easily 
re-used, and very simple to understand. My view of the system is not 
abstract, it has solidity from the moment I commit to coding it, yet all 
the flexibility necessary.

> 
> Then comes the compiler, or better to say, the optimizer in place.
> It recognizes, that most of these constructs are very ineffective from
> the machines point of view.  So it throws all my layers and functions
> away  and leaves only the necessary code.

Seemingly making it hard for you to relate the concept to the practical 
implementation?

> 
> My C program has 3 or 4 independent layer, handles massages between
> tasks, an includes lots and lots of function calls.

So it is simply a typical program. Depending on what you call a layer. 
The modern misuse differs considerably from what I would consider a 
software 'layer' to be.

> This way of writing it makes the program obvious
and portable.

Portability is not a property of C. There are always differences between 
compilers and versions of compilers that need to be taken into account. 
Portability is a myth, I can port code from a HC11 to an MSP430 faster 
than you could study the differences between compiler A and compiler B, 
and perform on the fly optimisation.

> 
> The compiler then shrinks all this to pure spaghetti-code with only
> one single CALL statement left (where it really is more effective to
> leave the CALL).

And you enjoy debugging this?

> 
> 
> Now, again, I've written lots of text.  Maybe I'd better come to
the
> point:
> 
> You can can write every program in two ways:

You can write ANY program in a thousand ways ate least.


> a) highly abstract code, which is inefficient, but
flexible.

or a highly abstract code which is neither of the above

> b) spaghetti-code, which is very lean, short and
fast.  Maybe you can
> still read it, but it is never flexible!

Why not? And you omit non-spaghetti hand crafted assembler that is clear 
and clean to read. I would like to believe, and there are lots of posted 
examples for you to look at, that my assembler is no where near as 
obfuse as typical C. Heavily optimised code may not be obvious at a 
casual glance, but that's what comments are for.

> 
> The you can use either asm or a high level language.

Of course there are a million opinions about this, non of which is 
correct. The real answer is use what you are comfortable with, that does 
the job. For me that is assembler 99% of the time.

> 
> Asm might be faster to finish the program, but you always get exactly
> the program you wrote.  

Well of course, that is the intention. I WANT to get what I wrote, that 
way I know it will function correctly.

You write b), you get b) ... you write a) you
> get a).
> 
> The great achievement of C is, that it can transform and a) program
> to a b) program.

This is not a great achievement, it is a diabolical disaster. Why do I 
want it to give me b if I wrote a. Had I wanted b I would have written 
it in the first place.

> 
> 
> I have many KiloBytes of C-source-code and get 800 bytes after
> compilation.
> 
> If I had written the same API, HAL and so on in assembler, the program
> would be at least 2000 bytes.

Please don't be offended, but this is probably more a personal thing 
than a technical issue, some people cannot think in asm, even if they 
can write it, to write good asm I believe you need to not only think in 
it, but to think in terms of the physical hardware function as well, ie 
what else is happening, what side effects might be useful to me, how can 
I use that to my advantage. I like hardware, I don't want to abstract 
myself from it.

practically speaking I have never had to port one of my own designs to a 
differnet micro , and I know  for a fact that systems I designed over 20 
years ago are still in every day commercial use, and that designs from 
the pre single chip micro days, ie wholly logic based computer designs 
are still in use moe than 30 years after I designed them. Portability is 
NOT an issue for me, efficient functionality is.

> 
> If had written the spaghetti code in assembler i would probably only
> have 700 bytes.  But I would neither have a HAL, nor an OS, or
> anything else.

Why not, and why do you believe it would be spaghetti code? I manage to 
write efficient tight highly modular code, as do many others. I don't 
eat pasta.

> None of my colleagues would be able to read the
program and if I
> tried to port it to another architecture or if I tried to get one
> the the core algorithms out of it, I would have to start all over
> again.

I mostly post code samples here to beginners. All in asm. So far nobody 
has complained that they are illegible, or couldn't be understood. I 
hope that isn't simply because they are afraid I might over react. 
certainly the same would appear to be true for the other guys here who 
regularly post code. Even I can read their C (though I hate the 
bastardisation used to make C embedded friendly) and the Op's appear to 
be able to read their asm posts as well. It doesn't seem to me to be a 
problem.

> 
> 
> 'Hope I could make myself clear this time.
> 'But always open for discussions.

The main game is to enjoy what you do. As long as it's fun you'll 
usually do it well. Once it becomes drudgery your results will reflect 
that. I take what I do very seriously, and I do some serious stuff, but 
I still refer to my office as the toy room, and new projects as my 
latest toys, no matter how serious they might be.

Cheers

Al


Reply by Dirk Reymann May 30, 20042004-05-30
Hi Wolfgang!

> I also used the Quadravox compiler, but found the
code generated
> quite good. And if it wasn't, Preston "the AQ430 C compiler 
> guy" usually was very fast in improving the code generator.
> Did you use a recent version of AQ430?

Don't know, how recent it was.  I just downloaded the eval-version
4 days ago.
Oh, by the way... Preston, if you read this:
Starting the IDE and then loading the project is no problem.
But starting the IDE by double-clicking the project file and then
compiling lets the compiler freeze.  Might be a bug?

> I generally don't rely on compiler
optimization - perhaps because I 
> grew up with non-optimizing compilers.
> I almost never use inlining, but preprocessor macros instead.
> For dead-code-elimination, I use conditional compilation - or just 
> don't write dead code.

> You didn't post your inlined function,
perhaps it looks like this:
> int P10_Low(void) { return (P1IN & 0x01) == 0x00;}
> or
> int P10_Low(void) { return (P1IN & 0x01) ? FALSE : TRUE;}

> You may want to try
> #define P10_Low() (!(P1IN & 0x01))
> I did't test it, but I'm pretty sure the generated code the code
will
> be better. And it's just as readable and portable as the inlined 
> version.


Sorry Wolfgang,  this is *exactly* what I was trying to avoid when I
chose C for my project.
Maybe you read my recent mail to Al.  The ONLY reason (for me) to use
the compiler is that it does optimization.  The approach you described
basically means:
Use the language C, but write the program in assembler style.
If you do this, you combine the disadvantages of both languages.  In
that case Al would be absolutely right.  Assembler is faster, leaner
and as easily to read as your C-code.

On the other hand you are right.  Many of my inlined functions look as
you guessed.  And yes, I also replaced some of them with macros as
you suggested.  In fact, using the macro saves 2 bytes with IAR and
about 12 Bytes (estim.) with Quadravox.


But as I wrote earlier, I'm mostly using C because I want to design my
code in a highly abstract way and then let the compiler do the
shrinking.


Example:

inline int IsVoltageAboveTheshold(void)
{
    CACTL = SOME_PATTERN;   // set up the comparator
    _NOP();                 // wait for settling
    return (!(CACTL & CAOUT));
}


inline int Signal(int state)
{
    if ( state == -1 )
       P1OUT &= ~ BIT2;
       
    if ( state == 1 )
       P1OUT |= BIT2;
       
    return ( P1OUT & BIT2 );
}

void main(void)
{
    if ( IsVoltageAboveTheshold() )
      Signal( 1 );
}


The main function is written first.
At this point I don't care about hardware or bits or registers at all.
It is high level.  All I want to "say" is: If my voltage is above a
threshold, some signal shall be HI.

Maybe there are other places in the program where I set this Signal
and others where I want to get the state.  Therefore
int Signal(int state);       would be a clear and lean interface.

What this signal actually is and how it is accessed, is defined later
in a different layer in a different module/file.  Maybe I also later
decide, that I do something with the PWM-generator to realize my
signal.

So you see:  main() is high-level,  Signal() and
IsVoltageAboveTheshold() are low-level with a very clean interface in
between.

And, lucky me, the IAR-compiler makes extremely good code out of this.
unfortunately Quadravox doesn't.

But to be honest, since I was very satisfied with IAR's code output
I didn't think much about "tricks" to shrink this.

--------------------------------
I'm looking forward to any suggestions how to "improve" the
inlined
functions above.
Do NOT change main().
--------------------------------


Regards,
Dirk




PS.:
Just for those, who are interested in what the compilers make out of
this program:

IAR...
main()
{
    CACTL = SOME_PATTERN;
    _NOP();
    if ( !(CACTL & CAOUT) )
        P1OUT |= BIT2;
)


Quadravox...
main()
{
    CACTL = SOME_PATTERN;
    _NOP();
    int x1= !(CACTL & CAOUT) ;
    if ( x1 )
    {
        int x2 = 1;
        if ( x2 == -1 )
           P1OUT &= ~ BIT2;
       
        if ( x2 == 1 )
            P1OUT |=    BIT2;

        int x3 = P1OUT & BIT2;
    }
}