View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
out of rom |
Posted: Mon Nov 14, 2005 3:19 pm |
|
|
Using a pic16f877a with PCm 3.225
I can compile my code and the compiler says I'm using 54% ROM. Adding a line of code gives me an
"OUT of ROM, a segment or the program is too large"
error.
I'm assuming it is the segment it is talking about. How do I know how big a "segment" is and how would I fix the error?
the .lst file says largest free fragment = 2048
Is it because a function is too long?
Any thoughts?
Thanks
Ringo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 14, 2005 3:25 pm |
|
|
Quote: |
The compiler says I'm using 54% ROM.
Adding a line of code gives me an "OUT of ROM, a segment or the
program is too large" error. Is it because a function is too long? |
You probably have a function that's larger than 2KB. This can easily
happen if you're using floating point. I suggest that you break up the
function into two or more smaller functions. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Mon Nov 14, 2005 3:35 pm |
|
|
Ok, that seems to work. How can I tell how big a function is though? Is there an easy way?
Thanks
Ringo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 14, 2005 4:33 pm |
|
|
Supposedly the command line compilers will generate a Statistics file
(.STA) if you specify the +A option. I've never been able to make this
work. I think it's really a PCW or PCWH option only.
You can study the .TRE file, but I've never liked that file. It just seems
like a mess.
If anybody has been able to make a .STA file with the command line
compilers, then please post how to do it. |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Mon Nov 14, 2005 5:23 pm |
|
|
This is what I use on pch 3.239 [[ But i have pcwh(the whole shebang)]]
ccsc +FH +T +A +DF +P4 "%f"
%f is repaced with the c file name test.c
top part of *.sta file
Code: |
ROM used: 22104 (67%)
22104 (67%) including unused fragments
4 Average locations per line
12 Average locations per statement
RAM used: 1000 (65%) at main() level
1274 (83%) worst case
|
Is using this in command line mode different then the single command line compiler? |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Tue Nov 15, 2005 3:52 pm |
|
|
PCM programmer wrote: | Quote: |
The compiler says I'm using 54% ROM.
Adding a line of code gives me an "OUT of ROM, a segment or the
program is too large" error. Is it because a function is too long? |
You probably have a function that's larger than 2KB. This can easily
happen if you're using floating point. I suggest that you break up the
function into two or more smaller functions. |
I'm still having issues. I had a pretty long function that parses the stream from the serial port. I have replaced lots of code with functions now but my problem remains the same. Even though I have taken out probably 200 lines of code out of this function if I try to add any code to it then I get the out of Rom error. Before trying to add code I'm at 52% rom used.
Here is the function I'm working on:
void Process_Commands()
{
int dir;
int pinn;
int state;
int channel;
int servo_value;
long int ADC_Return_Value;
int i;
int data1,data2,data3;
int TEMP_STRING[SERIAL_BUFFER_SIZE];
int SRF08_STRING[SERIAL_BUFFER_SIZE];
int BLINK_STRING[SERIAL_BUFFER_SIZE];
int TEMP_STRING3[SERIAL_BUFFER_SIZE];
int TEMP_STRING4[SERIAL_BUFFER_SIZE];
int TEMP_STRING5[SERIAL_BUFFER_SIZE];
Int iresult;
/////////////////////////////////////////////////////////////////////////////////
*TEMP_STRING=STRLWR(SERIAL_BUFFER);
// STRLWR(SERIAL_BUFFER);
// strcpy(SRF08_string,"srf08");
// strcpy(BLINK_string,"blink");
// if(strncmp (temp_string, serial_buffer, 5))
// printf("comparing %s and %s\r\n",temp_string,serial_buffer);
if((SERIAL_BUFFER[0]=='s') &&
(SERIAL_BUFFER[1]=='r') &&
(SERIAL_BUFFER[2]=='f') &&
(SERIAL_BUFFER[3]=='0') &&
(SERIAL_BUFFER[4]=='8'))
{
read_srf08();
}
/*
else if((SERIAL_BUFFER[0]=='c') &&
(SERIAL_BUFFER[1]=='m') &&
(SERIAL_BUFFER[2]=='p') &&
(SERIAL_BUFFER[2]=='s') &&
(SERIAL_BUFFER[3]=='0') &&
(SERIAL_BUFFER[4]=='3'))
{
read_cmps03();
}
*/
else if((SERIAL_BUFFER[0]=='m') && //m or M
(SERIAL_BUFFER[1]=='o') &&//f or O
(SERIAL_BUFFER[2]=='g') && //g or G
(SERIAL_BUFFER[3]=='o') && //o or O
(SERIAL_BUFFER[4]==' ') &&
((SERIAL_BUFFER[5]=='0') ||(SERIAL_BUFFER[5]=='1') || (SERIAL_BUFFER[5]=='2')) &&
(SERIAL_BUFFER[6]==' '))
{
MOGO();
Return;
}
/*
// else if(!strncmp(BLINK_string, serial_buffer, 5))
else if((SERIAL_BUFFER[0]=='b') && //b or B
(SERIAL_BUFFER[1]=='l') &&//l or L
(SERIAL_BUFFER[2]=='i') && //i or I
(SERIAL_BUFFER[3]=='n') && //N or n
(SERIAL_BUFFER[4]=='k')) //K or k
{
printf("\r\n");
for(i=0;i<5;i++)
putc(serial_buffer[i]);
printf("\r\n");
printf("ACK");
BlinkLeds ();
Return;
}
*/
/////////////////////////////////////////////////////////////////////////////////
else if((SERIAL_BUFFER[0]=='g') &&
(SERIAL_BUFFER[1]=='p') &&//P
(SERIAL_BUFFER[2]=='i') && //I
(SERIAL_BUFFER[3]=='o')) //O
{
pinn=SERIAL_BUFFER[5]-0x30;
state=SERIAL_BUFFER[7]-0x30;
if(serial_buffer[6]=='\r')
state=2;
GPIO(pinn,state);
}//end if gpio
else if((SERIAL_BUFFER[0]=='s') &&
(SERIAL_BUFFER[1]=='e') &&
(SERIAL_BUFFER[2]=='n') &&
(SERIAL_BUFFER[3]=='s') &&
(SERIAL_BUFFER[4]=='o') &&
(SERIAL_BUFFER[5]=='r'))
{
channel=SERIAL_BUFFER[7]-0x30;
set_adc_channel( channel );
delay_ms(1);
ADC_Return_Value = Read_ADC();
printf("%ld",ADC_Return_Value);
Return;
}
else if((SERIAL_BUFFER[0]=='s') &&
(SERIAL_BUFFER[1]=='e') &&
(SERIAL_BUFFER[2]=='r') &&
(SERIAL_BUFFER[3]=='v') &&
(SERIAL_BUFFER[4]=='o') &&
(SERIAL_BUFFER[5]==' ') &&
((SERIAL_BUFFER[6]=='0') ||(SERIAL_BUFFER[6]=='1') || (SERIAL_BUFFER[6]=='2')) &&
(SERIAL_BUFFER[7]==' '))
{
set_servo();
}
else
printf("NACK");
Return;
}
If I try to uncomment anything I get the error, even though things like "set_servo()" used to have the code in this function. Moving the code out of the function did not help. Am I missing something here? any ideas?
Thanks
Ringo _________________ Ringo Davis |
|
|
teletype-guy
Joined: 11 Oct 2005 Posts: 8 Location: AZ
|
|
Posted: Tue Nov 15, 2005 4:14 pm |
|
|
Hi Ringo:
When you uncomment lines, you are also adding the library function code (eg: strcmp) unless you have called it elsewhere. So you are adding much more code than just the call-and-pass-params stuff.
You are doing some rather large if comparisons. I parse serial strings a different way: the main loop constantly calls a parse function, which checks for a serial char (if no char avail it just exits, and the main loop continues). If a char is available, I drop into a switch statement based on a variable "rx_state" -- rx_state starts out as "IDLE," and in this switch case I check for the first char of the desired string. If I find the desired char, I update the rx_state (eg: GOT_1ST_CHAR) and exit. The next time through, if another char is available, it drops to the next state case to check for the second desired char. Yada, yada, so on and so forth.
In my code, I'm looking for a specific header string, and then grabbing comma-delimited ascii-encoded-decimal numbers, until I hit a CR or LF to terminate the command -- at this point the rx_state goes back to the IDLE state, waiting for the next command. If any error occurs during command parsing (bogus chars, etc), you can flag the error and return to IDLE state.
It's all pretty fast and compact, and can be extended to multiple strings. Just a thought.
gil |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 15, 2005 4:29 pm |
|
|
You probably could fix the problem by putting #separate on all the
routines that are called by Process_Commands(), but I dislike doing that.
That's because the compiler will no longer automatically limit the stack
usage to the hardware limit of the PIC. For 16F PICs, this is only 8.
You have to check the .LST file, each time after you compile.
Here's another option:
Break up your Process_Commands() function into two pieces.
The first one could be called "Parse_Commands()". It would look
at the incoming command string and decide which one it is, and return
a number indicating which command was received. A 2nd function,
"Do_Command()" would perform the command. Example:
cmd_code = Parse_Commands();
Do_Command(cmd_code);
void Do_Command(int8 cmd)
{
if(cmd == 0) // Null command ?
return;
if(cmd > MAX_CMD_CODE)
return;
switch(cmd)
{
case CMD_RD_SRF:
read_srf08();
break;
case CMD_RD_CMPS03:
read_cmps03();
break;
default:
}
}
I don't guarantee this will fix the problem, but it might work.
Also it's possible that using "if-else if" might work better than
switch-case. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Tue Nov 15, 2005 4:29 pm |
|
|
In my #int_rda function I grab all the bytes until I get a CR, then I call the function I listed before. I was trying to get the strcmp in there to get it working so I could replace all those letter by letter comparisons with 1 strcmp and hope it is smaller that way. I still have several commands I would to add. I guess I could just check the first letter then call another function (based on that letter) to check the rest.
But I guess the question still remains, is there a way to tell how big a function is without adding stuff to it until it will not compile?
Thanks
RIngo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 15, 2005 5:05 pm |
|
|
I just emailed CCS and asked them to enable the Statistics file option
for the command line compilers. If they reply, I'll post the answer to
this thread. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Nov 16, 2005 12:01 am |
|
|
PCM programmer wrote: | You probably could fix the problem by putting #separate on all the
routines that are called by Process_Commands(), but I dislike doing that.
That's because the compiler will no longer automatically limit the stack
usage to the hardware limit of the PIC. For 16F PICs, this is only 8.
You have to check the .LST file, each time after you compile.
|
I really reduced the function to almost nothing:
void Process_Commands()
{
read_cmps03();
GPIO();
MOGO();
set_sensor();
set_servo();
//read_srf08();
Return;
}
but I guess it is still trying to compile everything inline so I still get the out of rom error if I uncomment the last function (or any 1 of the functions).
I was able to get rid of the error by using the #separate in front of some of the functions called above. You said I need to check the .lst file after I compile can you describe what I need to be looking for? I saw in the help file that this could cause stack overflow, but what am I looking for to see if this could happen? I assume that the fewer functions I #separate the better?
Thanks
Ringo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 16, 2005 12:53 am |
|
|
Quote: | You said I need to check the .lst file after I compile.
Can you describe what I need to be looking for ? |
Look at my post at the end of the following thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=20422
In that post, you'll see the top portion of the .LST file for the program.
Notice that the number of stack locations = 9. That's the part
you have to watch. The number of locations used must be no
more than 8 for the 16F-series PICs. If it's greater than 8, you
need to remove the #separate directive from one or more functions
until the problem is corrected.
You should also put a very prominent comment at the start of your
main source file to remind yourself to do this, in case you ever
have to modify the program in the future. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Nov 16, 2005 8:32 am |
|
|
Thank you very much for the help. I'll definitely put the comment you suggested in the code.
Thanks again
Ringo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 17, 2005 3:31 pm |
|
|
Quote: |
I just emailed CCS and asked them to enable the Statistics file option
for the command line compilers. If they reply, I'll post the answer to
this thread. |
CCS says the "+A" option only works if you have PCW (or PCWH).
So, you can't make the statistics file for the command line compilers. |
|
|
|