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.

Compiler/MSP430F5438A: Maintaining variable declaration order

Part Number: MSP430F5438A

Tool/software: TI C/C++ Compiler

Hi Team,

is there a way to maintain the order of variable declartion in out file?

for e.g. i have following variables 

Uint32 crc;

Uint8 version[9];

Bool flag1;

Bool flag2;

Bool flag3;

Int32 var1[2];

Int32 var2;

Uint32 var3;

After compiling, when i see the order of memory allocation, they appear to be randomly allocated. I need them to be sequentially allocated. How can i achieve that.

Following are the compiler flag that i have in my project:

source/SCDF/%.obj: ../source/SCDF/%.c $(GEN_OPTS) | $(GEN_FILES) $(GEN_MISC_FILES)
@echo 'Building file: "$<"'
@echo 'Invoking: MSP430 Compiler'
"C:/ti/ccs920/ccs/tools/compiler/ti-cgt-msp430_18.12.3.LTS/bin/cl430" -vmspx --data_model=large -Ooff --opt_for_speed=4 --use_hw_mpy=none --include_path="C:/MyFolder/Project/source/types" --include_path="C:/MyFolder/Project/source/SCDF" --include_path="C:/MyFolder/Project" --advice:power="all" --define=PBA_V1 --define=__MSP430F5438A__ --undefine=EVB -g --c89 --float_operations_allowed=none --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --gen_data_subsections=on --enum_type=packed --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU23 --silicon_errata=CPU40 --auto_inline=0 -k --asm_listing --preproc_with_compile --preproc_dependency="source/SCDF/$(basename $(<F)).d_raw" --obj_directory="source/SCDF" $(GEN_OPTS__FLAG) "$<"
@echo 'Finished building: "$<"'
@echo ' '

thanks,

