Hello everyone,
I am currently having an issue with some code I have that seems to vary based on optimization:
In CommBuff ISR:
if (commData == 0x61) /* 0x61 = 'a' */ { if(DAC1DifVoltn==1) { DigPressure1 = DiffPressure1; // Enters this section, problem here } else { DigPressure1 = Pressure1>>3; } COMBUF = DigPressure1>>8; } else if (commData == 0x62) /* 0x62 = 'b' */ { COMBUF = DigPressure1; }
Currently, DAC1DifVoltn is set to 1. When the COMBUF register gets a 0x61, it updates DigPressure1 and puts out the MSB on the COMBUF. When it receives 0x62, it sends out the LSB bits.
The problem I'm having is with the line:
DigPressure1 = DiffPressure1;
DiffPressure1 is set to 0x0FF8. When optimization is set to 4-8, DigPressure1 is set to 0x0097. When it's set to 3, it gets 0x0F97. When it's set to 2-0, it gets the correct value (0x0FF8). Realistically, this has to do with the way my code is written rather than it being an assembly issue but I can't seem to see a better way to handle this.
Does anyone have any explanations as to what I can do? If you need me to post the assembly code, I can do that as well. Any help would be appreciated. Thanks!
My only objection to that is when I am testing this code, I am hardcoding values into those variables and still having the issue. I think you might still be right about me having a potential issue with atomicity but I think I might still have some other issue directly related to storing DiffPressure1 into DigPressure1. Or could that still be an atomicity issue, even with hardcoded values?
I think it is an atomicity issue that show up when the timing changes due to optimization.
Erik
Here is a screenshot of the assembly code being executed:
imgh.us/DiffAssemblyCode.jpg
As far as your other questions go, I will admit, I don't know how to answer your questions regarding atomic operations or my stack (though, to be fair, I haven't had this issue in any other variable storage location, even when I try and shift a variable by 3 spaces and then place it into a variable, as shown in my else statement (which appears to work correctly).
Regarding variables and interrupts, I have a pressure value that is updated in an ISR, which is then processed by a separate function and stored into Pressure1. Thus far, I haven't had any issues related to Pressure1.
DiffPressure is created by subtracting Pressure1 from Pressure2 and then processed to calculate the desired differential voltage. It is then stored in DiffPressure1 (though I am currently working with a saturated differential channel, hence the 0x0FF8). I haven't used any volatile functions at this point as I haven't needed them. Not sure if this error is a result of this but I can step through everything and all the values are correct and the program steps through without any issues but that line I mentioned in a previous post is causing an issue when trying to store 1 unsigned int into another (it didn't have any problems when I tried to store Pressure1>>3 into this same DigPressure1 so I'm guessing the issue is with the DiffPressure1 variable. Except it has the correct value, it's just unable to store it into DigPressure1 correctly, which is just odd.
It's kind of frustrating because storing one variable into another seems to be about as easy as it gets (especially when compared to the complexity of my current code). Maybe it's a really simple solution but, unfortunately, I can't see it yet.
Thanks for your help, Per!
You use an 8-bit processor. But your variables are larger than 8 bits. So how do you perform atomic operations on them? Are any of the variables volatile or getting updated by an interrupt handler?
Have you made sure you have room enough for your stack?
Yes, I do get incorrect values on the serial port. That's what actually alerted me of this issue.
Interestingly enough, when I go into the loops that just right shift pressure1 by 3 places, I don't seem to have these issues (which definitely points to an issue with this section. I just don't understand what would cause it to store incorrect data here. Could the issue be because DigPressure1 is an idata register or something odd like that?). In fact, I more or less get garbage code rather than a consistent output, from what I can see (it takes a new sample every 4ms or so, so it's giving me new data faster than I'm requesting it).
The whole situation is very odd, since it seems to only affect one branch.
It can be dangerous to try to look at variable values at high optimization levels, since the compiler can switch execution sequence and throw away actions without side effects. And same memory/register can represent one variable in one part of the code, and another variable at a different point in the code.
Do you get wrong values actually sent out on the serial port?
Per,
Thank you for your reply. The Pressure1, DiffPressure1, and DigPressure1 are all unsigned shorts(though it should be noted, there are currently being stored in the idata section, not sure if that is causing issues). Here is the code below:
unsigned short idata Pressure1 = 0; unsigned short idata DigPressure1 = 0; unsigned short idata DiffPressure1 = 0;
The reason I'm using 0x61 is because the program we are interfacing with has to be entered in hex form (hence the 0x61), though you are correct. I could use the 'a' and place the 0x61 in the comment section.
The value of Pressure1 is zero (as that section of my code is not processed if DAC1DifVoltn is equal to one (which it is, it's initialized in an init function at the beginning of the program). I have been simulating and placing breakpoints in each location, which is how I know I'm getting different values based on the optimization level.
If I'm doing something incorrectly or you have an alternate suggestion, please let me know. Thanks!
Where are your data types?
And what was the value of Pressure1?
How do you know the code doesn't select the 'else' part?
By the way - why write:
if (commData == 0x61) /* 0x61 = 'a' */
instead of
if (commData == 'a')
Doesn't it feel strange to use a construct that forces you to have a comment to tell you the important information?
View all questions in Keil forum