EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Which PIC18 C Compiler?

Started by Talal Itani July 8, 2004
On Mon, 12 Jul 2004 07:57:09 GMT, the renowned wouter@voti.nl (Wouter
van Ooijen (www.voti.nl)) wrote:

>>Yes, I explained that in my post if you'll read it carefully. However, >>in most non-trivial C programs there is some use of function pointers. > >In a 1k-code microcontroller application you will be happy to >sacrifice the use of function pointers anb recursion for the benefit >of (much) compacter code.
We are talking about the PIC18 though, which comes with up to 128K bytes of code memory/4K of RAM. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
Eric Smith <eric-no-spam-for-me@brouhaha.com> wrote in message
news:qhy8lrkcgh.fsf@ruckus.brouhaha.com...
> I wrote: > > The compiler doesn't really have enough information to deternine that. > > wouter@voti.nl (Wouter van Ooijen (www.voti.nl)) writes: > > It does, but not when compiling a separate file. Classic C compilers > > Yes, I explained that in my post if you'll read it carefully. However, > in most non-trivial C programs there is some use of function pointers. > If a pointer to a function anywhere but at the leaves of the call graph > is stored, it is unlikely that the compiler can then prove that functions > that are not leaves are not called recursively.
This is nonsense. You cannot conjure the address of a function out of thing air. All functions that are invoked by a pointer to function are easily identified. All function pointers are easily identified. The assignment of a function address to a function pointer is easily identified. All function pointers can be easily tracked at compile time. The only way the compiler would loose track is if the execution path passed through some assembler code or C code for which the source is not available AND the function pointer is passed into that code by reference. There is no way a function address can be computed using a mathematical expression, you have to look them up. Yes I know you can load an object file into a running program, locate functions by name and then execute them via a function pointer BUT this is the same situation I mentioned above where the compiler does not have access to the source and in any case you wouldn't be doing this on a small embedded system. Conclusion: the number of situations where a function cannot be proven to be either reenterant or non-reenterent is increadibly small and would involve increadibly complex function pointer manipulation. Such functions could be treated as reenterant (or flagged by the compiler as being too complex) while all the other functions in the system would be well defined and treated accordingly.
> > I have yet to see any C compilation system for the PIC that does > interprocedural optimization, let alone optimization across multiple > source files, so the ability to provide hints to the compiler as I > suggested would still be useful. Since it's unlikely to be adopted > as part of the C standard, a compiler vendor that wanted to do this > could provide it as an implementation-defined pragma.
This is complete BS. On the one hand you talk about how things are not done and on the other how things could be done. You use the argument that existing compilers don't do blah blah to support your argument for not being able to gather the information required and you use the argument for adding new facilities to show how it can only be done your way. This is gibberish. If you're going to modify a compiler you can make it do what you want. If you're not going to modify it then what does this "hints" thing mean. Do you intend shouting at the compiler to get it to do what you want? Ok, lets say for the sake of argument that you implement this "hints" thing. Are you going to make the compiler varify that the hint is valid or are you going to blindly generate code that will crash because the hint is not valid.?Are you going to analyse the generated code in some way to identify how "hinted" variable RAM will be re-used or are you going to treat them like static varaible are not bother with a static stack? Wouter, Walter and I have all told you that you don't need this "hints" thing, that all the info is there. Go back and think about how you would solve the problems you think you have and then tell us why you think it is impractical (forget impossible). Regards Sergio Masci
>We are talking about the PIC18 though, which comes with up to >128K bytes of code memory/4K of RAM.
I missed that. But not that not all 18F's are that fat. Wouter van Ooijen -- ------------------------------------ http://www.voti.nl PICmicro chips, programmers, consulting
Spehro Pefhany <speffSNIP@interlogDOTyou.knowwhat> wrote in message
news:nes4f05tgg0u9prreeo4qtb5on3okrjm05@4ax.com...
> On Mon, 12 Jul 2004 07:57:09 GMT, the renowned wouter@voti.nl (Wouter > van Ooijen (www.voti.nl)) wrote: > > >>Yes, I explained that in my post if you'll read it carefully. However, > >>in most non-trivial C programs there is some use of function pointers. > > > >In a 1k-code microcontroller application you will be happy to > >sacrifice the use of function pointers anb recursion for the benefit > >of (much) compacter code. > > We are talking about the PIC18 though, which comes with up to > 128K bytes of code memory/4K of RAM. >
Yes but you still would not want to loose the advantage of the extra code space by filling it with inefficient code, or the advantage of a faster processor by giving it unnecessary code to execute. Regards Sergio Masci
In article <8puqcc.hcv.ln@fenelon.com>, pete@fenelon.com says...
> In comp.arch.embedded Michel Catudal <bbcat@netonecom.net> wrote: > > > > The portability is overplayed with small microcontrollers. > > It's not. We have customers in automotive who demand portability, they > want the same platform running on platforms from PIC right up to PowerPC.
I find it VERY unlikely that any of your customers demand that the code be portable between PICs and Power PCs.
> > For people who are building one or two products, yes, portability is not > important. For big customers, it is.
Why? I have found after doing this for over 20 years that in "big" projects COST is the big factor. Not once did anyone ask me to make sure that the code that runs on one of our gaming voucher printers be portable to a Wintel bos, but they sure ask about the price. When you say "big" I take it you mean big numbers of shipped units.
> > > The PIC > > is not made for C language. > > The PIC18 was intended to be C-friendly. Microchip knew they'd screwed > up with the PIC17.
Many of us have sucessfully completed 17 series parts using 'C'. Just as many of us learned to deal with the limitations of the Intel segmented architecture of the X86 we have learned to deal with the oddities of small MCUs.
> > > CCS does a very good job at optimizing > > the code and that it very important when code memory usage is high. > > > > I don't think that the fact that IAR is more ANSI compliant is a > > good justification for the high price. > > I do, and so do large customers.
Once again I find that ridiculous. Jim
On Tue, 13 Jul 2004 15:21:32 GMT, the renowned "Sergio Masci"
<sergio@NO.SPAM.xcprod.com> wrote:

