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

Out of ROM error, please help in condensing code

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



Joined: 08 Jul 2005
Posts: 91

View user's profile Send private message

Out of ROM error, please help in condensing code
PostPosted: Thu Apr 13, 2006 3:27 pm     Reply with quote

Hi all,

When compiling my code with the 16F87, I get the infamous error: "Out of ROM, A segment or the program is too large". I know the atan2 function eats up a lot of this, but I kinda need it. Can anyone see any other ways that I can condense my code or eliminate variables to free up some space? Just a note: I originally implemented a circular buffer in the INT_RDA interrupt, but eradicated it to free up more space. What I have there now works (I tested it without the code in main), but I can't compile the darn thing because of the aforementioned error. I appreciate any help as always.

Thanks in advance,
weg

Code:

#include <16F87.H>
#include <rdaDefine.c>
#include <stdlib.h>
#include <math.h>

#define LED PIN_A2

#fuses HS,NOWDT,NOPROTECT,PUT,NOLVP
#use delay(clock=10000000)

// global variables
int rud_pwm=128, reset=0;
long pulseLength=0;
int i=0, j=0, k=0, commas=0;
char tr1[6], LAT[10], LONGI[11];

// Timer interrupt to generate PWM signals
#INT_TIMER0
void pwm_signal()
{
   reset=1;

   set_timer0(37); // 61 for 20 msec

   output_high(PIN_B6); // generates initial high time ie 1 msec
   delay_us(1000);
   i=0;
   for(i=0;i<rud_pwm;i++) // generates remaining high time
   {
      //use this to tune duty cycle
      delay_us(1);
   }
   output_low(PIN_B6);
}

// hardware interrupt to detect manual override
#int_ccp1
void isr()
{
   reset=0;
   set_timer1(0);
   while(input(PIN_B0));

   // if SW interrupt triggers during HW interrupt, prevent
   if(reset==0) pulseLength = get_timer1();
   else
   {
      pulseLength = pulseLength;
      reset=0;
   }
}

#int_rda
void rda_isr(void)
{
   char c;

   c = my_getc();
   c = (char)c;

   if(c=='$') {j=1; commas=0;}
   if(c=='G' && j==1) j=2;
   if(c=='P' && j==2) j=3;
   if(c=='R' && j==3) j=4;
   if(c=='M' && j==4) j=5;
   if(c=='C' && j==5) j=6;
   
   if(c==',' && j==6) commas++;

   if(commas==3) // get latitude data (3)
   {
        if(c==',') k=0; // do nothing
        else {LAT[k]=c; k++;}
   }

   if(commas==5) // get longtitude data (5)
   {
        if(c==',') k=0; // do nothing
        else {LONGI[k]=c; k++;}
   }

    if(commas==10) // get true heading (8)
   {
        if(c==',') k=0; // do nothing
        else {tr1[k]=c; k++;}
   }

}

