

*********************
Placing code and data
*********************

When compiling for modern computers, code and data placement often requires
minimal attention, as tools handle it effectively for same-machine targets.

Cross-compilation is more complex, requiring knowledge of the target
system. Embedded systems are even more challenging, with widely varying
memory systems necessitating precise control over code and data placement.

Effective embedded system tools provide control over code and data
placement. This is achieved using building blocks that offer placement
flexibility and control. The compiler assists by providing abstractions
through type qualifiers, initializers, and runtime model settings, which
simplify configuring the memory system.

.. index:: section

Sections
========

A *section* is a unit of code or data. The compiler will place code
and data into different sections which are saved as separate sections
in the object file.

The compiler places data objects and functions into suitable sections
following specific rules. For data objects, it considers if the object is
``const``, its address space, and explicit initializers.

.. index:: code; section, farcode; section,
.. index:: compactcode; section,
.. index:: znear; section, near; section, cnear; section
.. index:: ztiny; section, tiny; section, switch; section
.. index:: zfar; section, far; section, cfar; section
.. index:: zhuge; section, huge; section, chuge; section
.. index:: idata; section, inear; section, ifar; section, ihuge; section
.. index:: data_init_table; section

.. index:: section; code, section; farcode
.. index:: section; compactcode
.. index:: section; znear, section; near, section; cnear
.. index:: section; ztiny, section; tiny, section; switch
.. index:: section; zfar, section; far, section; cfar
.. index:: section; zhuge, section; huge, section; chuge
.. index:: section; idata, section; inear, section; ifar, section; ihuge
.. index:: section; data_init_table

.. table:: Sections
 :widths: 2 1 1 4
 :column-dividers: none single single single none
 :column-alignment: left left left left

 +----------------------+------------+------------------+---------------------------------+
 |Section name          |Type        |Memory kind       |Description                      |
 +======================+============+==================+=================================+
 | ``code``             |text        |ROM               |Executable code                  |
 +----------------------+------------+------------------+---------------------------------+
 | ``compactcode``      |text        |ROM               |Executable code                  |
 +----------------------+------------+------------------+---------------------------------+
 | ``farcode``          |text        |ROM               |Executable code                  |
 +----------------------+------------+------------------+---------------------------------+
 | ``ztiny``            |bss         |RAM               |Zero initialized (bss)           |
 |                      |            |                  |direct page data                 |
 +----------------------+------------+------------------+---------------------------------+
 | ``tiny``             |data        |RAM               |Initialized direct page data     |
 +----------------------+------------+------------------+---------------------------------+
 | ``zdata``            |bss         |RAM               |Zero initialized (bss) data,     |
 |                      |            |                  |default memory, Small data model |
 |                      |            |                  |only                             |
 +----------------------+------------+------------------+---------------------------------+
 | ``data``             |data        |RAM               |Initialized near data, default   |
 |                      |            |                  |memory, Small data model only    |
 +----------------------+------------+------------------+---------------------------------+
 | ``cdata``            |rodata      |ROM               |Constant near data, default      |
 |                      |            |                  |memory, Small data model only    |
 +----------------------+------------+------------------+---------------------------------+
 | ``znear``            |bss         |RAM               |Zero initialized (bss) near      |
 |                      |            |                  |data, not available in           |
 |                      |            |                  |Small data model                 |
 +----------------------+------------+------------------+---------------------------------+
 | ``near``             |data        |RAM               |Initialized near data, not       |
 |                      |            |                  |available in Small data model    |
 +----------------------+------------+------------------+---------------------------------+
 | ``cnear``            |rodata      |ROM               |Constant near data, not          |
 |                      |            |                  |available in Small data model    |
 +----------------------+------------+------------------+---------------------------------+
 | ``zfar``             |bss         |RAM               |Zero initialized (bss) far data  |
 +----------------------+------------+------------------+---------------------------------+
 | ``far``              |data        |RAM               |Initialized far data             |
 +----------------------+------------+------------------+---------------------------------+
 | ``cfar``             |rodata      |ROM               |Constant far data                |
 +----------------------+------------+------------------+---------------------------------+
 | ``zhuge``            |bss         |RAM               |Zero initialized (bss) huge data |
 +----------------------+------------+------------------+---------------------------------+
 | ``huge``             |data        |RAM               |Initialized huge data            |
 +----------------------+------------+------------------+---------------------------------+
 | ``chuge``            |rodata      |ROM               |Constant huge data               |
 +----------------------+------------+------------------+---------------------------------+
 | ``switch``           |rodata      |ROM               |Switch tables                    |
 +----------------------+------------+------------------+---------------------------------+
 | ``itiny``            |rodata      |ROM               |Tiny data initializers           |
 +----------------------+------------+------------------+---------------------------------+
 | ``idata``            |rodata      |ROM               |Data initializers, default       |
 |                      |            |                  |memory, Small data model only    |
 +----------------------+------------+------------------+---------------------------------+
 | ``inear``            |rodata      |ROM               |Near data initializers, not      |
 |                      |            |                  |available in Small data model    |
 +----------------------+------------+------------------+---------------------------------+
 | ``ifar``             |rodata      |ROM               |Far data initializers            |
 +----------------------+------------+------------------+---------------------------------+
 | ``ihuge``            |rodata      |ROM               |huge data initializers           |
 +----------------------+------------+------------------+---------------------------------+
 | ``data_init_table``  |rodata      |ROM               |Data initializer table           |
 +----------------------+------------+------------------+---------------------------------+
 | ``registers``        |noinit      |RAM               |Pseudo registers in direct page  |
 +----------------------+------------+------------------+---------------------------------+
 | ``reset``            |text        |ROM               |Reset vector, when used          |
 +----------------------+------------+------------------+---------------------------------+
 | ``heap``             |noinit      |RAM               |Heap memory, for ``malloc()``    |
 +----------------------+------------+------------------+---------------------------------+
 | ``stack``            |noinit      |RAM               |CPU stack, anywhere in bank 0    |
 +----------------------+------------+------------------+---------------------------------+

