I've been wresting with a couple of seriously painful bugs over the past 24 hours and I'm starting to think they are both related to this central issue.
I was previously compiling some code for the MSP430F6733 in CCS v5.5 with Register Optimization (level 0). When I turned optimization off, execution sometimes got stuck in a particular "for" loop:
int i=0;
for(i=0; i<=9; i++)
{
lcdmem[i] = ((mem[9-i] >> 4) & 0x0F) | ((mem[9-i] << 4) & 0xF0);
}
On closer examination with the debugger, I saw that the variable "i" was not being initialized to 0 at the beginning of the loop, instead taking the value of some large negative number. While single stepping through the disassembly, I discovered that a CLR.W instruction was not clearing both bytes of "i" (on the stack):
458 int i=0;
005222: 4381 0002 CLR.W 0x0002(SP)
459 for(i=0; i<=9; i++)
005226: 4381 0002 CLR.W 0x0002(SP)
00522a: 90B1 000A 0002 CMP.W #0x000a,0x0002(SP)
005230: 343E JGE ($C$L5)
461 lcdmem[i] = ((mem[9-i] >> 4) & 0x0F) | ((mem[9-i] << 4) & 0xF0);
$C$L1:
005232: 403F 0009 MOV.W #0x0009,R15
005236: 811F 0002 SUB.W 0x0002(SP),R15
Neither the instruction at 0x5222 nor the one at 0x5226 were actually clearing two bytes of stack - only the byte at SP+2 was cleared, with the byte at SP+3 remaining untouched.
When Register Optimization is re-enabled, the variable "i" is stored in a register instead of the stack and is cleared properly at the beginning of this loop.
My first thought was that the byte of RAM at SP+3 was malfunctioning and hence not getting updated properly. However I was able to change that byte with the debugger, and I also witnessed that byte being changed to other values by different parts of the code.
I would greatly appreciate some guidance on this issue, either as suggestions of the cause or suggestions on next debugging steps. I realize that these types of bugs are often user error rather than hardware issues, but at the moment I can't find any other explanation!