cmsp430

In C, will a compiler allow me to alter variables if they won't be used anymore?


I am converting this ATmega328 code for use on the Texas Instruments MSP430FR5994. It sets registers in HW via I2C. It isn't working (HW isn't behaving as I expect). I got the code from here: https://www.qrp-labs.com/synth/si5351ademo.html I don't know if this code works (I don't expect anyone to debug it for me). I have modified it slightly for the TI MCU. I am using Code Composer Studio v9.

Stepping through this code, the variable frequency is altered after the second time it is used (marked in code with ***). It isn't used after this so it shouldn't hurt anything. But I have never seen a compiler do this before.

Is it normal for a variable to be altered if it won't be used anymore? Or is this a symptom of a weird problem that could be causing other issues?

// Set CLK0 output ON and to the specified frequency
// Frequency is in the range 1MHz to 150MHz
// Example: si5351aSetFrequency(10000000);
// will set output CLK0 to 10MHz
//
// This example sets up PLL A
// and MultiSynth 0
// and produces the output on CLK0
//
void si5351aSetFrequency( uint32_t frequency )
{
    uint32_t pllFreq;
    uint32_t xtalFreq = XTAL_FREQ;
    uint32_t l;
    float f;
    uint8_t mult;
    uint32_t num;
    uint32_t denom;
    uint32_t divider;


    divider = 900000000 / frequency;// Calculate the division ratio. 900,000,000 is the maximum internal
                                    // PLL frequency: 900MHz
    if (divider % 2) divider--;     // Ensure an even integer division ratio

    pllFreq = divider * frequency;  // ***Calculate the pllFrequency: the divider * desired output frequency

    mult = pllFreq / xtalFreq;      // Determine the multiplier to get to the required pllFrequency
    l = pllFreq % xtalFreq;         // It has three parts:
    f = l;                          // mult is an integer that must be in the range 15..90
    f *= 1048575;                   // num and denom are the fractional parts, the numerator and denominator
    f /= xtalFreq;                  // each is 20 bits (range 0..1048575)
    num = f;                        // the actual multiplier is  mult + num / denom
    denom = 1048575;                // For simplicity we set the denominator to the maximum 1048575

                                    // Set up PLL A with the calculated multiplication ratio
    setupPLL( SI_SYNTH_PLL_A, mult, num, denom );

                                    // Set up MultiSynth divider 0, with the calculated divider.
                                    // The final R division stage can divide by a power of two, from 1..128.
                                    // represented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file)
                                    // If you want to output frequencies below 1MHz, you have to use the
                                    // final R division stage
    setupMultisynth( SI_SYNTH_MS_0, divider, SI_R_DIV_1 );

                                    // Reset the PLL. This causes a glitch in the output. For small changes to
                                    // the parameters, you don't need to reset the PLL, and there is no glitch
    WriteClockGenReg( SI_PLL_RESET, 0xA0 );

                                    // Finally switch on the CLK0 output (0x4F)
                                    // and set the MultiSynth0 input to be PLL A
    WriteClockGenReg( SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A );

}

Edit: Based on comments, I checked the variable locations. Part of the register is reused. enter image description here


Solution

  • Stepping through this code, the variable frequency is altered after the second time it is used (marked in code with ***). It isn't used after this so it shouldn't hurt anything. But I have never seen a compiler do this before.

    If the code is compiled for optimisation, the compiler could potentially re-use the same register / stack location for different variables. It's been a while since I have debugged TI MCUs, but from memory recall that the Code Composer Studio debugger shows the location of variables. The relocation may be either a register (when register optimisations are enabled) or the address on the stack.

    The Debug versus Optimization Tradeoff on the TI site lists how optimisation may impact the debug process. E.g.:

    Ease of debugging is characterized by things such as:

    • Do the values in the variables correspond to what is expected at that point in execution? Or something else?

    If one register is re-used for multiple variables, then when stepping the value of a variable may appear to change unexpectedly when the register gets re-used to hold a different variable.

    This is a valid optimisation if it doesn't affect the correct behaviour of the program.