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, A segment or the program is too large
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

Out of ROM, A segment or the program is too large
PostPosted: Sat Dec 30, 2023 3:33 am     Reply with quote

I am using the PIC18LF46K22 MCU, MPLAB IDE v8.92, and CCS C compiler v5.115.

I am referencing this helpful reply from Ttelmah regarding optimizing code (https://ccsinfo.com/forum/viewtopic.php?t=59937; that post is locked):
Quote:
Very basic things.
For example, if you are doing basically the same job in
two different places, making this into a separate routine, and then calling
this single routine (especially if you declare this as #SEPARATE, to avoid
the compiler by default 'inlining' small routines, will save space.
This is what the COMPRESS will switch. By default, small functions will
not be called as subroutines, instead the compiler will make a separate
copy each time these are called. Now when debugging, you step through
the code and can see that this is inside the main code where it is called.
However with COMPRESS selected the compiler instead makes this a
called subroutine. If you 'break' inside this, you can't tell which of the
calls you actually got there from.

Questions:
1. For the following error message, how can I find out which functions the segments are pointing to?
*** Error 71 "F:\A\_Data1\Programming\SMN-828B_Code_v6.1\main_N828B_v6.1.c" Line 628(1,2): Out of ROM, A segment or the program is too large MAIN
Seg 00194-0FFFE, 04F2 left, need 00786
Seg 00000-00002, 0000 left, need 00786 Reserved
Seg 00004-00006, 0004 left, need 00786
Seg 00008-00192, 0000 left, need 00786 Reserved

I am trying to identify these functions so that I can break them into smaller functions.

2. I am already using the "#opt compress" directive. Does this directive make every function a "#separate" function?
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Sat Dec 30, 2023 3:41 am     Reply with quote

No, opt compress will tend to combine things rather than separate them.
It is trying to make the total code size as small as possible.

However what you show suggests you are actually running out of total
size, not space in one segment. Splitting things up will actually make this
worse rather than better....

Segments as a problem are more a PIC16 problem, rather than PIC18.
If you look your whole available code space is the first segment.

You have simply run out of space. Second part of the message
'or the program is too large'.....
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Dec 30, 2023 6:28 am     Reply with quote

WOW, ran out of ROM in a 46K22 !!!
I'm thinking you have HUGE 'data tables' in your program ??
If so, perhaps you could store that data(say it was a 'font table' ) in an external EEPROM ?

Any 'finished' program shouldn't use more than 90% of ROM, as we all know 'other code' HAS to be added a few days later.....

Just trying to think of options.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Sat Dec 30, 2023 7:20 am     Reply with quote

Thank you, Ttelmah and Temtronic.

My code can now compile, but with 99% ROM usage (I removed a function that is not called):
Memory usage: ROM=99% RAM=61% - 67%

I am still looking into how to reduce the ROM usage.

My code has many fprintf statements that print both text and variables to a software UART (and ultimately to the computer screen, for the user to see). When I commented out one group of fprintf statements in a function, the ROM usage reduced to 95%!

I will now try to shorten the text in all fprintf statements. Most static data and parameters are already stored in the built-in EEPROM. The PCB does not have any external EEPROM.

I will appreciate any other ideas you or any other contributors may have that can reduce ROM usage.
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Dec 30, 2023 8:24 am     Reply with quote

One possible solution...all depends on how the compiler works....

If all the 'fprints to PC screen' changed into calling a common function, that should ( may ?) reduce space.
Say you need to send 1-10 variables to the PC screen, have ONE function that sends ALL of them,even if some are not needed

I'm thinking each current 'printf to PC screen' code would be changed to a short 'call to 'printtoPCscreen' function instead of several lines of code.

Hopefully you can code a test of my idea,see if it does work or not.

Others may reply already knowing if this will work...at least it sounds good in my head.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Sat Dec 30, 2023 12:05 pm     Reply with quote

Several things.

The first is duplication. Any code that could be split off to be a subroutine?.
That includes as Jay says things like printouts etc.. Also things like messages.
If these are used in more than one place, then store as a constant value
instead of having these stored twice.
Then look at things that could be more efficient. So for example, arrays
are less efficient to access than separate variables. Large switch statements
etc. etc..
Jay also alludes to data. Remember if you initialise a variable, this involves
a ROM copy of the values being stored. Could these values come from
somewhere else like an external EEPROM instead?.
Then really if the code is this large, would it be better to look at a DsPIC?.
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Dec 30, 2023 1:45 pm     Reply with quote

re: Then really if the code is this large, would it be better to look at a DsPIC?.

No, he needs a SMALLER PIC !

Being told you have to use a smaller device and you're forced into becoming 'creative' on how to code and use BITS instead of having 'unlimited' WORDS to use.

As Mr. T points out several ways you can reduce ROM requirements.

I was thinking about this the other day while looking at BASIC code I'd cut in 1977. Had to 'pack' data into 256 byte sectors (85 x 3 was efficient ! ). Another chunk of 'fun' code was encoding 24hrs into a byte,well 7 bits. Each bit represented 15 minutes, and the 8th bit was a 'flag'.
Since memory got huge in size and cheap to buy, programmers don't have 'fun' anymore.. doing more with less.
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Sun Dec 31, 2023 10:53 am     Reply with quote

Good point.
It is easy to write code very inefficiently, and modern programming is
more and more going that way. Using smaller variables also saves size
in the routines to handle them. Multiplying or adding two 8bit values
uses perhaps 1/10th the space of doing the same with 16bit values,
Going with float again perhaps 10* more space.
Using a bit of thought and scaling values to fit into integer types save
both ROM and RAM.
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Sun Dec 31, 2023 11:48 am     Reply with quote

kgng97ccs wrote:
My code has many fprintf statements.....


I'll offer this since no one else has yet. I've found that the compiler tends to 'inline' printf/fprintf calls instead of what I assumed was a traditional implementation of a generic function which is subsequently called when invoked.

I ran into a similar issue as you; what I did was break out the printfs based on the number of arguments.

It saved a literal TON of memory.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Mon Jan 01, 2024 3:51 am     Reply with quote

Thank you, everyone, for your ideas.

So far, by shortening the text in fprintf statements by using abbreviations for some words, I have managed to get the ROM usage down to 97% (not much, but at least the full code compiles). I am still looking into other options.

From Newguy:
Quote:
what I did was break out the printfs based on the number of arguments.
Question:
I am not sure what you mean by “break out the printfs based on the number of arguments”. Can you explain more? One or more examples will help. Thank you.
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Mon Jan 01, 2024 11:33 am     Reply with quote

Instead of using (for example)

Code:
printf(bputc, "Test message %u\r\n", count);


Do this instead

Code:
#separate
void my_printf(unsigned char *text, unsigned int8 number) {
   printf(bputc, "%s %u\r\n", text, number);
}


Obviously quite a simplification and generalization, but I hope you get the point. I found that when I looked at the list file, the compiler was generating a completely unique instantiation of each printf I used in code. I then a) refactored my strings to follow the same format, i.e. [TEXT] [ascii number] [carriage return] [line feed], and b) made appropriate calls to my_printf() instead of printf(). The code shrank by a very large amount.

