Part Number: MSP430F1232
The GNU ld (Mitto Systems Limited - msp430-gcc 9.3.1.11) 2.34 compiler appears to generate incorrect assembly code that writes to the wrong memory address for the sluft_value_ member variable in certain conditional branches.
I have this simplified if construct. That produces the same result as the real implementation.
uint8_t AppVtux_Slave::dummyID() {
static uint32_t counter = 0;
uint8_t values[] = {0x03, 0x05};
uint8_t index = counter % 2;
counter++;
return values[index];
}
#pragma GCC push_options
#pragma GCC optimize("O0")
void AppVtux_Slave::SLuftDetection() {
valve_flash_.iot_cs_number_ = 1;
uint16_t tmp_ven_id = dummyID();
sluft_connected_ = 3;
if (tmp_ven_id == 5) {
sluft_connected_ = 1;
sluft_value_ = 0;
} else if (tmp_ven_id == 3) {
sluft_connected_ = 1;
sluft_value_ = 1;
}
SendUInt16(tmp_ven_id);
SendStringNoLen("|");
SendUInt16(sluft_connected_);
SendStringNoLen("|");
SendUInt16(sluft_value_);
SendStringNoLen("\n");
}
#pragma GCC pop_options
That depending on the ID sets two variables and then print the result. This is the variable definition in the class.
private:
uint16_t sluft_value_;
uint16_t sluft_connected_;
When I look at the print it does not look right.
Exprected:
When tmp_ven_id == 5: sluft_value_ should be set to 0
When tmp_ven_id == 3: sluft_value_ should be set to 1
Actual Behavior
he sluft_value_ member variable always reads as 1, regardless of which conditional branch executes.
ID | Connected | Value
00005 | 00001 | 00001 (expected: 00000)
00003 | 00001 | 00001 (expected: 00001)
00005 | 00001 | 00001 (expected: 00000)
00003 | 00001 | 00001 (expected: 00001)
When looking into the asembler code the problem is esily visible. The wirte of the 0 value in case 5 happen to another address then it is passed to the function that prints the value. I spend some time debuggign this, but can't find the real cause of this issue. Just a bunch of changes I can make to seemingly "solve" this issue.
// Option 1:
//add Dummy variable.
private:
uint16_t dummy = 0xFFFF;
uint16_t sluft_value_;
uint16_t sluft_connected_;
// Option 2:
//Change the else if to if
if (tmp_ven_id == 5) {
sluft_connected_ = 1;
sluft_value_ = 0;
}
if (tmp_ven_id == 3) {
sluft_connected_ = 1;
sluft_value_ = 1;
}
For option 1 the text size as expected increases by 2 and the code works. Chainging from "else if" to only "ifs" has no effect.
GNU ld (Mitto Systems Limited - msp430-gcc 9.3.1.11) 2.34
text data bss dec hex filename
29556 1338 1292 32186 7dba -> broken
29558 1338 1292 32188 7dbc ->working
29534 1340 1292 32166 7da6 -> if
29534 1340 1292 32166 7da6 -> else if
This is the resulting assembler code. Of the 3 differen implementations. In the broken example the mov 0 appears to a address that is far away.

I am using all options to reduce code size as well as ink-time optimization.
Compiler flags used: -g3 -Os -fno-rtti -fno-exceptions -std=gnu++11 -Wl, -mcpu=430 -mhwmult=16bit -mno-warn-mcu
Ihave the suspiccion that there is a bug in the memory alignment that causes this. I disabled the LTO and changed the size of the rom section in the .ld file and the assembler code still had the faulty adress.