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.
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.