Linker does not transition from Non Paged to Paged allocations

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Linker does not transition from Non Paged to Paged allocations

Jump to solution
2,592 Views
ebrady
Contributor I

I am compiling ~30K of code using the linker map snippet below.  Whenever I include the line

 

DEFAULT_ROM INTO OS_NONPAGED, OS_PAGED_E0

 

I will consistently see Linker Error L1102: Out of allocation space in segment OS_NONPAGED at address 0x7ee0.    However if I change the DEFAULT_ROM line to read

 

DEFAULT_ROM        INTO  OS_PAGED_E0, OS_NONPAGED;

 

It will link fine, but it will not run due to the Init function being placed in Paged Flash.

 

Can anyone give some input as to what is going on with this?  Thanks

 

-------------------------------------------------------------------------------------------

SEGMENTS
      EE_OS_VERSION = READ_ONLY     0x0FFC TO   0x0FFF;
      RAM           = READ_WRITE    0x2000 TO   0x3FFF;
      OS_NONPAGED   = READ_ONLY     0x4000 TO   0x7EFF;
      BOOT_PUB_FNS  = READ_ONLY     0xEFD0 TO   0xEFFF;
      RAM_F8        = READ_WRITE  0xF81000 TO 0xF81FFF;
      RAM_F9        = READ_WRITE  0xF91000 TO 0xF91FFF;
      RAM_FA        = READ_WRITE  0xFA1000 TO 0xFA1FFF;
      RAM_FB        = READ_WRITE  0xFB1000 TO 0xFB1FFF;
      RAM_FC        = READ_WRITE  0xFC1000 TO 0xFC1FFF;
      RAM_FD        = READ_WRITE  0xFD1000 TO 0xFD1FFB;
      OS_PAGED_E0   = READ_ONLY   0xE08000 TO 0xE0BFFF;
      OS_PAGED_E1   = READ_ONLY   0xE18000 TO 0xE1BFFF;
      BOOT_PARAM    = NO_INIT     0xFD1FFC TO 0xFD1FFF;

END

PLACEMENT
      _PRESTART,              
      STARTUP,                
      ROM_VAR,                
      STRINGS,                
      VIRTUAL_TABLE_SEGMENT,  
      NON_BANKED,             
      INTERRUPT,
      COPY              INTO  OS_NONPAGED;

      
     DEFAULT_ROM        INTO  OS_NONPAGED, OS_PAGED_E0;
      

      BOOT_PUBLIC_FNS   INTO  BOOT_PUB_FNS;

      EE_OS_VERSION     INTO  EE_OS_VERSION;      

      SSTACK,                 
      DEFAULT_RAM             
                        INTO  RAM;

      PAGED_RAM         INTO  RAM_F8, RAM_F9, RAM_FA, RAM_FB, RAM_FC, RAM_FD;

      BOOT_PARAM        INTO  BOOT_PARAM;           

END

Labels (1)
0 Kudos
1 Solution
800 Views
CompilerGuru
NXP Employee
NXP Employee

You should use the

DEFAULT_ROM        INTO  OS_PAGED_E0, OS_NONPAGED;

order.

 

I try to explain the reason why with the other order the linking does fail for certain setups.

The problem is that DEFAULT_ROM fills up OS_NONPAGED and only the last few bytes of that section may be available to subsequently allocate COPY (the COPY section gets allocated last as its content depends on the content of the other READ_WRITE sections).


With the (not recommended) order

DEFAULT_ROM  INTO  OS_NONPAGED, OS_PAGED_E0;

the linker to places all objects (functions) from DEFAULT_ROM into OS_NONPAGED until one function does not completely fit into OS_NONPAGED anymore. When this happens the linker switches the output to the next segment, here OS_PAGED_E0, and starts placing this function and the future objects in this segment. There are usually a few bytes (less than the size of the first function in OS_PAGED_E0) left in OS_NONPAGED. The linking will now only succeed if the COPY section fits into this gap.

The number of the remaining bytes is pretty unpredictability and therefore the linking success or failure can be triggered by a small change in the C code.

 

The correct (and easy) way to fix this issue is to list the section which also gets COPY as the last one for any PLACEMENT is it used. With that setup the linking will only fail if there is really not enough space left.

In general I would recommend to list sections which can be used for different content behind sections which can only take some particular content. This is not only the case for banked vs non banked segments, but to give another example the S08 has zero page memory which can also be used to host non zero page variables, so those zero page segments can also be listed to receive non zero page content (which is a bit of a waste, but it is better to link that to fail).

 

BTW: There are linker options to cause the linker to fill up the remaining bytes more efficiently. With those the linking would have failed more likely :smileyhappy:

BTW2: The content of the STARTUP, STRINGS and other generic sections are allocated in the order they are listed in the prm, so in this case before DEFAULT_ROM. The only two exceptions are COPY and the checksum sections, the content (and size) of those two depend on other sections which have to be placed first.

 

Daniel

 

View solution in original post

0 Kudos
8 Replies
800 Views
isionous
Contributor III

ebrady wrote: It will link fine, but it will not run due to the Init function being placed in Paged Flash.

 

