10.9.1. Using the crc_table() Operator in the SECTIONS Directive

For any section that should be verified with a CRC, the linker command file must be modified to include the crc_table() operator. The specification of a CRC algorithm is optional. The syntax is:

crc_table(user_specified_table_name[, algorithm=xxx])

The linker uses the CRC algorithm from any specification given in a crc_table() operator. If that specification is omitted, the TMS570_CRC64_ISO algorithm is used. The linker includes CRC table information in the map file. This includes the CRC value as well as the algorithm used for the calculation.

The CRC table generated for a particular crc_table() instance can be accessed through the table name provided as an argument to the crc_table() operator. The linker creates a symbol with this name and assigns the address of the CRC table as the value of the symbol. The CRC table can then be accessed from the application using the linker-generated symbol.

The crc_table() operator can be applied to an output section, a GROUP, a GROUP member, a UNION, or a UNION member. In a GROUP or UNION, the operator is applied to each member.

You can include calls in your application to a routine that will verify CRC values for relevant sections. You must provide this routine. See below for more details on the data structures and suggested interface.

10.9.1.1. Restrictions when using the crc_table() Operator

It is important to note that the CRC generator used by the linker is parameterized as described in the crc_tbl.h header file (see Interface When Using the crc_table() Operator). Any CRC calculation routine employed outside of the linker must function in the same way to ensure matching CRC values. The linker cannot detect a mismatch in the parameters. To understand these parameters, see A Painless Guide to CRC Error Detection Algorithms by Ross Williams.

Only CRC algorithm names and identifiers in crc_tbl.h are supported. All other names and ID values are reserved for future use. Systems may not include built-in hardware that computes these CRC algorithms. Consult documentation for your hardware for details. These CRC algorithms are supported:

  • CRC8_PRIME

  • CRC16_ALT

  • CRC16_802_15_4

  • CRC_CCITT

  • CRC24_FLEXRAY

  • CRC32_PRIME

  • CRC32_C

  • CRC64_ISO

The default is the TMS570_CRC64_ISO algorithm, which has an initial value of 0. Additional information about the algorithm can be found in A Note on the TMS570_CRC64_ISO Algorithm.

There are also restrictions that will be enforced by the linker:

  • CRC can only be requested at final link time.

  • CRC can only be applied to initialized sections.

  • CRC can be requested for load addresses only.

  • Certain restrictions also apply to CRC table names. For example, BINIT may not be used as a CRC table name.

10.9.1.2. Examples When Using the crc_table() Operator

The crc_table() operator is similar in syntax to the table() operator used for copy tables. A few simple examples of linker command files follow.

The following example defines a section named “.section_to_be_verified”, which contains the .text data from the a1.c.o file. The crc_table() operator requests that the linker compute the CRC value for the .text data and store that value in a table named “my_crc_table_for_a1”.

SECTIONS
{
    ...
    .section_to_be_verified: {a1.c.o(.text)} crc_table(_my_crc_table_for_a1)
}

This table will contain all the information needed to invoke a user-supplied CRC calculation routine, and verify that the CRC calculated at run time matches the linker-generated CRC. The table can be accessed from application code using the symbol my_crc_table_for_a1, which should be declared of type “extern CRC_TABLE”. This symbol will be defined by the linker. The application code might resemble the following.

#include "crc_tbl.h"

extern CRC_TABLE my_crc_table_for_a1;

verify_a1_text_contents()
{
    ...
    /* Verify CRC value for .text sections of a1.c.o. */
    if (my_check_CRC(&my_crc_table_for_a1)) puts("OK");
}

The my_check_CRC() routine is shown in detail in Interface When Using the crc_table() Operator.

In the following example, the CRC algorithm is specified in the crc_table() operator. The specified algorithm is used to compute the CRC of the text data from b1.c.o. The CRC tables generated by the linker are created in the special section .TI.crctab, which can be placed in the same manner as other sections. In this case, the CRC table _my_crc_table_for_b1 is created in section .TI.crctab:_my_crc_table_for_b1, and that section is placed in the CRCMEM memory region.

SECTIONS
{
    ...
    .section_to_be_verified_2: {b1.c.o(.text)} load=SLOW_MEM, run=FAST_MEM,
        crc_table(_my_crc_table_for_b1, algorithm=TMS570_CRC64_ISO)

.TI.crctab: > CRCMEM
}

In the following example, the same identifier, _my_crc_table_for_a1_and_c1, is specified for both a1.c.o and c1.c.o. The linker creates a single table that contains entries for both text sections. Multiple CRC algorithms can occur in a single table. In this case, _my_crc_table_for_a1_and_c1 contains an entry for the text data from a1.c.obj using the default CRC algorithm, and an entry for the text data from c1.c.obj using the TMS570_CRC64_ISO algorithm. The order of the entries is unspecified.

SECTIONS
{
    .section_to_be_verified_1: {a1.c.o(.text)}
        crc_table(_my_crc_table_for_a1_and_c1)
    .section_to_be_verified_3: {c1.c.o(.text)}
        crc_table(_my_crc_table_for_a1_and_c1, algorithm=TMS570_CRC64_ISO)
}