void main()
{

   char degreesLat[2], degreesLong[3];
   float diff_Lat=0.0, diff_Long=0.0;
    float currentLat=0.0, currentLong=0.0;
   float currentWayptLat=0.0, currentWayptLong=0.0;
   float waypointHeading=0.0;
   long trueHeading=0;
   
   init_uart();

   output_high(LED); delay_ms(1500);
   output_low(LED); delay_ms(1500);
   
   // setup interrupts
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_ccp1(CCP_CAPTURE_RE); // on rising edge
    setup_timer_1(T1_INTERNAL);

   // enable interrupts
     enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_CCP1);
     enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   while(1)
   {

      if(pulseLength>3750)
      {
         disable_interrupts(INT_RDA);
         disable_interrupts(INT_TIMER0);
         output_low(LED);
      }


      else
      {
                                                enable_interrupts(INT_TIMER0);
         enable_interrupts(INT_CCP1);
                                                enable_interrupts(INT_RDA);
         enable_interrupts(GLOBAL);

         // true heading
         trueHeading = atol(tr1);

         // calculate heading to waypoint
                                                currentWayptLat = 39.983680;
                                                currentWayptLong = 75.015951;

         degreesLat[0] = LAT[0];
            degreesLat[1] = LAT[1];
            currentLat = atof(degreesLat) + ((atof(LAT)) - (atof(degreesLat)*100.0))/60.0;

            degreesLong[0] = LONGI[0];
            degreesLong[1] = LONGI[1];
            degreesLong[2] = LONGI[2];
            currentLong = atof(degreesLong) + ((atof(LONGI)) - (atof(degreesLong)*100.0))/60.0;

         // pythagorean theorem - works for short distances...not enough RAM to factor in Earth's curvature
         diff_Lat = currentWayptLat - currentLat;
            diff_Long = currentWayptLong - currentLong;
            waypointHeading = atan2(diff_Long,diff_Lat);
            if(sin(currentWayptLong - currentLong)>0.0)
                waypointHeading = waypointHeading*180.0/Pi;
            else
                waypointHeading = 360.0 + waypointHeading*180.0/Pi;

         
            if(waypointHeading<trueHeading)
            rud_pwm = 90;
         else
            rud_pwm = 140;
      }
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 13, 2006 4:08 pm     Reply with quote

Convert your program so it will compile for a 16F877. This PIC has 8K
of ROM and your file will compile with no errors. Then look at the .LST
file and see how far you're going over the 4K limit for the 16F87.
It looks to me like it's about 0x30 words over.

Then closely examine the .LST file and try find areas of code that
look like they're wasting a lot of ROM space for no real reason.
Try to re-write the source in those areas. Maybe you can get
the total size down to less than 4K. Then try it in the 16F87 again.

One problem with doing this is that you have no room for added
features or changes in the future. You will have to go through
this process every time you do anything to the program.
weg22



Joined: 08 Jul 2005
Posts: 91

View user's profile Send private message

PostPosted: Thu Apr 13, 2006 7:07 pm     Reply with quote

PCM,

Yeah, I had a feeling you would say that :-( Luckily, I have an F877 laying around that I will switch to tomorrow. One question:

How do I change that "workaround" code you wrote for me in order to make it work with the F877? The F87 Tx and Rx pins are B5 and B2 respectively while the F877 Tx and Rx pins are C6 and C7 respectively.

Thanks again,
weg
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Apr 13, 2006 7:14 pm     Reply with quote

He didn't say that you actually have to use the F877, just compile with it so that you can look at the lst file in order to make some changes.
weg22



Joined: 08 Jul 2005
Posts: 91

View user's profile Send private message

PostPosted: Thu Apr 13, 2006 7:17 pm     Reply with quote

PCM programmer wrote:

One problem with doing this is that you have no room for added
features or changes in the future. You will have to go through
this process every time you do anything to the program.


Yeah I know, but I want to be able to add code in the future without the headaches. BTW, it used 4870 ROM!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 13, 2006 7:32 pm     Reply with quote

Quote:

How do I change that "workaround" code you wrote for me in order to
make it work with the F877? The F87 Tx and Rx pins are B5 and B2
respectively while the F877 Tx and Rx pins are C6 and C7 respectively.


1. Delete the three functions that you added:

init_uart()
my_getc()
my_putc()

Basically, delete everything that you entered from my post:
http://www.ccsinfo.com/forum/viewtopic.php?t=26631&start=8


2. In your program, delete the call to init_uart(). Then do a search
and replace for "my_getc" and replace all instances with "getc".
Do the same thing for "my_putc" and replace it with "putc".


3. Change the initial part of your program so it uses the 16F877
and the hardware UART:
Code:
#include <16F877.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=10000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
weg22



Joined: 08 Jul 2005
Posts: 91

View user's profile Send private message

PostPosted: Fri Apr 14, 2006 5:58 am     Reply with quote

Oh, I thought that workaround code was a way of getting past the early version of software I am using. But apparently, it was just my F87 that was causing the problem? I will be testing it soon...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 14, 2006 9:28 am     Reply with quote

The problem with your compiler version is that the #use rs232 library
code doesn't work correctly with the 16F87 (and likely the 16F88).
You have a fairly normal type of CCS bug. A PIC which was probably
newly added doesn't have all of its peripherals working correctly.
Almost all other supported PICs will work OK with your version, at least
with respect to the serial port.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Fri Apr 14, 2006 10:57 am     Reply with quote

Quote:

One problem with doing this is that you have no room for added
features or changes in the future. You will have to go through
this process every time you do anything to the program.


That's the point.
This it is a very important aspect that nobody must misestimate at designing stage.


Having in consideration that the code you posted is not complete, I used it for compilation
purpose but with the F877, the compilation result shows 4107 words of ROM used.
In short words, there is no room in the F87 for such code.
You also must consider that compilers, -for code relocations - before making
use of the available memory, analyze available memory space in the same block,
not available memory space in the whole memory.
Only the function atan2 takes around 400 bytes and while the compiler doesn't
find an available memory block of that size will give you the infamous
OUT of ROM error.


Humberto
arunb



Joined: 08 Sep 2003
Posts: 492
Location: India

View user's profile Send private message Send e-mail

RE:
PostPosted: Sat Apr 15, 2006 9:31 am     Reply with quote

Hi,

MCU: 16F877
Compiler: PCM 3.1619

I find that at 65% ROM space the compiler generates the Out of ROM error, after this its very difficult to increase space by even a few percent.

Do you think I should change the micro-controller.

thanks
arunb
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Sun Apr 16, 2006 8:35 am     Reply with quote

Most likely your problem has to do with the page size of the program space. You will find one of your functions is larger than a page size or your have several functions that are quite large and cannot not fit into the space left in a page. The solution is to breakup these large fuctions. Any functions that you call only once, try adding #separate before the declaration of the function

Code:

#separate
void somefuction(void);


#separate
void somefuction(void)
{
}
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