I'm going to assume you're working with some HC12/S12/S12X microcontroller.  In Start12.c there is the _Startup function which is the entry point upon reset, which must not be in banked flash.  _Startup calls Init, which can be in banked flash.  Perhaps you need to make sure your memory model is banked so _Startup uses a 'call' instead of a 'jsr'?

0 Kudos
800 Views
ebrady
Contributor I

Thanks for the feedback..

EDIT:  I am using 9S12XDP512

I am using the banked memory model, when using-->

 

DEFAULT_ROM INTO OS_PAGED_E0 , OS_NONPAGED

 

The _Startup function is placed into non paged memory and the Init function is placed into OS_PAGED_E0. Using the debugger, I was able to step the _Startup function until it tried to call Init.  When I tried to step into Init, it appeared to jump to the correct address in the debugger, but the memory window shows all 0xFFFF

 

One other behavior I --> 

 

When using

DEFAULT_ROM INTO OS_NONPAGED, OS_PAGED_E0

I can arbitrarily shrink the size of OS_NONPAGED and it will link correctly sometimes, however there seems to be no logic as why this works.    Also this will usually work only until I modify a function that exists in Non Paged memory...

0 Kudos
800 Views
isionous
Contributor III

ebrady wrote: When I tried to step into Init, it appeared to jump to the correct address in the debugger, but the memory window shows all 0xFFFF

 

Sounds like that page was not programmed.  Make sure your programmer is set to program paged flash.  You might want to double-check everything with the Project.map file.

 

 

ebrady wrote: I can arbitrarily shrink the size of OS_NONPAGED and it will link correctly sometimes, however there seems to be no logic as why this works.    Also this will usually work only until I modify a function that exists in Non Paged memory...

 

I don't know enough about the linker to explain its quirks and subtle behaviors.  At first I thought OS_NONPAGED might have gotten full from code placed in DEFAULT_ROM and thus _PRESTART, STARTUP, ROM_VAR, and could not fit in OS_NONPAGED.  Thus having DEFAULT_ROM first placed into OS_PAGED_E0 left room in OS_NONPAGED for the other segments.  But with what you just said, I'm confused.

0 Kudos
800 Views
ebrady
Contributor I

Thanks for the insight...  The project.map file was good, however when I double checked the programmer (it's custom), I found a problem with it.  It was in fact not programming OS_PAGED_E0, so this explains why the board was crashed whenever on jump to Init from _Startup

 

It makes sense that the OS_NONPAGED section is becoming full and there are no places to put the required fields like _PRESTART, STARTUP, ROM_VAR. I am assuming the segment gets full and when the linker tries to place one of the required fields it has no place to do so. 

 

My environment is working again, which works for me... I am still curious why chaning the size of OS_NONPAGED to a smaller value worked, but am able to live without an answer for now.

 

Thanks for the help

0 Kudos
801 Views
CompilerGuru
NXP Employee
NXP Employee

You should use the

DEFAULT_ROM        INTO  OS_PAGED_E0, OS_NONPAGED;

order.

 

I try to explain the reason why with the other order the linking does fail for certain setups.

The problem is that DEFAULT_ROM fills up OS_NONPAGED and only the last few bytes of that section may be available to subsequently allocate COPY (the COPY section gets allocated last as its content depends on the content of the other READ_WRITE sections).


With the (not recommended) order

DEFAULT_ROM  INTO  OS_NONPAGED, OS_PAGED_E0;

the linker to places all objects (functions) from DEFAULT_ROM into OS_NONPAGED until one function does not completely fit into OS_NONPAGED anymore. When this happens the linker switches the output to the next segment, here OS_PAGED_E0, and starts placing this function and the future objects in this segment. There are usually a few bytes (less than the size of the first function in OS_PAGED_E0) left in OS_NONPAGED. The linking will now only succeed if the COPY section fits into this gap.

The number of the remaining bytes is pretty unpredictability and therefore the linking success or failure can be triggered by a small change in the C code.

 

The correct (and easy) way to fix this issue is to list the section which also gets COPY as the last one for any PLACEMENT is it used. With that setup the linking will only fail if there is really not enough space left.

In general I would recommend to list sections which can be used for different content behind sections which can only take some particular content. This is not only the case for banked vs non banked segments, but to give another example the S08 has zero page memory which can also be used to host non zero page variables, so those zero page segments can also be listed to receive non zero page content (which is a bit of a waste, but it is better to link that to fail).

 

BTW: There are linker options to cause the linker to fill up the remaining bytes more efficiently. With those the linking would have failed more likely :smileyhappy:

BTW2: The content of the STARTUP, STRINGS and other generic sections are allocated in the order they are listed in the prm, so in this case before DEFAULT_ROM. The only two exceptions are COPY and the checksum sections, the content (and size) of those two depend on other sections which have to be placed first.

 

Daniel

 

0 Kudos
800 Views
ebrady
Contributor I

Thanks Daniel, excellent explanation!

0 Kudos
800 Views
isionous
Contributor III

Daniel, thanks for the explanation.

0 Kudos
800 Views
isionous
Contributor III

My pleasure.  Glad to help.

0 Kudos