>Yes but you still would not want to loose the advantage of the extra code >space by filling it with inefficient code, or the advantage of a faster >processor by giving it unnecessary code to execute. > >Regards >Sergio Masci
Ideally, I would like to have the choice, not to have a non-standard limitation imposed that breaks existing C code. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
"Sergio Masci" <sergio@NO.SPAM.xcprod.com> writes:
> All functions that are invoked by a pointer to function are easily > identified.
No. All functions that *might* be invoked by a pointer are identifiable. But they are not necessarily identifiable through static analysis of only the file defining those functions (unless the functions are declared static).
> Conclusion: the number of situations where a function cannot be proven to be > either reenterant or non-reenterent is increadibly small and would involve > increadibly complex function pointer manipulation.
No. I've got real-world examples in two IP router code bases I've worked on at past jobs.
> Such functions could be > treated as reenterant (or flagged by the compiler as being too complex)
The whole point of my suggestion was that the programmer may KNOW that a particular function with never be called reentrantly, and could give a hint to the compiler rather than relying on the compiler to possibly figure it out. Of course, if the programmer supplies a hint that is wrong, all bets are off.
> This is complete BS. On the one hand you talk about how things are not done > and on the other how things could be done. You use the argument that > existing compilers don't do blah blah to support your argument for not being > able to gather the information required and you use the argument for adding > new facilities to show how it can only be done your way.
I *never* said it can only be done my way. I provided a reasonable argument for why it might be desirable to do it the way I suggest, though I stated outright that I thought it unlikely that my proposal would be adopted (only because it doesn't benefit mainstream C users). You can rant all day about how my idea is "complete BS", but such ranting is not likely to convince anyone.
> This is gibberish.
Another very insightful and constructive bit of criticism. Truly you have a dizzying intellect. -- The Man in Black, "The Princess Bride", screenplay by William Goldman
> Ok, lets say for the sake of argument that you implement this "hints" thing. > Are you going to make the compiler varify that the hint is valid or are you > going to blindly generate code that will crash because the hint is not > valid.?
Blindly generate code that may produce undesired results. If the programmer tells the compiler that it's allowed to do something, then the compiler is allowed to do it. On two occasions I have been asked [by members of Parliament!], "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question." -- Charles Babbage Of course, if the compiler can prove that the programmer is wrong, it can ignore the hint and/or produce a compile time warning or error. In fact, the compiler can ignore the hint for any reason or none at all. But if the programmer supplies the hint and the compiler chooses to act on it, the programmer is responsible for the consequences.
> Are you going to analyse the generated code in some way to identify > how "hinted" variable RAM will be re-used or are you going to treat them > like static varaible are not bother with a static stack?
The compiler is allowed to use the hint to do any sort of optimization that is guaranteed to still yield the defined C automatic storage class semantics under the restriction that the function is not called reentrantly. The compiler could treat the variable as static, or it could treat it as automatic, or it could do something else we haven't thought of. The C standard doesn't define a specific mechanism by which an implmentation is required to implement the automatic storage class, and similarly there is no reason why it would dictate an implementation mechanism for the proposed hint.
> Wouter, Walter and I have all told you that you don't need this "hints" > thing, that all the info is there.
You have told me it is unnecessary but you have provided no evidence or concrete argument to counter the code example I provided. The most coherent criticism of my proposal that you've managed to produce is the claim that it is "complete BS".
> Go back and think about how you would solve the problems you think you > have and then tell us why you think it is impractical (forget > impossible).
I stated myself that it is impractical because the C committee has no motivation to add a feature that only benefits programmers of very small embedded systems. Other than that, speaking as someone who has actually written small compilers (for special-purpose languages) I am fairly certain that there is no particular reason why the proposal it is impractical from a technical perspective. Eric
Walter Banks <walter@bytecraft.com> writes:
> This is the very reason that we link the intermediate code from the compiler > and don't begin to do code generation until we know the entire structure of > the application. The other similar issue is pointers to functions.
Interesting. I was not aware that any PIC C compiler did that. Given the limited program memory of (most) PICs, this is a reasonable approach.
I have many years experience with AVR and WinAVR (GCC)
 
Recently I have started a new job where only the PIC18 and PIC16 families
are allowed.  I started with Microchip's C18 compiler and got frustrated
with it when I could only have 256 bytes of global variables.  The
compiler would give a message saying something along the lines that I have
run out of RAM.  I guess the PICs have the RAM in banks of 256 bytes, so
you need to manually assign the global variables into different banks.  I
couldn't figure out how to do this, so I bought the CCS compiler hoping
for a better experience.
 
CCS solved the banking issue, but the C18 appears to be more "ANSI C
compliant".  for example:
 
GCC and the C18 will compile this code, but not the CCS
 
union hello {
     struct {
         unsigned char a;
         unsigned char b;
     };
     unsigned char ppp[2];
};

union hello test;


void main(void)
{
 test.a = 5;
 test.ppp[0] = 50;

 /* ------ MAIN CONTROL LOOP ------ */
 for (;;) {


 }
} 
The CCS compiler is saying that " test.a = 5;" is not a valid member :(
 
And I have to use this work around for printing strings in ROM on the CCS
 
void print_string(char rom *pBuf) 
{
 unsigned int16 temp, *data_prog;
 unsigned char a[1];
 
 temp = &pBuf;
 data_prog = temp;
 temp = *data_prog;
 
 a[0] = "a";
 while (a[0]!=0) {
     read_program_memory(temp, a, 1);
     txbyte(a[0]);
     temp++;
 }
}
 
Instead of this:
void print_string(char rom *pBuf) 
{
 unsigned char a[1];
 
 a[0] = "a";
 while (a[0]!=0) {
     read_program_memory(pBuf, a, 1);
     txbyte(a[0]);
    pBuf ++;
 }
}
 
Conclusion, If you have to use PICs and are on a budget, buy HiTec
compiler, otherwise use IAR, otherwise use GCC with a real processor like
and AVR, MSP, or ARM7



On 2007-09-19, drwho <drwho@mailinator.com> wrote:
> Recently I have started a new job where only the PIC18 and PIC16 families > are allowed. I started with Microchip's C18 compiler and got frustrated > with it when I could only have 256 bytes of global variables. The > compiler would give a message saying something along the lines that I have > run out of RAM. I guess the PICs have the RAM in banks of 256 bytes, so > you need to manually assign the global variables into different banks. I > couldn't figure out how to do this
Wouldn't it have been easier to find out how to do it rather than changing compilers? One bank of static storage duration per module is a common limitation on PIC18 compilers.
> CCS solved the banking issue, but the C18 appears to be more "ANSI C > compliant". for example: > > GCC and the C18 will compile this code, but not the CCS > > union hello { > struct { > unsigned char a; > unsigned char b; > }; > unsigned char ppp[2]; > };
That is not "ANSI C compliant" code. That is an extension known as an "anonymous structure."
> Conclusion, If you have to use PICs and are on a budget, buy HiTec > compiler,
I don't think anyone would consider Hi-Tech to be a "budget" solution.
> otherwise use IAR,
My experience evaluating IAR for PIC18 vs. Hi-Tech showed that IAR's much higher price gets you much larger code, which wasn't exactly what I was looking for. -- John W. Temples, III

The 2024 Embedded Online Conference