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 support@ccsinfo.com

Error 71 ... Out of ROM, A segment or the program is too lar
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

Error 71 ... Out of ROM, A segment or the program is too lar
PostPosted: Wed Jul 13, 2016 4:34 am     Reply with quote

Hi guys

I have to make some little changes in a program I wrote one year ago.
At this date I compiled with Ccsc.exe V 4.3.0.357 (30/11/2012) PCW V4.119 (PCH V4.140) and it worked
I still have a workstation with this configuration, and it still works on it ...

As world has turned since this date I now compile with Ccsc.exe V5.0.0.463 (28/06/2016) PCW 5.061 (PCH V5.061) on another workstation and ...

I get the error 71 :

Quote:
Executing: "C:\Program Files (x86)\PICC\Ccsc.exe" +FH "cms.c" +DF +LN +T +A +M +Z +Y=9 +EA
>>> Warning 216 "cms.c" Line 1121(1,2): Interrupts disabled during call to prevent re-entrancy: (LED)
>>> Warning 216 "cms.c" Line 1121(1,2): Interrupts disabled during call to prevent re-entrancy: (I2C_Transmit)
>>> Warning 202 "cms.c" Line 458(5,6): Variable never used: i
*** Error 71 "cms.c" Line 1121(1,2): Out of ROM, A segment or the program is too large LitRegistre
Seg 00188-00FFE, 006E left, need 0016A
Seg 00000-00002, 0000 left, need 0016A Reserved
Seg 00004-00006, 0004 left, need 0016A
Seg 00008-00186, 0000 left, need 0016A Reserved

1 Errors, 3 Warnings.
Build Failed.
Skipping link step. Not all sources built successfully.
BUILD FAILED: Wed Jul 13 11:46:11 2016


As you imagine, it is very irritating, especially when the planning is short

Does anybody had this issue and have an idea to solve as I do not believe I have a lack of memory. maybe a configuration somewhere is not correct

Thanks for your help
temtronic



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

View user's profile Send private message

PostPosted: Wed Jul 13, 2016 5:07 am     Reply with quote

The PIC you're using has 'banks' of program memory and requires that functions and main() be located wholely within a single bank. IE: a function can't cross or be in 2 banks. Say the banks are 10KB in size and you have 2 functions of 4KB each. 2 of them fit into a bank fine(2 X4=8) with some space left over but 3 will NOT fit(3 x 4=12), the 3rd function would have to overlap or cross or occupy 2 banks and that's NOT allowed.
One possible way to fix this is to rearrange the order of your functions and main() so that the compiler might get better use of the banks.
If that doesn't work, options include using a PIC with more memory or re-coding to maximize space. Since this is an existing project, hopefully you can re-code or rearrange existing code to get it to work.

Jay
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Wed Jul 13, 2016 7:38 am     Reply with quote

Thanks for your quick answer temtronic

I think I understand what you write, but ...
In this case, the same PIC18F2220 compiled on the old workstation works, and on the new one does not !!!
It is the same panel that I move from one to the other, I hope the banks have not changed during the transfer.

If I increase memory (I put a PIC18F2520 = 16384 bytes iso 4096 bytes) I obtain exactly the same : it works on the old compiler and not on the new one.

I find it curious, not you ?
gaugeguy



Joined: 05 Apr 2011
Posts: 290

View user's profile Send private message

PostPosted: Wed Jul 13, 2016 7:57 am     Reply with quote

With the newer version there have been udpates and fixes causing the assembly code size to increase just enough to not fit within the banking limitiations.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Wed Jul 13, 2016 8:39 am     Reply with quote

gaugeguy wrote:
With the newer version there have been udpates and fixes causing the assembly code size to increase just enough to not fit within the banking limitiations.


Aïe Aïe Aïe

Do you mean the code can increase from 4K to 16K ?
jeremiah



Joined: 20 Jul 2010
Posts: 1320

View user's profile Send private message

PostPosted: Wed Jul 13, 2016 9:06 am     Reply with quote

No, he is talking about the code can increase past the bank size. IIRC that's around 256 bytes per bank? not 100% sure but your data sheet should say.

You need to get your function size down I think. Maybe break it up into smaller functions?

EDIT:
see https://www.ccsinfo.com/forum/viewtopic.php?t=40257&highlight=bank+functions
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 13, 2016 10:42 am     Reply with quote

Are you using a bootloader with #org statements ? Did those #org
statements come from a CCS example file available for vs. 4.119 ?
They might not work with the larger code size in the modern compiler.

Post your #org statements.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Mon Jul 18, 2016 1:44 am     Reply with quote

The function which seems too large for it is the following (it is the one the error 71 mentions)

In my mind, it is not very long, and not so easy to split off
Why the V5.061 makes code larger than V4.119 ? Have they communicate on that ?