When the crc_table() operator is applied to a GROUP or a UNION, the linker applies the table specification to the members of the GROUP or UNION.

In the following example, the linker creates two CRC tables, table1 and table2. table1 contains one entry for section1. Because both sections are members of the UNION, table2 contains entries for section1 and section2. The order of the entries in table2 is unspecified.

SECTIONS
{
    UNION
    {
        section1: {} crc_table(table1)
        section2:
    } crc_table(table2)
}

10.9.1.3. Interface When Using the crc_table() Operator

The CRC generation function uses a mechanism similar to the copy table functionality. Using the syntax shown above in the linker command file allows specification of code/data sections that have CRC values computed and stored in the run time image. This section describes the table data structures created by the linker, and how to access this information from application code.

The CRC tables contain entries as detailed in the run-time-support header file crc_tbl.h, as shown in the following figure:

../../../_images/CRC_table_spnu118.png

The crc_tbl.h header file is included below. This file specifies the C structures created by the linker to manage CRC information. It also includes the specifications of the supported CRC algorithms. A full discussion of CRC algorithms is beyond the scope of this document, and the interested reader should consult the referenced document for a description of the fields shown in the table. The following fields are relevant to this document.

  • Name – text identifier of the algorithm, used by the programmer in the linker command file.

  • ID – the numeric identifier of the algorithm, stored by the linker in the crc_alg_ID member of each table entry.

  • Order – the number of bits used by the CRC calculation.

  • Polynomial – used by the CRC computation engine.

  • Initial Value – the initial value given to the CRC computation engine.

/*****************************************************************************/
/* crc_tbl.h                                                                 */
/*                                                                           */
/* Specification of CRC table data structures which can be automatically     */
/* generated by the linker (using the crc_table() operator in the linker     */
/* command file).                                                            */
/*****************************************************************************/
/*                                                                           */
/* The CRC generator used by the linker is based on concepts from the        */
/* document:                                                                 */
/* "A Painless Guide to CRC Error Detection Algorithms"                      */
/*                                                                           */
/* Author : Ross Williams (ross@guest.adelaide.edu.au.).                     */
/* Date : 3 June 1993.                                                       */
/* Status : Public domain (C code).                                          */
/*                                                                           */
/* Description : For more information on the Rocksoft^tm Model CRC           */
/* Algorithm, see the document titled "A Painless Guide to CRC Error         */
/* Detection Algorithms" by Ross Williams (ross@guest.adelaide.edu.au.).     */
/*****************************************************************************/
#include <stdint.h>        /* For uintXX_t */

/*****************************************************************************/
/* CRC Algorithm Specifiers                                                  */
/*                                                                           */
/* The following specifications, based on the above cited document, are used */
/* by the linker to generate CRC values.                                     */
/*
 ID Name                Order Polynomial  Initial     Ref Ref CRC XOR     Zero
                                          Value       In  Out Value       Pad
------------------------------------------------------------------------------
 10 "TMS570_CRC64_ISO", 64,   0x0000001b, 0x00000000, 0,  0,  0x00000000, 1
                                                                             */
/* Users should specify the name, such as TMS570_CRC64_ISO, in the linker    */
/* command file. The resulting CRC_RECORD structure will contain the         */
/* corresponding ID value in the crc_alg_ID field.                           */
/*****************************************************************************/
#define TMS570_CRC64_ISO 10

/*********************************************************/
/* CRC Record Data Structure                             */
/* NOTE: The list of fields and the size of each field   */
/* varies by target and memory model.                    */
/*********************************************************/
typedef struct crc_record
{
    uint64_t   crc_value;
    uint32_t   crc_alg_ID; /* CRC algorithm ID      */
    uint32_t   addr;       /* Starting address      */
    uint32_t   size;       /* size of data in bytes */
    uint32_t   padding;    /* explicit padding so layout is the same for ELF */
} CRC_RECORD;

In the CRC_TABLE struct, the array recs[1] is dynamically sized by the linker to accommodate the number of records contained in the table (num_recs). A user-supplied routine to verify CRC values should take a table name and check the CRC values for all entries in the table. An outline of such a routine is shown in the following example:

/**************************************************************/
/* General-purpose CRC check routine. Given the address of a  */
/* linker-generated CRC_TABLE data structure, verify the CRC  */
/* of all object components that are designated with the      */
/* corresponding LCF crc_table() operator.                    */
/**************************************************************/
#include <crc_tbl.h>

/*********************************************************/
/* MY_CHECK_CRC() - returns 1 if CRCs match, 0 otherwise */
/*********************************************************/
unsigned int my_check_CRC(CRC_TABLE *tp)
{
    int i;

    for (i = 0; i < tp-> num_recs; i++)
    {
        CRC_RECORD crc_rec = tp->recs[i];

        /**************************************************/
        /* COMPUTE CRC OF DATA STARTING AT crc_rec.addr   */
        /* FOR crc_rec.size UNITS. USE                    */
        /* crc_rec.crc_alg_ID to select algorithm.        */
        /* COMPARE COMPUTED VALUE TO crc_rec.crc_value.   */
        /**************************************************/
    }
    if all CRCs match, return 1;
    else return 0;
}