The sections ``itiny``, ``inear``, ``ifar``, ``ihuge`` and ``data_init_table`` in
the table above are linker generated.

.. note::

   It is assumed that there is no ROM in direct page. Constants placed
   in ``tiny`` address space are handled in the same way as
   non-constant data objects in the  ``tiny`` address space.
   The only difference is that they have the ``const`` attribute in the
   C type system.

.. note::

   The table assigns sections to ROM and RAM for ROM-based applications
   that start on power-up. For hosted systems loading from storage to
   RAM, this distinction is not applicable. Always consider ROM-marked
   sections as read-only.

Section types are derived from the UNIX world; see :ref:`sectionkinds`
in the assembler reference for details.

.. note::

   When generating a ROM-executable application, the linker separates an
   initialized data section into two. Initializers go into a new ``i``-prefixed
   section (placed in ROM); the data section is placed in RAM. The C runtime
   startup module copies initializers from ROM to RAM before giving control to
   the ``main()`` function.


Linking process
----------------

The linker reads object files with sections and a placement rules file.
This file describes available memory areas and their permitted sections,
optionally with additional placement constraints.

Memories containing actual value bits (program code or initialized data)
are emitted in the executable.

An executable can serve as input for ROM or FLASH programmers, be loaded by
the target machine, or be used by a debugger that connects to or simulates
the target. Various executable formats are available to suit different
execution environments.

.. note::

   Although code and data are entirely separated into different sections,
   placing these sections together in the same memory may be desirable.
   This can be achieved at the link stage.

.. index:: linker rules, section; placement
.. index:: placement control

Placing sections in memory
--------------------------

The linker rules file uses file extension ``.scm``, which is actually
a source file in the Scheme language. However, you do not need to
learn Scheme in order to use it, as it just a simple description of
available memories and their associated properties. Sections are then
bound to the memories. You can also define the size of the stack and
heap in this file.

A simple example of such linker rules file is:

.. literalinclude:: example/simple-linker-rules.scm
   :language: scheme

The Scheme interpreter evaluates the rules file, which defines a single
global ``memories`` object. This object lists ``memory`` and block
objects. Sections can be bound to memories either by specifying the memory
type or by listing the sections within each memory.

The example simplifies memory system description. The linker deduces where
compiler and linker-generated sections are placed; this requires specifying
the memory type. To prevent automatic section placement in a memory, omit
its type specification.

.. note::

   You can specify a memory type and manually place custom sections.
   This is useful for sections requiring specific placement.

.. note::

   Since the linker rules file is a Scheme program, it can theoretically
   construct the ``memories`` object via functions or macros. After evaluation,
   the Scheme interpreter is expected to leave a ``memories`` object in its
   global environment. However, a simple file like the example is usually
   sufficient.

.. index:: initialization; of data, data initialization
.. index:: heap; initialization, file streams; initialization

Data initialization
===================

A startup routine is performed before the ``main()`` function is called. This
startup routine takes care of preparing the execution environment for the C
program by initializing the stack pointer, initialize global variables
and prepare system resources such as file streams and the heap, if
used by the application.

Static data
-----------

Static data that needs to be initialized comes in two forms, zero
initialized and those that have non-zero initializers. Zero
initialization is done by filling such memory ranges with zero.
Explicit initialization is done by copying an initializer section in
ROM to its corresponding RAM area.

This process is table driven using a section named ``data_init_table``
which should be placed in the same memory as the ``cdata`` section, which
holds constants.

.. note::

   In a hosted environment, the linker provides the ``--hosted`` command-line
   option. This assumes the program image loads directly into RAM from
   external media. Variable initialization is done in-place via the
   load action; therefore, separate initializers are not required.

   The ``--target`` option also has the effect of enabling running in a hosted environment.

.. index:: stack; usage

Stack
=====

The stack stores function return addresses, saved registers, and local
variables. It tracks the current execution state, enabling reentrant
and recursive functions.

.. index:: stack; size considerations

Stack size considerations
-------------------------

The stack size is defined in the linker rules file.
The stack size should be set low as possible, but not any lower.
If given too much space you are wasting RAM space not
being used for anything. However, if set too small it will cause
corruption of other data.

Exact stack use can be hard to predict and it is better to err on the
side of some safety. Also during development of your application you
may want to use a bit oversized stack if possible, to allow you to focus
on other issues. In the end, you are most likely constrained by some
fixed amount of RAM and need to balance how much you can use for the
stack with the optional heap and statically allocated data.
