View previous topic :: View next topic |
Author |
Message |
weg22
Joined: 08 Jul 2005 Posts: 91
|
Out of ROM error, please help in condensing code |
Posted: Thu Apr 13, 2006 3:27 pm |
|
|
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;
}
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 13, 2006 4:08 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
weg22
Joined: 08 Jul 2005 Posts: 91
|
|
Posted: Thu Apr 13, 2006 7:07 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Apr 13, 2006 7:14 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
weg22
Joined: 08 Jul 2005 Posts: 91
|
|
Posted: Thu Apr 13, 2006 7:17 pm |
|
|
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! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 13, 2006 7:32 pm |
|
|
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) |
|
|
![](templates/subSilver/images/spacer.gif) |
weg22
Joined: 08 Jul 2005 Posts: 91
|
|
Posted: Fri Apr 14, 2006 5:58 am |
|
|
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... |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 14, 2006 9:28 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Fri Apr 14, 2006 10:57 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE: |
Posted: Sat Apr 15, 2006 9:31 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Apr 16, 2006 8:35 am |
|
|
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)
{
} |
|
|
![](templates/subSilver/images/spacer.gif) |
|