SLAA534A June 2013 – June 2020
As described in Section 4.2, initialized read-write variables are collected into dedicated section(s) of the object file, for example .data. The section contains an image of its initial state upon program startup.
The TI toolchain supports two models for loading such sections. In the so-called RAM model, some unspecified external agent such as a loader is responsible for getting the data from the executable file to its location in read-write memory. This is the typical direct-initialization model used in OS-based systems or, in some instances, boot-loaded systems.
The other model, called the ROM model, is intended for bare-metal embedded systems that must be capable of cold starts without support of an OS or other loader. Any data needed to initialize the program must reside in persistent offline storage (ROM), and get copied into its RAM location upon startup. The TI toolchain implements this by leveraging the copy table capability described in Chapter 14. The initialization mechanism is conceptually similar to copy tables, but differs slightly in the details.
Figure 14-3 depicts the conceptual operation of variable initialization under the ROM model. In this model, the linker removes the data from sections that contain initialized variables. The sections become uninitialized sections, allocated into RAM at their run-time address (much like, say, .bss). The linker encodes the initialization data into a special section called .cinit (for C Initialization), where the startup code from the run-time library decodes and copies it to its run address.
Like copy tables, the source data in the .cinit tables may or may not be compressed. If it is compressed, the encoding and decoding scheme is identical to that of copy tables so that the handler tables and decompression handlers can be shared.
The .cinit section contains some or all of the following items:
These items may be in any order.
Figure 14-4 is a schematic depiction of the .cinit section.
The .cinit section has the section type SHT_TI_INITINFO which identifies it as being in this format. Tools should rely on the section type and not on the name .cinit.
Two special symbols are defined to delimit the cinit table: __TI_CINIT_Base points to the cinit table, and __TI_CINIT_Limit points one byte past the end of the table. The startup code references the table using these symbols.
The format of the CINT_RECORD structure depends on the code and data model being used.
For the small data model and small code model:
typedef struct {
void * source_data; /* 16-bit pointer */
void * dest; /* 16-bit pointer */
} CINIT_RECORD;
For the small data model and large code model:
typedef struct {
uint32 source_data; /* 32-bit storage for data or code pointer */
uint32 dest; /* 32-bit storage for data or code pointer */
} CINIT_RECORD;
For the large (or restricted) data model and large code model:
typedef struct {
void * source_data; /* 20-bit pointer */
void * dest; /* 20-bit pointer */
} CINIT_RECORD;
The source data has the same format as compressed copy table source data (see Section 14.2), and the handlers have the same interface. In addition to the RLE and LZSS formats, there are two additional formats defined for cinit records: uncompressed, and zero-initialized.
The encoded data includes a size field, which is aligned on the next 2-byte boundary following the handler index. The size of the "size" field depends on the memory model. For the small code and small data model, the size is 2 bytes. In all other memory model combinations, the size is 4 bytes. The size field specifies how many bytes are in the data payload, which begins immediately following the size field. The initialization operation copies sizebytes from the data field to the destination address. The TI run-time library contains a handler called _ _TI_decompress_none for the uncompressed format.
The size field is aligned on the next 2-byte boundary following the handler index. The size of the "size" field depends on the memory model. For the small code and small data model, the size is 2 bytes. In all other memory model combinations, the size is 4 bytes. The initialization operation fills size consecutive bytes at the destination address with zero. The TI run-time library contains a handler called _ _TI_zero_init for this format.
As an optimization, the linker is free to coalesce initializations of adjacent objects into single cinit records if they can be profitably encoded using the same format. This is typically significant for zero-initialized objects.