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.
I have come across a possible issue when using the optimizer when assigning the result of the _swap_bytes intrinsic to a volatile variable as follows:
I am using compiler version TI 4.1.0 (CCS v5.2), targeting the MSP430F5438A device.
I am using the _swap_bytes intrinsic to reverse the byte order of a value, and write the result to a volatile variable, i.e. volatileVar = _swap_bytes(word);
When optimization is enabled (any level >0), the compiler generates assembly that writes 'word' to the volatile variable, and then performs the byte swap instruction directly on the volatile variable. This results in an intermediate value being written to the volatile before the desired value. As I understand it, this is not a valid thing for the compiler to do with a volatile variable.
Here is an example of how this behaviour can result in incorrect code execution. The following program uses the hardware CRC generator of the MSP430F5438A to calculate the CRC of a value that is byte swapped. The hardware registers of the CRC generator are defined in <msp430.h> as volatile. The CRC is generated twice, once directly writing the result of the _byte_swap macro to the CRC generator, and once writing the result of the byte swap to an intermediate value (which is also volatile) before writing to the CRC generator.
With the optimizer set to level 0, the byte swap occurs before writing to the CRC generator, and two results are the same.
With the optimizer set to any other level, the issue described above occurs, which causes an intermediate value to be written to the CRC generator when getting result1 this generates an incorrect CRC. When getting result2 the byte swap occurs on the variable 'temp' and not the CRC register, resulting in the correct CRC.
#include <msp430.h>
#include <assert.h>
void main(void)
{
unsigned int result1, result2;
const unsigned int data = 0x1234;
volatile unsigned int temp;
// Do a crc of the data
CRCINIRES = 0;
CRCDIRB = _swap_bytes(data);
result1 = CRCINIRES;
// Do a crc of the data with a forced intermediate step after byteswap
CRCINIRES = 0;
temp = _swap_bytes(data);
CRCDIRB = temp;
result2 = CRCINIRES;
// The results should be the same
assert(result1 == result2);
return;
}
I build the above code using an empty example project in CCS. What do you think? Have I missed somthing?
There may be another unrelated issue in the project compilier settings of CCS5.2. The options given in the GUI for optimizer level are 'Off', the numbers 0 to 4, or leaving the value blank. Leaving the value blank or at 0 results in the above code operating normally, however setting the optimizer to 'Off' causes the issue. This implies that the behaviour of 'Off' is *not* the same as optimizer level 0...
Thanks, Terry.
I cannot reproduce this problem. Could you please show me the assembly code you're getting?
Thanks for your reply. I've repeated my testing and it appears I was mistaken on some of the details with this issue. Apologies for any time this has wasted.
The problem does not occur for any of the optimization levels 0 to 4 (-O0 ... -O4). However, it does occur when the optimisation level in the CCS project settings is set to 'off'. This settings appears in the drop down list:
Project Properties>CCS Build>MSP430 Compiler>Optimization>Optimization level.
This results in a compiler argument of '-Ooff' being used. Looking through the compiler user guide, it does not mention the argument 'off' for the -O option, so I am not sure what effect it has. The argument 'off' implies to me that there would be no optimization (and is the reason I had originally selected it), but its use results in the generation of code that has the issue described in my first post.
This is a bug; this is now SDSCM00044781. Using optimization is not a guaranteed workaround, so you'll need to check all occurrences of SWPB in the assembly code until this bug is fixed.
Thanks for confirming. I will implement a workaround to avoid using the _swap_bytes intrinsic for the time being.