This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CL2000 linker generating wrong autoinitialization data



I need to configure fixed address for internal variables with some default values. I correctly get variables at specified addresses, but some values are initialized to zero instead of specified value. After some investigation I found linker is generating wrong size for intialization data.

I created simple program to reproduce it (using eabi):

#include <stdint.h>

uint16_t a4[4] = {64,65,66,67};
uint16_t a3[3] = {48,49,50};
uint16_t a2[2] = {32,33};
uint16_t a1[1] = {16};
uint16_t a0 = 0x100;

#pragma LOCATION( a0, 0xA800 )
#pragma LOCATION( a1, 0xA801 )
#pragma LOCATION( a2, 0xA802 )
#pragma LOCATION( a3, 0xA804 )
#pragma LOCATION( a4, 0xA807 )


int main(void)
{
    
    // some variable access to avoid optimization out
    a4[0] = a0; a3[0] = a4[0];  a2[0] = a3[0];   a1[0] = a2[0];   a0 = a1[0];

	return 0;
}

relevant output in linker map seems to be correct:

LINKER GENERATED COPY TABLES

__TI_cinit_table @ 00082120 records: 6, size/record: 4, table size: 24
    .data: load addr=000820f0, load size=00000009 bytes, run addr=0000aa00, run size=0000000a bytes, compression=lzss
    .TI.bound:a4: load addr=000820fa, load size=00000008 bytes, run addr=0000a807, run size=00000004 bytes, compression=copy
    .TI.bound:a3: load addr=00082102, load size=00000007 bytes, run addr=0000a804, run size=00000003 bytes, compression=copy
    .TI.bound:a2: load addr=0008210a, load size=00000006 bytes, run addr=0000a802, run size=00000002 bytes, compression=copy
    .TI.bound:a0: load addr=00082110, load size=00000005 bytes, run addr=0000a800, run size=00000001 bytes, compression=copy
    .TI.bound:a1: load addr=00082116, load size=00000005 bytes, run addr=0000a801, run size=00000001 bytes, compression=copy

but when I check generated binary file I see there inconsistency (like saturation for minimum of two 16-bit "bytes"), which is causing to copy two 16-bit bytes for 16-bit variables instead of one byte what is causing unintended zeroing of the next address (which is used for different variable):

data from generated binary:

uint16_t a4[4] = {64,65,66,67};

    @0820FA = 0x1    // type
    @0820FB = 0x0
    @0820FC = 0x4    // length - correct
    @0820FD = 0x0
    @0820FE = 0x40
    @0820FF = 0x41
    @082100 = 0x42
    @082101 = 0x43

uint16_t a3[3] = {48,49,50};

    @082102 = 0x1   // type
    @082103 = 0x0
    @082104 = 0x3   // length - correct
    @082105 = 0x0
    @082106 = 0x30
    @082107 = 0x31
    @082108 = 0x32
    @082109 = 0x0


uint16_t a2[2] = {32,33};

    @08210A = 0x1   // type
    @08210B = 0x0
    @08210C = 0x2   // length - correct
    @08210D = 0x0
    @08210E = 0x20
    @08210F = 0x21

uint16_t a1[1] = {16};

    @082110 = 0x1   // type
    @082111 = 0x0
    @082112 = 0x2   // length - should be 1
    @082113 = 0x0
    @082114 = 0x100
    @082115 = 0x0

uint16_t a0 = 0x100;

    @082116 = 0x1   // type
    @082117 = 0x0
    @082118 = 0x2   // length - should be 1
    @082119 = 0x0
    @08211A = 0x10
    @08211B = 0x0

Is there some configuration which I'm missing or is it bug and exists some good workaround?

For complete description, what i really need is to create several 16-bit varaiables which are on specified addresses without gap. (I would like to avoid creating structs).

I was using code composer 9.3, but same issue is also with 12.2.

from build console log:

Invoking: C2000 Linker
"/opt/ti/ccs1220/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS/bin/cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 --advice:performance=all -g --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi -z -m"test.map" --stack_size=0x200 --warn_sections -i"/opt/ti/ccs1220/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS/lib" -i"/opt/ti/ccs1220/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS/include" --reread_libs --diag_wrap=off --display_error_number --xml_link_info="test_linkInfo.xml" --rom_model -o "test.out" "./main.obj" "../28375S.cmd"  -lrts2800_fpu32_eabi.lib

  • is it bug

    Unfortunately, yes.  It has already been reported.  Please see EXT_EP-10875.

    exists some good workaround?

    I have a workaround for you to consider.

    The problem only applies to scalar global variables.  Here is a C macro which defines one variable to not be initialized, and allocated to a specific address.

    // DNVA : Define No-init scalar Variable at a specific Address
    #define DNVA(type, name, address) \
        type name __attribute__((noinit, location(address)))

    You can do the same thing with #pragma statements.  But it takes two of them, and it is hard to wrap that in a convenient macro like this.

    Here is an example of how to use the macro.

    DNVA(uint16_t, a0, 0xa800);

    The variable is not initialized.  To do that, take advantage of the boot hook function _system_post_cinit.  Add this function to a source file in your project.

    void _system_post_cinit()
    {
        a0 = 0x100;
    }

    Of course, change it to initialize all the global scalar variables affected by this problem.

    To understand more about the variable attributes, please search the C28x compiler manual for the sub-chapter titled Variable Attributes.  To understand more about _system_post_cinit, search the same manual for the sub-chapter titled Boot Hook Functions for System Pre-Initialization.

    Thanks and regards,

    -George

  • Thank you for quick answer. I was considering similar workaround to put variables initialization at the beginning of the main(), but using _system_post_cinit looks nicer.

    Thanks and regards,

    Branislav