CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

CCS Function to asm optimization

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
x34678



Joined: 18 May 2012
Posts: 6
Location: Argentina

View user's profile Send private message

CCS Function to asm optimization
PostPosted: Fri May 18, 2012 10:51 am     Reply with quote

Hi All,
i'm developing in C for my actual project and ROM space is critical because the program which I'm programming is really big.

So, here is the fact:
PIC: 16F887A
CCS Version: 4.120
Xtal: 4Mhz

My Problem: When I compile my code, there are some functions (from my C code) which appear more than once in assembly code. Is that correct?
I think, if I would program in assembly I would put my "function" just only 1 time and I would "call" this function whenever I would need it.

I try to use #org but I get the "out of range" error...

So... a part of the whole Code:
Code:

void rom2lcd(int16 rom_location)
{
   char u,x;
   /* wr lcd buffer with byte, with bytes stored in flash */
   /* copy each byte to lcd_putchar() */
   u RESET;
   do
   {
      /* first byte */
      x = read_flash(rom_location + u,0);
      if (x)
      {
         lcd_putc(x);
         /* second byte */
         x = read_flash(rom_location + u,1);
         if (x)
         {
            lcd_putc(x);
         }
      }
      u++;
   }
   while (x != 0x00);
}

//READ BYTE FROM FLASH
char read_flash(int16 y, char x)
{
   char u;
   /* read byte 0x100 */
   eeadrh = y >> 8; /* high byte */
   eeadr = y & 0x00FF; /* low byte */
   eecon1.eepgd SET ; /* point to flash */
   eecon1.rd SET; /* start read operation */
   delay_us(3); /* required delay(two nops) */
   /* high or low byte */
   if (x == 0)
   {
      /* high byte */
      u = eedath << 1; /* get first 6 bits */
      u &= 0x7F; /* clear bit7 */
      /* get bit0 */
      if ((eedat & 0x80) == 0x80)
         u |= 0x01;
      else
         u &= 0xFE;
   }
   else
   {
      /* low byte */
      u = eedat & 0x7F;
   }
   return(u);
}

And the Assembly code done by CCS:
Code:

here appears my funtion more than once!!...
  2683   0A7A    01D2 rom2lcd      CLRF 0x52                             
  2684   0A7B    0852               MOVF 0x52, W                           
  2685   0A7C    0750               ADDWF 0x50, W                         
  2686   0A7D    00D4               MOVWF 0x54                             
  2687   0A7E    0851               MOVF 0x51, W                           
  2688   0A7F    00D5               MOVWF 0x55                             
  2689   0A80    1803               BTFSC STATUS, 0                       
  2690   0A81    0AD5               INCF 0x55, F                           
  2691   0A82    0855               MOVF 0x55, W                           
  2692   0A83    00D7               MOVWF 0x57                             
  2693   0A84    0854               MOVF 0x54, W                           
  2694   0A85    00D6               MOVWF 0x56                             
  2695   0A86    01D8               CLRF 0x58                             
  2696   0A87    0857 read_flash    MOVF 0x57, W                           
  2697   0A88    1703               BSF STATUS, 0x6                       
  2698   0A89    008F               MOVWF TMR1H                           
  2699   0A8A    1303               BCF STATUS, 0x6                       
  2700   0A8B    0856               MOVF 0x56, W                           
  2701   0A8C    1703               BSF STATUS, 0x6                       
  2702   0A8D    008D               MOVWF PIR2                             
  2703   0A8E    1683               BSF STATUS, 0x5                       
  2704   0A8F    178C               BSF PIR1, 0x7                         
  2705   0A90    140C               BSF PIR1, 0                           
  2706   0A91    2A92               GOTO 0x292                             
  2707   0A92    0000               NOP 
...
2835   0B12    01D2 rom2lcd       CLRF 0x52                             
  2836   0B13    0852               MOVF 0x52, W                           
  2837   0B14    0750               ADDWF 0x50, W                         
  2838   0B15    00D4               MOVWF 0x54                             
  2839   0B16    0851               MOVF 0x51, W                           
  2840   0B17    00D5               MOVWF 0x55                             
  2841   0B18    1803               BTFSC STATUS, 0                       
  2842   0B19    0AD5               INCF 0x55, F                           
  2843   0B1A    0855               MOVF 0x55, W                           
  2844   0B1B    00D7               MOVWF 0x57                             
  2845   0B1C    0854               MOVF 0x54, W                           
  2846   0B1D    00D6               MOVWF 0x56                             
  2847   0B1E    01D8               CLRF 0x58                             
  2848   0B1F    0857 read_flash    MOVF 0x57, W                           
  2849   0B20    1703               BSF STATUS, 0x6                       
  2850   0B21    008F               MOVWF TMR1H                           
  2851   0B22    1303               BCF STATUS, 0x6                       
  2852   0B23    0856               MOVF 0x56, W                           
  2853   0B24    1703               BSF STATUS, 0x6                       
  2854   0B25    008D               MOVWF PIR2                             
  2855   0B26    1683               BSF STATUS, 0x5                       
  2856   0B27    178C               BSF PIR1, 0x7                         
  2857   0B28    140C               BSF PIR1, 0                           
  2858   0B29    2B2A               GOTO 0x32a                             
  2859   0B2A    0000               NOP                                                   

