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.

MSP430G2553: GCC vs TLV data

Part Number: MSP430G2553

GCC has started warning about array access out of bounds when it shouldn't. It appears that the compiler writers are trying very hard to warn against this problem but it is messing things up. I upgraded from the 9.2 distribution to 9.3 but the results were the same. My problem is with this code:

/*
  Compute a checksum on the TLV data area and compare it to the value
  stored there. If they match, return true. Checked before using
  the ADC calibration data and DCO settings stored there.
 */
int tlv_good(void)
{
  int *p, chk, i;

  chk = 0;
  p = (int *)(&TLV_CHECKSUM + 1);
  for(i = 0; i < 31; i++)
    chk ^= *p++;

  chk += TLV_CHECKSUM;
  return ~chk;
}


/*
  Use factory calibration data to correct ADC readings.

  Starts with filtered Q4 fixed point numbers but just throws away the
  fractional bits.

  Remembers if the TLV structure checksum has checked out previously.
 */

uint16_t corrected(int val)
{

  int32_t tmp;
  static int *p = 0;

  if(p || tlv_good())
    {
      p = (int *)&TLV_ADC10_1_TAG;
      tmp = val >> 3;
      tmp *= *(p + CAL_ADC_25VREF_FACTOR/2);
      tmp >>= 16;      
      tmp *= *(p+CAL_ADC_GAIN_FACTOR/2);
      tmp >>= 16;
      tmp += *(p+CAL_ADC_OFFSET/2);
      return tmp;
    }
  else 
    return val >> 4;
  
}

The first function (tlv_good()) is fine but the second results in several warnings:

beeper.c: In function 'corrected':
beeper.c:86:14: warning: array subscript 6 is outside array bounds of 'volatile unsigned char[1]' [-Warray-bounds]
   86 |       tmp *= *(p + CAL_ADC_25VREF_FACTOR/2);
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/ti/gcc/include/msp430g2553.h:65,
                 from /usr/ti/gcc/include/msp430.h:1423,
                 from beeper.c:1:
/usr/ti/gcc/include/msp430g2553.h:904:1: note: while referencing 'TLV_ADC10_1_TAG'
  904 | sfr_b(TLV_ADC10_1_TAG);                       /* TLV ADC10_1 TAG */
      | ^~~~~

Notice how even though I am using a pointer to an integer, the compiler is complaining about the source of the address I used and as an array of characters. It did not make any such complaint about the pointer references in tlv_good(). The only difference is in the size of the item referenced. One is defined as a word (sfr_w) and the other as a char. (sfr_b) in the device header file.

Even worse is that when I look at the code it is beyond awful. In spite of my using a pointer to an integer, the compiler fetches the data one byte at a time. Doing a slow and painful eight bit shift on one byte before combining the bytes into an integer.

