Preparing for PROMs:
Steps Required

Applies to: GCC-1750 Version 1.0.
Last updated: Friday May 03, 2002.

By default, the GCC-1750 linker uses its built-in memory layout. This has one 64K-byte block of read-write-execute memory starting at byte address 0x10000. This is exactly what the GCC-1750 development target looks like, but it is probably not what you have.

You can override the default by giving the name of a linker script file on the link command line. If you do not link separately, then you can give the script file option on the compiler command line, using "-Wl," as a prefix. The linker script option is "-T" followed by the name of the script file.

Let us consider an example.

We have a 1750A 16K words of RAM, 8K words of ROM and no memory management unit. We already know that the application program and its stack will fit.

We will not be using interrupts, so the interrupt vector table (32 words from address zero) will not be required. The ROM will start at address zero, and we will place the entry point there.

Note: some 1750s require a Start-up ROM, which overlays addresses from zero up, then switches back to ordinary RAM or ROM when the start-up code is complete.

The RAM can be placed anywhere in the address space but must not overlap the ROM. We will locate the RAM at word address 8000. This is byte address 0x10000.

Note: some 1750s have separate code and data address spaces where it’s OK for RAM and ROM to overlap.

To override the default linker script, we give a script file on the link command line. In our first example, we are going to call the linker script file eg1.ld. You may use any name you like. The following example command line uses this file.

bash$ m1750-coff-gcc -O2 eg1.c -o eg1 -Wl,-T eg1.ld -Wl,-Map=eg1.map    

This command does the following:

bulletruns the C compiler with the given source file (eg1.c)
bulletlinks the generated object code with the run-time system file crt0.o
bulletlinks any required library functions
bulletuses the script file eg1.ld
bulletleaves a map in the file eg1.map.

It is useful to get a map file so that you can convince yourself that everything has been placed where you expect it.

Now let us look at the linker script file.

The first part of the script defines the layout of memory.

MEMORY {
  rom8 : ORIGIN = 0x000000, LENGTH = 16K
  ram16 : ORIGIN = 0x010000, LENGTH = 32K
}    

The second line of the MEMORY command specifies a block of memory starting at address zero, and extending for 16K bytes. This is our 8K word ROM.

The third line specifies a block of memory starting at byte address 64K, which is word address 32K. The block extends for 32K bytes or 16384 words. This is our 16K of RAM, and it is in the top half of memory.

Note that the names "rom8" and "ram16" are arbitrary, and are in the linker’s private name space.

The next line in the script gives a value to the linker symbol __stack. The stack may be anywhere but must not cross the 32K word line where addresses change sign.

PROVIDE (__stack = 0x10000 + 32k - 2);    

The value we have given is the byte address of the highest word in the stack, and becomes the initial value of the stack pointer. The code in file crt0.c imports __stack and sets the stack pointer using the LIM instruction. Usually there is no stack limit check, so you need to be very careful about allowing sufficient space for the stack. If the stack overflows, it is most likely that you will corrupt the .bss area.

Note: you can solve this and other memory problems using the 1750's memory management unit.

The next part of the linker script is the SECTIONS command. This tells the linker what to do with program sections read from object code files and libraries given on its command line.

In GCC-1750, each object file may contain some or all of the following kinds of sections:

bulletThe .text section - contains instructions
bulletThe .data section - contains static initialized data
bulletThe .rdata section - contains static constant data
bulletThe .bss section - contains uninitialized data
bulletThe .ctor section - contains addresses of global constructors
bulletThe .dtor section - contains addresses of global destructors
bulletThe .stabs section - part of the debug symbol table
bulletThe .stabstr section - part of the debug symbol table

All of these sections must be placed somewhere. If you specify a MEMORY command, then the chances are that the default placement will not be what you want. So you should have a statement in the SECTIONS command to tell the linker where to place each kind of section.

Of course, you may want finer control than this. Rather than place all instructions in ROM, you may have several ROMs and wish to place certain object code modules in one ROM, and the rest in another. You can do this with the linker, but we are not going cover that here.

The SECTION command builds linker sections from object code sections, and usually you use the same section names. So the linker puts all .text sections into a compound section called .text.

In this example, we’ll collect all the .text sections, read-only data (.rdata) sections, .ctor and .dtor sections, and put them into the ROM. The linker will locate the instructions for crt0 first.

Here is the SECTIONS command. If you do not intend to use C++ or to define constructors in C, (yes you can do this in GNU C), then the all the stuff to do with CTOR and DTOR can be deleted. You will also need to delete the run-time system functions that refer to these. You will find this code in crt0.c.

SECTIONS
  {
    .text : {
    /* Include all .text sections, and mark each end with a label.
       We use the underscore prefix to avoid clashes with names
       in your C or C++ source files. */
    _stext = .;
    *(.text)
    _etext = .;
  } > rom8

  /* All initialized data sections go into ram. Don't forget to
     write additional code to intialize these sections. Better
     still, include explicit initialization code in your
     application program. */
    .data : {
    _sdata = .;
    *(.data)
    _edata = .;
  } > ram16

  /* All read-only sections go into the second ROM. */
  .rdata : {
    *(.rdata)

    /* Include any C++ global constructors. If you're not using
       C++ then you can delete this and the code in crt0.c that
       refers to it. */

    __CTOR_LIST__ = .;
    LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
    *(.ctors)
    LONG(0)
    __CTOR_END__ = .;

    /* Include any C++ global destructors. You can delete
       this too. */
    __DTOR_LIST__ = .;
    LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
    *(.dtors)
    LONG(0)
    __DTOR_END__ = .;
  } > rom8

  /* The .bss sections, which are uninitialized in the source and
     set to zero at run time, are located in RAM after the .data
     sections. Beyond the end of the .bss sections are the
     heap and stack. */
  .bss : {
    __bss_start = .;
    *(.bss)
    *(COMMON)
    end = ALIGN(0x2);
    _end = ALIGN(0x2);
  } > ram16

  /* Debug symbol tables are not loaded, but do need to get
     linked with the rest of the program. */
  .stab 0 (NOLOAD) :
  {
    [ .stab ]
  }

  .stabstr 0 (NOLOAD) :
  {
    [ .stabstr ]
  }
}
  
Updated May 11, 2005
Copyright XGC Software