Creating an LCF from Scratch

Consider creating a LCF for a sample BOOKE ROM project.

First add the memory area for vectors (interrupts), exception tables, code, data, heap and stack.

Listing 1. Adding memory area
MEMORY
{

    resetvector:           org = 0x00000000,   len = 0x00000008

    exception_handlers_p0: org = 0x00001000,   len = 0x00001000

    internal_flash:        org = 0x00003000,   len = 0x001FD000

    

    internal_ram:          org = 0x40000000,   len = 0x0007C000

    heap  :                org = 0x4007C000,   len = 0x00002000 /*  Heap start location */

    stack :                org = 0x4007E000,   len = 0x00002000 /* Start location for Stack */

}

Place the sections to the above memory areas in LCF in the SECTIONS { } block.

.__bam_bootarea LOAD (0x00000000): {} > resetvector

The code to handle exceptions are grouped and placed in memory area exception_handlers_p0.

Listing 2. Grouping exceptions code
    GROUP : {
      .ivor_branch_table_p0  LOAD (0x00001000)   : {}

      .intc_hw_branch_table_p0 LOAD (0x00001800): {}           

      .__exception_handlers_p0   LOAD (0x00001100) : {}

    } > exception_handlers_p0

The hardware initialization routines, application code, constants, code for constructors/destructors, and C++ exception tables are grouped together and placed in Flash.

Listing 3. Grouping initialization routines
   GROUP : {
      .intc_sw_isr_vector_table_p0 ALIGN (2048) : {}
      .init : {}
      .text : {} 
       .rodata (CONST) : {
         *(.rdata)
         *(.rodata)
       }
       .ctors : {}
       .dtors : {}
       extab : {}
       extabindex : {}
    } > internal_flash

The uninitialized and initialized data are placed in RAM.

Listing 4. Placing data in RAM
   GROUP : {
       .__uninitialized_intc_handlertable ALIGN(2048) : {}

       .data   : {}

       .sdata  : {}

       .sbss   : {}

       .sdata2 : {}

       .sbss2  : {}

       .bss    : {}

    } > internal_ram 
Note: For more information on placing data in RAM refer to MCU_Power_Architecture_Compiler.pdf.

The sections are allocated to segments in the order given in SECTIONS/GROUP block of lcf file.

For internal_flash segment, following is the order of section allocation: .init, .text, .rodata, .ctors, .dtors, extab and extabindex.

Variables are added in LCF and these can be used in application as well as internally in linker tool for computation.

Listing 5. Adding variables in LCF
_stack_addr = ADDR(stack)+SIZEOF(stack);
_stack_end  = ADDR(stack);

_heap_addr  = ADDR(heap);

_heap_end   = ADDR(heap)+SIZEOF(heap);

EXCEPTION_HANDLERS    = ADDR(exception_handlers_p0);

L2SRAM_LOCATION = 0x40000000;

Let us take a simple example to see how the allocation of variables to the respective sections take place.

Listing 6. C Source file
#include "MPC5675K.h"

int sdata_i = 10;

int sbss_i;

const char sdata2_array[] = "Hello";

__declspec(section ".rodata") const char rodata_array[40]="CodeWarior";

__declspec(section ".data") long bss_i;

__declspec(section ".data") long data_i = 10;

int main(void) {

  return sdata_i + sbss_i + sdata2_array[3] + data_i + bss_i + rodata_array[5];

}
Note: Above is a hypothetical example built to provide clarity on variables and their allocation to sections. __declspec is used to forcefully place the variables into sections.

The table below lists the details of the allocation of objects to the sections.

Table 1. Allocating Objects
Variable Section Address
sdata_i .sdata 0x400004d8
sbss_i .sbss 0x400004e8
sdata2_array .sdata2 0x40000500
rodata_array .rodata 0x00003938
bss_i .bss 0x40000508
data_i .data 0x400004d0
Related information
Predefined Sections
Additional Small Data Sections
Linker Map File
Deadstripping
CodeWarrior Linker Command File (LCF)
Relocating Code in ROM
Relocating Code and Data in Internal RAM
Relocating Code and Data in External MRAM
Unique LCF Examples
Linker Command File Commands