|
|
View previous topic :: View next topic |
Author |
Message |
rmozer
Joined: 06 Jun 2005 Posts: 17
|
Vastly different compile times with one line of code? |
Posted: Tue Dec 18, 2012 3:19 pm |
|
|
I'm using PCH V4.124 and a PIC18F6722 target. The code is massive with some 40,547 lines of code using 93% of ROM.
As any complex project there are many calls to various subroutines. In this case I called "SendCustomerData" and pass it an int as a parameter. I make calls to this sub in several places in the program and the compiler generates code such as:
.................... SendCustomerData(master);
19F98: MOVFF B9A,C15
19F9C: CALL FDF6
So the issue comes about when I called the subroutine in a different part of the program. It generated the code:
.................... SendCustomerData(master);
12CBA: MOVFF C14,C15
12CBE: CALL FDF6
12CC2: MOVLB C
All is well in the world but the compile and link time without the last invocation was only 9 seconds. When I added the last single line of code to invoke the subroutine one more time, it goes to 63 seconds ?
It works but wow, that slows down future development. Any ideas what might be going on? I haven't seen any compiler updates that are related to the PIC18F6722 but it that would fix it then I am all over it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue Dec 18, 2012 4:09 pm |
|
|
What is happening, is that the compiler is having to 'juggle' things much more to fit the small amount extra. There is probably just enough gap in several banks, with the one line smaller code that is doing the calling, but with the slight increase, lots of things are having to be moved to make it fit. Hence big jump in time. Probably splitting the routine that makes the call, would help.
Best Wishes |
|
|
rmozer
Joined: 06 Jun 2005 Posts: 17
|
|
Posted: Wed Dec 19, 2012 8:07 am |
|
|
Ttelmah,
Very interesting and maybe this old dog can still learn something. Please bear with me as I really want to understand this.
The optimization of the CCS PCH compiler is truly interesting. Just a small change anywhere will cause the compiler to move code around in ROM.
The calling routine that contains the invocation of my SendCustomerData occupied program ROM from 0x12A08 to 0x12C62 (0x238 or 568 bytes) - 63 seconds to compile and link.
Without the invocation of the subroutine the calling routine occupies 0x07EDC to 0x08102 (0x226 or 550 bytes) - 9 seconds to compile and link.
As a test, I pruned down my calling routine and left the invocation of SendCustomerData in the code. Program ROM then used 0x0FDD2 to 0X0FFB2 (only 0x1E0 or 480 bytes). It still took 63 seconds to compile and link although the code is considerably smaller than when no invocation of SendCustomerData was made.
Could this possibly have something to do with the calling stack and the way that PCH does it's best to emulate the stack. The compiler reports in the lst file that the stack is 21 worst case (18 in main + 3 for interrupts).
I had a directive #BUILD(stack=710) in my startup module but I don't remember why I put it there nor do I see where that is even a good memory segment to specify. It had no noticeable affect when removed.
Since a PIC has no stack to push variables onto, this must be handled by the compiler. How would one know they are blowing up the stack? Execution just goes haywire? |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Dec 19, 2012 9:27 am |
|
|
Have you tried putting the target routine:
SendCustomerData(master);
as EARLY in your code file as possible?
I find that my best compile times are achieved if I
place frequently called routines as far up front as possible in the
program file AND consolidate all my global VAR defines up front - as well.
Nested calls to the same routine could be a problem stack wise too. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Wed Dec 19, 2012 10:24 am |
|
|
First the stack. Don't get confused here. The PIC24, has a 'proper' stack, used for variables, as well as function calls. As such, it _will_ overflow, if you leave it set at the default size, and use things like float printf calls. The listing file, only tells you about call usage (which was vital on the older PIC's with a fixed size stack), but does not tell you how much the stack is being used by variables. 710, is an 'odd' number. Typically people normally use binary sizes like 512 bytes (which is large enough for 99% of programs). STACK, _is_ the segment. The stack always goes at the top of RAM, and defaults to 256 bytes, though (strangely), some people get stack overflow crashes, that are fixed by specifying #BUILD(stack=256), suggesting that some compiler versions may default to less than this.... The stack is fairly complex, since there is a small part of it 'hardwired' to a set of fixed working registers, and then the software stack, when this reaches it's end.
On these chips, they will (by default) develop an error trap if the stack overflows. For these chips, there is therefore a 'STACK' command.
Your STACK= command doesn't do anything, since the 18F6722, does not have such a software stack. This is why this option is not in the PCH manual.... You've pulled something from a thread on one of the later PIC's, and added it to your code without understanding that it does nothing....
There is a fuse setting to enable a reset on stack overflow/underflow. STRVEN.
Now the compiler will try to limit physical calls if it can. If you call a function just once, it won't separate it, but will build it 'inline'. This will still happen, with a function called several times, if it is small. You can control this using #inline, and #separate. In some cases it may be necessary to do this yourself.
There are also hidden things. If (for instance) you have ICD enabled, quite a slice at the top of memory is used, and usually at least one stack level. The compiler doesn't directly 'know' this....
Now, on the older PIC16's, memory was page orientated. On the PIC18, it is much closer to a linear address space. However you still have the concept of things being 'local', or 'distant'. You can call a routine that is within 1K instruction, using a single instruction, while anything further, requires a 2 word call. Hence it behoves you to orient programs so subroutines are stores close-by. Data tables stored in ROM (every string you declare, every constant variable etc.), need to be word aligned. As such therefore things have to be 'juggled' to try to optimise how things are placed.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|