I also broke out different versions of my_printf() depending on how many arguments I'd need.

Clearer?
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Jan 01, 2024 11:38 am     Reply with quote

and remember you must have #device PASS_STRINGS=IN_RAM to use
constant strings passed like this.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Tue Jan 02, 2024 12:39 am     Reply with quote

Thank you, Newguy and Ttelmah. Yes, the example helps.

1. If I am passing a string constant declared in an array, I will not need to use the directive “#device PASS_STRINGS=IN_RAM”. Is this correct?
Example:
Code:
char num_loops[] = “Number of loops: ”;
my_printf(num_loops, number);

2. If I am passing a string constant written in double quotes in the calling statement, I will need to use the directive “#device PASS_STRINGS=IN_RAM”. Is this correct?
Example:
Code:
my_printf(“Number of loops: ", number);

Will this option (passing a string constant in double quotes) use less ROM than option 1 (using a declared string constant)?
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Tue Jan 02, 2024 4:20 am     Reply with quote

Pass strings is useful in a lot of places and costs very little in code size.
Passing as a RAM string will work, but will cost (in this case) 18bytes of RAM.
Add this up for all the strings, and you'll probably run out....
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Wed Jan 03, 2024 5:39 am     Reply with quote

I have managed to get the ROM usage down to 95% (from 100%) by doing the following (I have “opt compress” in my code).
1. Abbreviating some text in fprintf() statements.
2. Consolidating sequential fprinf() statements into one fprintf() statement.
3. Using a wrapper function to wrap the built-in read_eeprom() function and doing the same for the write_eeprom() function. I gathered from the CCS forum that this can help to prevent the compiler from making these built-in functions inline. I placed “#separate” before the function prototype of each of these wrapper functions, but found that it actually does not affect the ROM usage (as shown in the .STA file).

I am still looking into how best to use one or more subroutines to do the fprintf(). This will need more planning, as my fprintf() statements are varied and scattered across many functions.

Ttelmah wrote:
Jay also alludes to data. Remember if you initialise a variable, this involves
a ROM copy of the values being stored. Could these values come from
somewhere else like an external EEPROM instead?.
Then really if the code is this large, would it be better to look at a DsPIC?.

Is it possible to ask the compiler to save constants, including string constants, and initial values of variables in the RAM?

I am asking this because my code has some unused RAM space:
Memory usage: ROM=95% RAM=61% - 67%

It will be great if I can use the RAM to free up some ROM space.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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