17.2.10.1 Data-initialization Template

In order to clear or initialize all the data and RAM function sections, the linker creates a data-initialization template, which is loaded into an output section named .dinit and allocated space in program memory. The code in the C/C++ start-up module, crt0.o, interprets this template, which indicates how the appropriate sections must be initialized.

The sections initialized by this template includes those holding intialized objects (such as the .data section) as well as sections containing ramfunc attributed functions, all of which must have values copied from the template in program to data memory where the objects and functions will be accessed at runtime. Other data sections holding unititialized objects (such as the .bss section) are cleared by the template before the main() function is called. The persistent data section (.pbss) is not considered by the runtime startup code. When the application’s main program takes control, all objects and RAM functions in data memory will have been initialized.

The data initialization template contains one record for each output section that needs initializing. Each record has one of several formats, represented by a format code within the record. The record formats specify how the data values are stored in the record itself and how they should be used to initialize the corresponding section. The --dinit-compression linker option (see Dinit-compression Option) controls which of these records can be utilized by the template. The numerical format codes and the type of initialization they represent are as follows:
#0
Fill the RAM defined by the corresponding output section with zeros. No data bytes are stored in the record. Used by bss sections.
#1
Copy each byte of data from the record's array to the RAM associated with the output section. Used by data and lit sections, and sections associated with ramfunc functions.
#2
Copy the same 16-bit value into the RAM associated with the output section multiples times. Used by data and lit sections whose initial values are a repeating sequence.
#3
Copy the same 32-bit value into the RAM associated with the output section multiple times. Used by data and lit sections whose initial values are a repeating sequence.
#4
Copy and decompress a simplified version of PackBits encoded data_record. Used by data and lit sections, and sections that contain large numbers of consecutive zero bytes.
The data contained in each record type can be represented by the equivalent C structures that are presented below. The first element of the record is a pointer to the section in data memory. The second element is the section length or repeat count. The third element is the format code, which indicates the type of the record (listed above) and hence how the corresponding section should be initialized. The forth element is used for either alignment padding or an initial value. A fifth element, if present, is an array of data bytes.The template is terminated by a null instruction word.
/* For format values of 0 */
struct data_record_bss {
    uint32_t *dst;     /* destination address */
    uint32_t len;      /* length in bytes */
    uint16_t format;   /* format code */
    uint16_t padding;  /* padding for alignment */
};

/* For format values of 1 and 3 (also identical to format value 4) */
struct data_record_standard {
    uint32_t *dst;     /* destination address */
    uint32_t len;      /* length in bytes */
    uint16_t format;   /* format code */
    uint16_t padding;  /* padding for alignment or a 16-bit initialization value */
    uint32_t dat[0];   /* object-length data - holding initialization data */
};

/* For format values of 2 - objects are initialised with the same 16-bit value */
struct data_record_short_standard {
    uint32_t *dst;     /* destination address */
    uint32_t count;    /* count in bytes */
    uint16_t format;   /* format code */
    uint16_t dat       /* 16-bit repeated value data */
};

/* For format values of 4 - A simplified PackBits data compression is applied, where
each run of zeros is replaced by two 8-bit characters in the compressed array:
zero followed by the number of zeros in the original run. */
struct data_record_compressed {
    uint32_t *dst;               /* destination address */
    uint32_t count;              /* count in bytes */
    uint16_t format;             /* format code */
    uint16_t padding;            /* 16-bit repeated value data */
    uint32_t compressed_data[0]; /* compressed intialized data */
};

When the new --mchp-dinit=word option (or its synonym --word-dinit) has been issued, a different word-initialization scheme is available. Under this scheme, the layout of the data initialization template is different from that described above, but each record remains 12 bytes in length. Data is initialized using 32-bit word writes and so is faster than the byte-oriented writes used by the default scheme. For this alternative scheme to work, objects must be aligned to a word address. Any padding to achieve this can increase the size of the data memory, so to mitigate this, sections with similar initialization needs are allocated contiguously and share a single record in the initialization template. This reduces the impact of both padding and the number of records, and by aggressively pursuing this strategy, the memory footprint is kept as small as possible.

If an object is placed with an absolute address in RAM such that it partitions the memory space, there is an increased chance of memory allocation failing. Additionally, word initialization does not support data compression, so if the application data is suitable for compression, the program code size might actually be smaller with this feature disabled.

For devices with ECC memory, this initialization scheme satisfies the word-write requirements of this memory as well as achieving greater efficiency. For more details on the --word-dinit linker option and other linker settings that control data initialization, refer to the MPLAB® XC32 Assembler, Linker and Utilities User’s Guide.