And this means, of course, spend of ROM...
Question: What am I doing wrong?
How could I put my function only one time in asm code and call it whenever I need it?

Thanks!
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Fri May 18, 2012 11:40 am     Reply with quote

It's automatically "inlining" your function. To get around this you can do a couple of things. I think #separate prevents inlining...but it may also have some other side effects that I cannot bring to mind at this point.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 18, 2012 12:41 pm     Reply with quote

Quote:
PIC: 16F887A

There is no PIC with this part number.

Quote:

When I compile my code, there are some functions (from my C code)
which appear more than once in assembly code.

Edit your posted code and make it into a test program that we can
compile. Add the #include, #fuses, #use delay(), #include for the
lcd driver (but don't post the actual driver). Also add definitions for
lines like this:
Code:

u RESET;

Add the declarations for these symbols, etc.:
Code:

eeadrh = y >> 8; /* high byte */
eeadr = y & 0x00FF; /* low byte */
eecon1.eepgd SET ; /* point to flash */
eecon1.rd SET;


In other words, make it into a complete, compilable test program.
Test it to make sure it compiles before you post it.
Also, ideally, convert all the traditional C comments ( /* ... */ ) into
modern line comments: //
dyeatman



Joined: 06 Sep 2003
Posts: 1937
Location: Norman, OK

View user's profile Send private message

PostPosted: Fri May 18, 2012 4:06 pm     Reply with quote

My question is why go to all the hassle? You have to deal with paging and
other such issues.

For a $5 PIC 18F with more memory you can save dozens, if not hundreds
of hours of development/debugging time... it must be a school assignment.
_________________
Google and Forum Search are some of your best tools!!!!
x34678



Joined: 18 May 2012
Posts: 6
Location: Argentina

View user's profile Send private message

PostPosted: Sat May 19, 2012 1:22 am     Reply with quote

dyeatman wrote:
My question is why go to all the hassle? You have to deal with paging and
other such issues.

For a $5 PIC 18F with more memory you can save dozens, if not hundreds
of hours of development/debugging time... it must be a school assignment.



Thanks for the tip, but please don't forget that a PIC 18F is more expensive where i live :(

And YES... you have to deal with this paging issues because in another way you may not compile the whole program (out of ROM, blah blah)
x34678



Joined: 18 May 2012
Posts: 6
Location: Argentina

View user's profile Send private message

PostPosted: Sat May 19, 2012 1:30 am     Reply with quote

PCM programmer wrote:
Quote:
PIC: 16F887A

There is no PIC with this part number.

Quote:

When I compile my code, there are some functions (from my C code)
which appear more than once in assembly code.

Edit your posted code and make it into a test program that we can
compile. Add the #include, #fuses, #use delay(), #include for the
lcd driver (but don't post the actual driver). Also add definitions for
lines like this:
Code:

u RESET;

Add the declarations for these symbols, etc.:
Code:

eeadrh = y >> 8; /* high byte */
eeadr = y & 0x00FF; /* low byte */
eecon1.eepgd SET ; /* point to flash */
eecon1.rd SET;


In other words, make it into a complete, compilable test program.
Test it to make sure it compiles before you post it.
Also, ideally, convert all the traditional C comments ( /* ... */ ) into
modern line comments: //


Thanks for your tips (in special comment tips), but the whole program has more than 2400 lines and it is separated in several files. What I have posted is only a sample, I have more C functions that I got several times in the final asm code.

My POINT here is NOT to compile the mentioned code, but the question why should appear one C function more than once in the final assembly code. I have the feeling that CCS doesn't optimize enough.
x34678



Joined: 18 May 2012
Posts: 6
Location: Argentina

View user's profile Send private message

conclusion
PostPosted: Sat May 19, 2012 1:38 am     Reply with quote

I found some solutions optimizing memory organization (and distribution into the pages) by dividing some functions in subfunctions (but the stack is almost to the limit -> 7 worst case).

My conclusion is: If the time calculation or the ROM space is critical, then you have 2 options:

1. your pocket (PIC 18F)

2. Assembly code (my option).

Thanks all anyway. Exclamation
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat May 19, 2012 1:59 am     Reply with quote

You have already found out, that call stack limitation is the reason behind automatic function inlining. Apperently, this isn't a case of unsufficient optimization rather than caused by your application layout, that doesn't take account for the limited PIC16 resources.

Assembly coding as such can't be expected to solve the problem. Nevertheless, you'll most likely find other places where it can help to save rom space.

Code:
Edit your posted code and make it into a test program that we can
compile.
The suggestion was to make a small test program that reproduces the issue (unintentional "inlining"/duplication of functions), not to post your full application. Doing so usually helps yourself to understand the problem. In this case, it won't be necessary, because you identified the underlying problem.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat May 19, 2012 2:35 am     Reply with quote

Jeremiah is right, #separate does prevent inlining.

The CCS manual explains, at length, to pros and cons of #inline against #separate.

Having been advised, and before abandoning 'C', did you try #separate?

Mike
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat May 19, 2012 3:39 pm     Reply with quote

x34678 wrote:
dyeatman wrote:
My question is why go to all the hassle? You have to deal with paging and
other such issues.

For a $5 PIC 18F with more memory you can save dozens, if not hundreds
of hours of development/debugging time... it must be a school assignment.



Thanks for the tip, but please don't forget that a PIC 18F is more expensive where i live :(
Going to use assembly is a nightmare, not just now, but also for future maintenance.
That's why I want to remark on the above suggestion to use another processor. You didn't correct which PIC you are using, the 16F887A doesn't exist. With the 'A' in the number I assume you meant the 16F877A, an old chip and not recommended for new designs, about $5 each. Now Microchip is a bit strange in that they are selling the newer more advanced chips cheaper than the old models. So, for example you can buy a new chip with more memory for less money. Without more details about your circuit it is difficult to give good advice, but the PIC16F877A costs about $5,00 for a 40 pin PDIP. The PIC16F1519 has double the amount of Flash (28 kb), 3 times the RAM (1024 bytes) and doubled stack levels (16), costing $2.10 for a 40 pin PDIP in 1-25 quantities.
Do you really need the EEPROM feature, then a PIC16F1939 for $2.41 could fit the job.

If even remotely possible I would strongly recommend to upgrade to a PIC with more memory.
x34678



Joined: 18 May 2012
Posts: 6
Location: Argentina

View user's profile Send private message

PostPosted: Sat May 19, 2012 11:43 pm     Reply with quote

Mike Walne wrote:
Jeremiah is right, #separate does prevent inlining.

The CCS manual explains, at length, to pros and cons of #inline against #separate.

Having been advised, and before abandoning 'C', did you try #separate?

Mike


Hi Mike, thanks... Yes, I tried with #separate #inline #org... .... and... it was not easy to use them...
Some times it worked, sometimes it didn't.
x34678



Joined: 18 May 2012
Posts: 6
Location: Argentina

View user's profile Send private message

PostPosted: Sat May 19, 2012 11:46 pm     Reply with quote

ckielstra wrote:
x34678 wrote:
dyeatman wrote:
My question is why go to all the hassle? You have to deal with paging and
other such issues.

For a $5 PIC 18F with more memory you can save dozens, if not hundreds
of hours of development/debugging time... it must be a school assignment.



Thanks for the tip, but please don't forget that a PIC 18F is more expensive where i live :(
Going to use assembly is a nightmare, not just now, but also for future maintenance.
That's why I want to remark on the above suggestion to use another processor. You didn't correct which PIC you are using, the 16F887A doesn't exist. With the 'A' in the number I assume you meant the 16F877A, an old chip and not recommended for new designs, about $5 each. Now Microchip is a bit strange in that they are selling the newer more advanced chips cheaper than the old models. So, for example you can buy a new chip with more memory for less money. Without more details about your circuit it is difficult to give good advice, but the PIC16F877A costs about $5,00 for a 40 pin PDIP. The PIC16F1519 has double the amount of Flash (28 kb), 3 times the RAM (1024 bytes) and doubled stack levels (16), costing $2.10 for a 40 pin PDIP in 1-25 quantities.
Do you really need the EEPROM feature, then a PIC16F1939 for $2.41 could fit the job.

If even remotely possible I would strongly recommend to upgrade to a PIC with more memory.


Sorry, I meant pic16F887 (sorry for the A). Thanks! but the chip was not an option in this project :(
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sun May 20, 2012 3:28 am     Reply with quote

Quote:

My POINT here is NOT to compile the mentioned code, but the question why should appear one C function more than once in the final assembly code. I have the feeling that CCS doesn't optimize enough.


Back in the olden days of Z80 assembler I had a choice. Optimise for SPEED with inline code & lookup tables, or ROM SPACE with tight loops, deeply nested functions & and on the fly calculations.

The fundamentals haven't changed, whether your working in assmbler or higher level language.

The POINT is, YOU now tell the compiler WHICH route to take.

Mike
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun May 20, 2012 6:53 am     Reply with quote

Mike Walne wrote:
The POINT is, YOU now tell the compiler WHICH route to take.
You are right for most modern compilers; you can specify you want to optimize for speed or size. In the CCS compiler I don't know how to do this. There is the #OPT specifier, but nowhere have I ever seen an explanation for the difference between levels 0-9.

Back to the OT:
As you have already found out the most likely cause for the functions being duplicated has to do with the limited stack levels on your PIC16F887.
What you can do to improve this is to squeeze multiple functions into one larger function using the #inline option. Note that this is opposite to using #seperate for preventing the 'Out of ROM' compiler error. This will require some tweaking to find the optimum balance between stack level usage and spreading of functions aver memory banks.
As a guide you can have a look at the compiler generated tree file (*.tre, command line option +T). Here you can see at a glance which functions use the deepest call stack, so where optimization will work best.
Note that interrupts take up stack levels as well (see the top of the list file for a specification).
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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