Ich habe ein Problem mit der Optimierung des XC32-Compilers. Immer wenn ich eine Funktion schreibe, um etwas aus dem Register zu lesen, optimiert (sprich: Entfernt) XC32 die Variable, die den Rückgabewert enthält.
Ich habe eine Wrapper-Funktion, die einen bestimmten Pin eines bestimmten Ports liest:
uint8_t u8INT_DIO_ReadRangeSelect(void)
{
uint8_t u8pinstatus = 0;
// Read pin assigned to Range Select input
u8pinstatus = (uint8_t) SYS_PORTS_PinRead(PORTS_ID_0,
RANGE_SELECT_PORT, RANGE_SELECT_PIN);
return u8pinstatus;
}
Hier SYS_PORTS_PinRead
ist ein von Harmony (PICs Codegenerierungstool) generierter Code, der nur den Port-Pin liest. Code dafür ist:
return( _SFR_BIT_READ( _PORTS_READ_B_VREG(index) + ((channel-1) * 0x40), bitPos ) );
Beachten Sie, dass es sich um eine Inline-Funktion handelt.
Wenn ich jetzt die Optimierungsstufe auf 1 setze, entfernt XC32 u8pinstatus
die Variable und gibt immer 0 zurück.
u8pinstatus
Aber wenn ich als deklariere volatile
, funktioniert alles gut (was erwartet wurde).
Aber dann muss ich alle Variablen als flüchtig deklarieren, weil alle meine Wrapper-Funktionen immer 0 zurückgeben. Das ist kein guter Weg.
Ist der XC32 durchgeknallt oder mache ich etwas falsch?
Zusätzliche Information:
Assemblercode mit Optimierung :
!uint8_t u8INT_DIO_ReadRangeSelect(void)
!{
0x9D00AA8C: ADDIU SP, SP, -24
0x9D00AA90: SW RA, 20(SP)
! uint8_t u8pinstatus = 0;
!
! // Read pin assigned to Range Select input
! u8pinstatus = (uint8_t) SYS_PORTS_PinRead(PORTS_ID_0,
0x9D00AA94: ADDU A0, ZERO, ZERO
0x9D00AA98: ADDIU A1, ZERO, 3
0x9D00AA9C: JAL SYS_PORTS_PinRead
0x9D00AAA0: ADDIU A2, ZERO, 8
! RANGE_SELECT_PORT, RANGE_SELECT_PIN);
! return u8pinstatus;
!}
0x9D00AAA4: LW RA, 20(SP)
0x9D00AAA8: JR RA
0x9D00AAAC: ADDIU SP, SP, 24
Assemblercode ohne Optimierung :
!uint8_t u8INT_DIO_ReadRangeSelect(void)
!{
0x9D00F998: ADDIU SP, SP, -32
0x9D00F99C: SW RA, 28(SP)
0x9D00F9A0: SW S8, 24(SP)
0x9D00F9A4: ADDU S8, SP, ZERO
! uint8_t u8pinstatus = 0;
0x9D00F9A8: SB ZERO, 16(S8)
!
! // Read pin assigned to Range Select input
! u8pinstatus = (uint8_t) SYS_PORTS_PinRead(PORTS_ID_0,
0x9D00F9AC: ADDU A0, ZERO, ZERO
0x9D00F9B0: ADDIU A1, ZERO, 3
0x9D00F9B4: ADDIU A2, ZERO, 8
0x9D00F9B8: JAL SYS_PORTS_PinRead
0x9D00F9BC: NOP
0x9D00F9C0: SB V0, 16(S8)
! RANGE_SELECT_PORT, RANGE_SELECT_PIN);
! return u8pinstatus;
0x9D00F9C4: LBU V0, 16(S8)
!}
0x9D00F9C8: ADDU SP, S8, ZERO
0x9D00F9CC: LW RA, 28(SP)
0x9D00F9D0: LW S8, 24(SP)
0x9D00F9D4: ADDIU SP, SP, 32
0x9D00F9D8: JR RA
0x9D00F9DC: NOP
Compiler-Optimierungen gehen normalerweise davon aus, dass nichts als das Programm selbst den Inhalt des Speichers ändern kann. Mit dieser Annahme werden wiederholte Lesevorgänge aus demselben Register auf einem Mikrocontroller oft optimiert, da der Compiler im Code nichts sieht, was bei wiederholter Ausführung möglicherweise zu einem anderen Ergebnis führen kann. Warum immer wieder dieselben Anweisungen ausführen, wenn das Ergebnis immer dasselbe ist?
Volatile ist die Problemumgehung. Es sagt dem Compiler, dass etwas anderes im Universum diese bestimmte Adresse im Speicher ändern könnte und dass seine Annahmen über zukünftige Werte nicht unbedingt wahr sind. "Optimiere mich nicht, Bruder".
Kurz gesagt, ich denke, die Dinge verhalten sich genau wie beabsichtigt.
u8pinstatus
da er nicht verwendet wird.SYS_PORTS_PinRead
.
Schwanand
Bence Kaulics
Daniel
Löffel