Code:
/**************************************************************************
Renvoie la valeur d'un registre
**************************************************************************/

Int LitRegistre(Int Numero)
{
int I_Valeur=0x00;

   switch(Numero)                            // numero du registre à lire
     {
    case 0x00:                              // Adresse Module
       I_Valeur=I_Adresse_JX;
       break;
     
     case 0x01:                                 // numéro de série L
        I_Valeur=I_NumeroSerieL;   
        break;
        
     case 0x02:                                 // numéro de série H
        I_Valeur=I_NumeroSerieH;
        break;
     
     case 0x03:                                 // Version minor
         I_Valeur=VERSION_MINOR;
         break;
   
   case 0x04:                                 // Version Major
         I_Valeur=VERSION_MAJOR;
         break;

   case 0x05:                                 // Lamp alarm delay
        I_Valeur=I_Delai_Lampe_Alarme_Max;
         break;
   
   case 0x06:                                 // Global alarm delay
        I_Valeur=I_Delai_Alarme_Max;
         break;
   
   case 0x07:                                 // 14ms
         I_Valeur=I_Duree_14_Mesuree;            // Attention L_period a changé peut-être
         break;
      
   case 0x08:                                 // durée trou de faulty lamp
         if(SFLS.Alarm) I_Valeur=(int)(L_TrouMesure); else I_Valeur=0x00;
         break;
    
    case 0x09:                                 // durée trou de faulty lamp
         if(SFLS.Alarm) I_Valeur=(int)(L_TrouMesure>>8); else I_Valeur=0x00;
         break;
        
     case 0x0A:                                 // off, LI MI ou HI
        if (SFLS.MA)
           {
            if(SFLS.HI)
               {
                  I_Valeur=0x03;
               }
               else if (SFLS.MI)
               {
                  I_Valeur=0x02;
            }
               else
               {
                  I_Valeur=0x01;
            }       
           }
        else I_Valeur=0x00;

      if(B_NoSignal) I_Valeur+=0x04;
      if(SFLS.Local) I_Valeur+=0x08;
         if(SFLS.Alarm) I_Valeur+=0x10;
        break;
    
    case 0x0B:
       if(I_No_15ms>=CYCLE_15) I_Valeur=0x01; else I_Valeur=0x00;
       if(I_No_5ms>=CYCLE_40) I_Valeur+=0x02;
       break;
       
   default:
      if (Numero<0x10)                  // Unsused
      {
         I_Valeur=UART_Trace_Adress[Numero-0x0C];
      }   
      else if(Numero<0x31)               // chaque lampe               
      {
         int k=Numero-0x10;

         if (k>=SFLS.length)
         {
            I_Valeur=0x00;                              // pas de lampe
         }   
         else if (SFLS.defaut[k]>=I_Delai_Lampe_Alarme_Max)
         {
            I_Valeur=SFLS.defaut[k];                  // Panne lampe
         }
         else I_Valeur=0x01;                           // OK   
      }
      break;
   }
   return(I_Valeur);
}   
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Mon Jul 18, 2016 2:09 am     Reply with quote

And if I clearly empty this function (mark inside as /* ... */) another one appears :

Code:
*** Error 71 "cms.c" Line 1119(1,2): Out of ROM, A segment or the program is too large    bputc
  Seg 00188-00FFE, 005E left, need 00064
  Seg 00000-00002, 0000 left, need 00064 Reserved
  Seg 00004-00006, 0004 left, need 00064
  Seg 00008-00186, 0000 left, need 00064 Reserved


Does that mean it does not find place to put 64 bytes ?

Where do I find the length of segment for my PIC18F2220 or PIC18F2520 ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19267

View user's profile Send private message

PostPosted: Mon Jul 18, 2016 2:13 am     Reply with quote

You are fractionally missing the point here.

It's a 'blocks into hole' puzzle. The compiler tells you which one it can't fit, but the problem is almost certainly caused by one of the ones it has already put into the space. Imagine you have two boxes to fit on a shelf. Shelf is 1m long, and one box is 800mm long, and the other 250mm long. You put the 800mm box on the shelf, and then find the 250mm one won't fit. However the real problem is the 800mm one....

You can almost certainly get V5 to actually fit the code, if it did go in with V4, by compiling with the option (near the top of your source file):

#OPT compress

However this is fractionally dangerous. The reason V5 code is at times slightly larger, is that CCS have added more internal error checking to a lot of the functions. The compress option turns some of this off, and is less well tested code.

The real problem is that somewhere you have two of more large pieces of code, that are 'monolithic', and these are tending to block other items from fitting. It's down to programming 'style'. Keeping function sizes slightly smaller, allows much easier packing by the code.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Mon Jul 18, 2016 2:43 am     Reply with quote

Ttelmah wrote:


You can almost certainly get V5 to actually fit the code, if it did go in with V4, by compiling with the option (near the top of your source file):