Ashish

  • I'm pretty sure there's no way to do this, since the linker doesn't know what order you declared them in.

    If you need variables to be grouped together, put them in a struct-ure.

  • So there is no option like #pragma GCC optimize ("O0") , which can turn off the optimization for the file to ensure the data is declared in the order specified 

    Thanks,

    Ashish

  • It's the linker that decides where global variables end up.

    I can't tell you there's no such option, since I don't maintain the compiler. It seems (to me) like a very expensive feature which would provide very little benefit, since C provides a capability to force variables to be grouped.

    If you want, you can wait to see if one of the compiler people has a comment. Is there a reason you can't use a struct?

  • By default the linker appears to order variables to avoid holes due to padding.

    By default the TI compiler places global variables in their own subsection (the default for the --gen_data_subsections option is on).

    It is possible to use a GROUP in the linker command file to specify the order in which global variables are placed, by specifying the subsection names for the global variables.

    E.g. in the attached example project there are the following global variables in the C source code:

    uint32_t crc;
    
    uint8_t version[9];
    
    bool flag1;
    
    bool flag2;
    
    bool flag3;
    
    int32_t var1[2];
    
    int32_t var2;
    
    uint32_t var3;

    Which since are uninitialised get placed in .bss:.common:<var_name> sections.

    The following was added to the SECTIONS in the linker command file to control the order of allocation:

        GROUP
        {
        	/* Specify the order the global variables are to be placed */
        	.bss : {
        		*(.bss:.common:crc)
        	        *(.bss:.common:version)
        	        *(.bss:.common:flag1)
        	        *(.bss:.common:flag2)
        	        *(.bss:.common:flag3)
        	        *(.bss:.common:var1)
        	        *(.bss:.common:var2)
        	        *(.bss:.common:var3)
        	        }
        } > RAM

    And the linker map file showed the order has been respected, including a one byte hole to meet the alignment requirements:

     output                                  attributes/
    section   page    origin      length       input sections
    --------  ----  ----------  ----------   ----------------
    .bss       0    00001c00    00000022     UNINITIALIZED
                      00001c00    00000004     (.common:crc)
                      00001c04    0000000a     (.common:version)
                      00001c0e    00000001     (.common:flag1)
                      00001c0f    00000001     (.common:flag2)
                      00001c10    00000001     (.common:flag3)
                      00001c11    00000001     --HOLE--
                      00001c12    00000008     (.common:var1)
                      00001c1a    00000004     (.common:var2)
                      00001c1e    00000004     (.common:var3)

    See TI Linker Command File Primer for some background information.

    MSP430F5438A_linker_variable_order.zip

  • I tried the above method as suggested. It didn't workout. 

    Basically i'm trying to generate a bin file which will be loaded to controller as a separate image based on the configuration required. So for that i create a separate project to generate the file which have only initialized data. 

    Here is what i did:

    content of source file

    #include "file.h"

    extern const Uint32 LINKER__CRC_VALUE;
    /* Address of the CRC */
    const Uint32* const crc_loc = &LINKER__CRC_VALUE;
    const Uint8 version[19U] = {"version.1.1.1.1.1.0"};
    const Uint32 number = 4000UL;
    const Bool value = false;
    const Bool fault = true;
    const Int32 feet = 2000L;
    const Uint32 press = 40UL;
    const Uint32 rpm = 40UL;
    const Uint32 rpm2 = 408UL;

    const Uint32 gain[3U] = { 0UL, 820UL, 904UL};
    const Uint32 constants[3U] = {83UL, 89UL, 89UL};
    const Int32 gain2 = 678L;
    const Int32 gain3 = 122L;

    Contented of header file

    #include "types.h"

    /* Address of the CRC */
    const Uint32* const crc_loc;
    const Uint8 version[19U];
    const Uint32 number;
    const Bool value;
    const Bool fault;
    const Int32 feet;
    const Uint32 press;
    const Uint32 rpm;
    const Uint32 rpm2;
    const Uint32 gain[3U];
    const Uint32 constants[3U];
    const Int32 gain2;
    const Int32 gain3;

    Content of Linker file:

    SECTIONS
    {
        GROUP
        {
            .header : {
            *(.const:crc_loc)
                *(.const:.string:version)
                *(.const:number)
                *(.const:value)
                *(.const:fault)
                *(.const:feet)
                *(.const:press)
                *(.const:rpm)
                *(.const:rpm2)
                *(.const:gain)
                *(.const:constants)
                *(.const:gain2)
                *(.const:gain3)
                LINKER__CRC_VALUE = .;
                }
        } > HEADER_FLASH

    After compiling, it generate following linker warnings for most of the variable.

    "#10068-D no matching section"

    After looking at the map file, i found that linker is still generating the variable in random order and clubbing them to fill the memory in alignment.

    ******************************************************************************
                      MSP430 Linker PC v18.12.3                    
    ******************************************************************************
    >> Linked Mon May 11 00:15:54 2020
    OUTPUT FILE NAME:   <variable_order_test.out>
    ENTRY POINT SYMBOL: 0
    MEMORY CONFIGURATION
             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      SFR                   00000000   00000010  00000000  00000010  RWIX
      PERIPHERALS_8BIT      00000010   000000f0  00000022  000000ce  RWIX
      PERIPHERALS_16BIT     00000100   00000100  00000000  00000100  RWIX
      INFOD                 00001800   00000080  00000000  00000080  RWIX
      INFOC                 00001880   00000080  00000000  00000080  RWIX
      INFOB                 00001900   00000080  00000000  00000080  RWIX
      INFOA                 00001980   00000080  00000000  00000080  RWIX
      RAM                   00001c00   00004000  00000000  00004000  RWIX
      CRCSEC                00005c00   00000010  00000000  00000010  RWIX
      FLASH                 00005c10   0000a370  00000000  0000a370  RWIX
      RESET                 0000fffe   00000002  00000000  00000002  RWIX
      FLASH2                00010000   0002b000  00000000  0002b000  RWIX
      NVM                   0003b000   00002800  00000000  00002800  RWIX
      HEADER_FLASH          0003d800   00002800  0000002c  000027d4  RWIX
      P1TABLE               00040000   00005c00  00000000  00005c00  RWIX
    SECTION ALLOCATION MAP
     output                                  attributes/
    section   page    origin      length       input sections
    --------  ----  ----------  ----------   ----------------
    .bss       0    00001c00    00000000     UNINITIALIZED
    .header    0    0003d800    0000002c     
                      0003d800    00000013     main.obj (.const:.string:version)
                      0003d813    00000001     --HOLE-- [fill = 0]
                      0003d814    0000000c     main.obj (.const:gain)
                      0003d820    0000000c     main.obj (.const:constants)
    .const     0    00000010    00000022     
                      00000010    00000022     main.obj (.const)
    .text      0    00005c10    00000000     
    MODULE SUMMARY
           Module         code   ro data   rw data
           ------         ----   -------   -------
        .\
           main.obj       0      77        0      
        +--+--------------+------+---------+---------+
           Total:         0      77        0      
                                                  
        +--+--------------+------+---------+---------+
           Grand Total:   0      77        0      
    GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name 
    address   name                
    -------   ----                
    00001c00  LINKER__BSS_END     
    00001c00  LINKER__BSS_START   
    0003d82c  LINKER__CRC_VALUE   
    ffffffff  __TI_pprof_out_hndl 
    ffffffff  __TI_prof_data_size 
    ffffffff  __TI_prof_data_start
    ffffffff  __c_args__          
    UNDEFED   _c_int00            
    0003d820  constants           
    00000010  crc_loc             
    00000019  fault               
    0000001a  feet                
    0003d814  gain                
    0000002a  gain2               
    0000002e  gain3               
    00000014  number              
    0000001e  press               
    00000022  rpm                 
    00000026  rpm2                
    00000018  value               
    0003d800  version             
    GLOBAL SYMBOLS: SORTED BY Symbol Address 
    address   name                
    -------   ----                
    00000010  crc_loc             
    00000014  number              
    00000018  value               
    00000019  fault               
    0000001a  feet                
    0000001e  press               
    00000022  rpm                 
    00000026  rpm2                
    0000002a  gain2               
    0000002e  gain3               
    00001c00  LINKER__BSS_END     
    00001c00  LINKER__BSS_START   
    0003d800  version             
    0003d814  gain                
    0003d820  constants           
    0003d82c  LINKER__CRC_VALUE   
    ffffffff  __TI_pprof_out_hndl 
    ffffffff  __TI_prof_data_size 
    ffffffff  __TI_prof_data_start
    ffffffff  __c_args__          
    UNDEFED   _c_int00            
    [21 symbols]
  • Ashish Mishra1 said:
    After compiling, it generate following linker warnings for most of the variable.

    I have realised that the issue is that in my original example the variables were all uninitialised, and so placed in .bss subsections. For the uninitialised variables the scalar and arrays were each placed in their own subsection by the compiler which allow the GROUP 'trick' in the linker command file to work.

    However, with your variables which are const, then the behaviour of the compiler is different in that:

    1. The arrays are placed in their own .const subsections.
    2. However, the scalar variables are not placed in their own subsections, which leads to the linker "#10068-D no matching section" warnings, and the linker command file being unable to control their order.

    The same behaviour was seen with v18.12.5 and v20.2.1 compiler versions.

    Therefore, my suggestion won't work.

    As Bruce has already commented on, is there a reason why you can't use a struct to control the order in memory?

  • SInce this file will be used by multiple stakeholders, test team etc. i need to be consistent with them. As they have already developed the tools and scripts, it will require lot of changes for everyone. So willing to avoid that path.

    Thanks,

    Ashish

  • I recommend you define these variables in a hand-coded assembly file.  Then you have complete control over the order.  It is not as hard as it first sounds.  Please see this post for the details.  Though you want to use the assembler directives documented in the MSP430 assembly tools manual.

    Thanks and regards,

    -George

**Attention** This is a public forum