The problem probably starts with these data structures stored in memory being tagged as special function registers in the device header file but the compiler propagating those attributes is causing the most trouble. Short of disabling the array bounds warning I have found no way around the warning. And no way to make it generate sane code.

  • Hello David,

    First thing I want to point out is that the MSP430G2553 does not have at the typical TLV structure like a lot of other MSP430 devices. It stores its calibration data in memory segment INFOA, so just make sure you are pointing in the correct section of memory.

    As for the warning, the size mismatch is most likely what is causing this as you are trying to work with a word (2 chars) into a character array of 1. 

  • It is almost like you didn't read what I wrote.

  • I tested a work around to this problem. It required moving the pointer declaration and assignment outside the function which is not where I wanted it. The pointer is used only within this one function so global scope is not required or recommended. But at least it killed the compiler warnings.

    It also eliminated the fetch integer as unaligned nonsense. (It wouldn't have been as awful if it used the SWPB instruction instead of eight shifts.)

    I can understand the compiler designers desire to try and cut down on array indexing problems but those have existed in C since the beginning and require diligence on the part of the programmer, not smarter compilers. If I want that smart of a compiler I will use something else.

  • For information I was able to re-create the issue using your example code, in CCS 11.1 by creating a project for a MSP430G2553 using the msp430-gcc-9.3.0.31 (Mitto Systems Limited) compiler installed with CCS.

    I have attached the project, not sure how to get a defect raised about the issue. There are two build configurations, which differ in the optimisation level.

    The warnings are sensitive to the optimisation level used. At O1 there are no warnings:

    **** Build of configuration GCC_O1 for project MSP430G2553_TLV ****
    
    /home/mr_halfword/ti/ccs1110/ccs/utils/bin/gmake -k -j 12 all -O 
     
    Building file: "../main.c"
    Invoking: GNU Compiler
    "/home/mr_halfword/ti/ccs1110/ccs/tools/compiler/msp430-gcc-9.3.0.31_linux64/bin/msp430-elf-gcc-9.3.0" -c -mmcu=msp430g2553 -mhwmult=none -I"/home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc" -I"/home/mr_halfword/E2E_example_projects/MSP430G2553_TLV" -I"/home/mr_halfword/ti/ccs1110/ccs/tools/compiler/msp430-gcc-9.3.0.31_linux64/msp430-elf/include" -O1 -g -gdwarf-3 -gstrict-dwarf -Wall --save-temps -MMD -MP -MF"main.d_raw" -MT"main.o"   -o"main.o" "../main.c"
    Finished building: "../main.c"
     
    Building target: "MSP430G2553_TLV.out"
    Invoking: GNU Linker
    "/home/mr_halfword/ti/ccs1110/ccs/tools/compiler/msp430-gcc-9.3.0.31_linux64/bin/msp430-elf-gcc-9.3.0" -mhwmult=none -O1 -g -gdwarf-3 -gstrict-dwarf -Wall --save-temps -mmcu=msp430g2553 -Wl,-Map,"MSP430G2553_TLV.map" -Wl,--gc-sections -L"/home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc" -mmcu=msp430g2553 -o"MSP430G2553_TLV.out" "./main.o" -T"../msp430g2553.ld"  -Wl,--start-group -lgcc -lc -Wl,--end-group 
    Finished building target: "MSP430G2553_TLV.out"
     
    
    **** Build Finished ****

    At O2 there are warnings:

    **** Build of configuration GCC_O2 for project MSP430G2553_TLV ****
    
    /home/mr_halfword/ti/ccs1110/ccs/utils/bin/gmake -k -j 12 all -O 
     
    Building file: "../main.c"
    Invoking: GNU Compiler
    "/home/mr_halfword/ti/ccs1110/ccs/tools/compiler/msp430-gcc-9.3.0.31_linux64/bin/msp430-elf-gcc-9.3.0" -c -mmcu=msp430g2553 -mhwmult=none -I"/home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc" -I"/home/mr_halfword/E2E_example_projects/MSP430G2553_TLV" -I"/home/mr_halfword/ti/ccs1110/ccs/tools/compiler/msp430-gcc-9.3.0.31_linux64/msp430-elf/include" -O2 -g -gdwarf-3 -gstrict-dwarf -Wall --save-temps -MMD -MP -MF"main.d_raw" -MT"main.o"   -o"main.o" "../main.c"
    ../main.c: In function 'corrected':
    ../main.c:42:16: warning: array subscript 6 is outside array bounds of 'volatile unsigned char[1]' [-Warray-bounds]
       42 |         tmp *= *(p + CAL_ADC_25VREF_FACTOR/2);
          |                ^~~~~~~~~~~~~~~~~
    In file included from /home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc/msp430.h:1423,
                     from ../main.c:1:
    /home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc/msp430g2553.h:904:31: note: while referencing 'TLV_ADC10_1_TAG'
      904 | sfr_b(TLV_ADC10_1_TAG);                       /* TLV ADC10_1 TAG */
          |                               ^~~~~~~~~~~~~~~
    ../main.c:44:16: warning: array subscript 1 is outside array bounds of 'volatile unsigned char[1]' [-Warray-bounds]
       44 |         tmp *= *(p+CAL_ADC_GAIN_FACTOR/2);
          |                ^~~~~~~~~~~~~~~
    In file included from /home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc/msp430.h:1423,
                     from ../main.c:1:
    /home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc/msp430g2553.h:904:31: note: while referencing 'TLV_ADC10_1_TAG'
      904 | sfr_b(TLV_ADC10_1_TAG);                       /* TLV ADC10_1 TAG */
          |                               ^~~~~~~~~~~~~~~
    ../main.c:46:16: warning: array subscript 2 is outside array bounds of 'volatile unsigned char[1]' [-Warray-bounds]
       46 |         tmp += *(p+CAL_ADC_OFFSET/2);
          |                ^~~~~~~~~~~~~~~
    In file included from /home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc/msp430.h:1423,
                     from ../main.c:1:
    /home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc/msp430g2553.h:904:31: note: while referencing 'TLV_ADC10_1_TAG'
      904 | sfr_b(TLV_ADC10_1_TAG);                       /* TLV ADC10_1 TAG */
          |                               ^~~~~~~~~~~~~~~
    Finished building: "../main.c"
     
    Building target: "MSP430G2553_TLV.out"
    Invoking: GNU Linker
    "/home/mr_halfword/ti/ccs1110/ccs/tools/compiler/msp430-gcc-9.3.0.31_linux64/bin/msp430-elf-gcc-9.3.0" -mhwmult=none -O2 -g -gdwarf-3 -gstrict-dwarf -Wall --save-temps -mmcu=msp430g2553 -Wl,-Map,"MSP430G2553_TLV.map" -Wl,--gc-sections -L"/home/mr_halfword/ti/ccs1110/ccs/ccs_base/msp430/include_gcc" -mmcu=msp430g2553 -o"MSP430G2553_TLV.out" "./main.o" -T"../msp430g2553.ld"  -Wl,--start-group -lgcc -lc -Wl,--end-group 
    Finished building target: "MSP430G2553_TLV.out"
     
    
    **** Build Finished ****
    

    Notice how even though I am using a pointer to an integer, the compiler is complaining about the source of the address I used and as an array of characters.

    For the attached example, the --save-temps option was used to get the compiler to save the generated assembler.

    Line 42 in the C source code is the following statement:

            tmp *= *(p + CAL_ADC_25VREF_FACTOR/2);

    In the GCC_O2/main.s file the following assembler is shown for line 42:

    .LVL6:
    	.loc 1 42 9 is_stmt 1
    	.loc 1 42 16 is_stmt 0
    	MOV.B	&TLV_ADC10_1_TAG+13, R13
    	RLA.W	R13
    	RLA.W	R13
    	RLA.W	R13
    	RLA.W	R13
    	RLA.W	R13
    	RLA.W	R13
    	RLA.W	R13
    	RLA.W	R13
    	MOV.B	&TLV_ADC10_1_TAG+12, R14
    	BIS.W	R14, R13
    	.loc 1 42 13
    	MOV.W	R12, R14 { BIT.W	#0x8000, R14 { SUBC.W	R15, R15 { INV.W	R15, R15
    .LVL7:
    	MOV.W	R13, R12 { BIT.W	#0x8000, R12 { SUBC.W	R13, R13 { INV.W	R13, R13
    	CALL	#__mspabi_mpyl
    .LVL8:
    	MOV.W	R13, R14
    

    While the source statement uses the p pointer, the compiler optimiser seems to have replaced the reference to the pointer with offsets from &TLV_ADC10_1_TAG. I think that explains why the compiler then emits warnings.

    MSP430G2553_TLV.zip

  • I tested a work around to this problem. It required moving the pointer declaration and assignment outside the function which is not where I wanted it. The pointer is used only within this one function so global scope is not required or recommended. But at least it killed the compiler warnings.

    A different work-around which removed the compiler warnings, at optimisation level 2, was to declare the p pointer volatile. I.e. by changing from:

        static int *p = 0;

    To:

        static int *volatile p = 0;

    It also eliminated the fetch integer as unaligned nonsense.

    The above work-around had the same effect.

    The generated code in GCC_O2/main.s for line 42 is now:

    .LVL6:
    	.loc 1 42 9 is_stmt 1
    	.loc 1 42 20 is_stmt 0
    	MOV.W	&p.1566, R13
    	.loc 1 42 13
    	MOV.W	R12, R14 { BIT.W	#0x8000, R14 { SUBC.W	R15, R15 { INV.W	R15, R15
    .LVL7:
    	MOV.W	12(R13), R13
    	MOV.W	R13, R12 { BIT.W	#0x8000, R12 { SUBC.W	R13, R13 { INV.W	R13, R13
    	CALL	#__mspabi_mpyl
    .LVL8:
    	MOV.W	R13, R14

    The project with the work-around is attached.

    2352.MSP430G2553_TLV.zip

**Attention** This is a public forum