#OPT compress



OK thanks Ttelmah
I put #OPT compress and I get another function !!!
Where can I find the block length ? as I can look at function size with V4 and react on code on the good ones on V5, no ?
temtronic



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

View user's profile Send private message

PostPosted: Mon Jul 18, 2016 7:53 pm     Reply with quote

OK, going back to your original post, if v4.xyz worked WHY bother upgrading to v5.abc ? Obviously v4 was suitable for your PIC, perhaps you can explain why you upgraded?

I don't know how the 'optimize' feature may work but I do know that if YOU reorganize the functions, it might actually compile. I've seen it in the past where functions A,B,C would not compile but 'cut and paste' as A,C,B and it compiled just fine.

If you look at the disassembled listing ,you'll see the start and ending addresses for each function.Simply use a 'hex' calculator to subtract start from end and you'll know the size of the function. There's probably a magic bullet to choose this in MPLAB but I'm old school, like to dump listings and see what's going on...

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19267

View user's profile Send private message

PostPosted: Tue Jul 19, 2016 12:31 am     Reply with quote

Lets make some further comments.

It is important to understand what is actually involved here. The PIC program memory, is not one large 'lump' of memory, it is instead for certain things treated like a book with pages. Your code is also in sections. A subroutine is a 'section' (effectively a paragraphs). Now a single part of a program (routine), can only work inside one page. (So in publishing terms, 'widow' lines must not exist).
So you have loads of 'paragraphs' and 'pages', and the compiler then tries to fit combinations of the latter in the former. The more the code is split up, the better the packing it can do. If you have no paragraph that is over half a page long, and most are much smaller, the compiler can look through all the different size pieces you have, and fit things in.

However we then come to V5, versus V4. There are two differences here. The first is that V5, in some places does try to generate 'safer' code, and this can cost a little on size. However the changes for this are small. The other though is that by default, V5, is optimised for speed, rather than for code size. As such, it will 'inline' more code by default.

What does 'inline' mean?.

A subroutine, can be generated in two ways. One is 'inline', and the other 'separate'. With the 'inline' version, the whole of a routine, is included 'inside' the calling code. With the 'separate' version, instead the routine is placed elsewhere, and called. The downside of the former, is that it prevents splitting up across pages, and can result in bulkier code. It's plus, is that it is faster, and involves less actual data movements. The _default_ action with V5, is to put routines which are small, and not called from many locations 'inline'.

So, when laying out code, think what routines do not matter if it takes a tiny bit longer to call, and mark these yourself, as #separate. Try to avoid large routines. If you have something doing a series of different sequences of operations, then consider whether each of these sequences could instead be moved to separate routines. A search here will find notes about how to do this, from literally hundreds of threads. It is a fundamental part of writing code for the PIC (particularly the older PIC's).
For comparison, the page size on most PIC16's, is 2K words. So a PIC with 16K of ROM (8K words), will have this split into four pieces. However on a PIC18, the memory is generally no longer paged (there are paging limitations that appear over 64K).

However I must also go back to PCM_programmer's question about whether you are using a bootloader?. The error being reported, appears to show the compiler behaving as if it is being excluded from some areas of the memory. Also there is a 'nasty', in trying to use I2C, both inside and outside an interrupt.....
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Tue Jul 19, 2016 2:41 am     Reply with quote

temtronic wrote:
OK, going back to your original post, if v4.xyz worked WHY bother upgrading to v5.abc ? Obviously v4 was suitable for your PIC, perhaps you can explain why you upgraded?


Really I am a bit lost

last July 13th I compiled without problem on PC nbr1 with V4, I still have the .hex and .lst files
After I needed to move to PC nbr 2, which was not used for programming since a long time, so i upgraded MPLAB and Ccs. To do that I took contact with sales@ccsinfo.com and they sent me the procedure.
V5 has been download and installed

At this moment, my Error 71 appeared. No chance cos of course planning is too short !

So I finally post here and discovered and understood the changes in V5 and this story of paging (in 18F2220.h I read //////// Program memory: 2048x16 Data RAM: 512 Stack: 31, does that mean the pages are 2048x2 long ? If yes, I can be sure my routine are smaller)

As Planning is too short as I wrote, I decide this morning to come back to the PC nbr 1 with V4
And !!!
Error 71
Evil or Very Mad

It worked the 13th and not the 19th ?
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Tue Jul 19, 2016 3:19 am     Reply with quote

Ttelmah wrote:

However I must also go back to PCM_programmer's question about whether you are using a bootloader?. The error being reported, appears to show the compiler behaving as if it is being excluded from some areas of the memory. Also there is a 'nasty', in trying to use I2C, both inside and outside an interrupt.....

No I have no bootloader.
As soon I can compile, I will see and put I2C outside interrupt.
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, 3  Next
Page 1 of 3

 
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