XC32 optimiert die für das Lesen von Registern verwendeten Variablen

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_PinReadist 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 u8pinstatusdie Variable und gibt immer 0 zurück.

u8pinstatusAber 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
@Bence Dies ist nur eine Beispielfunktion, die ich aufstelle ... Wenn ich einige Registerinformationen lesen und verarbeiten möchte, wird die Variable, die den SFR-Wert enthält, zu Null und die gesamte Verarbeitung geht schief
Hmm ... Dann sollten Sie vielleicht einen Parameter übergeben, um den Registerwert darin zu speichern, anstatt eine lokale Variable zurückzugeben.
Nun, das klingt ziemlich eindeutig nach einem Compiler-Bug. Stellen Sie sicher, dass Ihre Entwicklungsumgebung auf dem neuesten Stand ist. Sehen Sie, ob Sie ein Downgrade durchführen können, wenn es so kritisch ist. Sie sollten Microchip mit einem klaren Codebeispiel kontaktieren, das den angezeigten Fehler verursacht, mit einem Hinweis, der das erwartete Verhalten zeigt und zeigt, dass es sich auf Optimierungsstufe 0 anders verhält. Bis sie antworten, Sie kann hängen bleiben, wenn alle lokalen Registerdatenhalter als flüchtig deklariert werden. Eine andere Option könnte das Schlüsselwort 'register' für wirklich einfache Dinge wie diese sein.
Ist das Stichwort „volatile“ hier wichtig? Ich sehe es in dem Code, der verwendet wird, um die ganze Zeit auf Register zuzugreifen. Etwas über das Verhindern, dass der Compiler die Leseanweisung optimiert.

Antworten (1)

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.

+1 und der Compiler könnte immer noch optimieren, u8pinstatusda er nicht verwendet wird.
@David Warum darf der Compiler u8pinstatus wegoptimieren?
@David Ich gebe diese Variable zurück, wie kann sie nicht verwendet werden?
@Swanand @le_top, da es nur zum vorübergehenden Speichern und Zurückgeben des Werts von einer Inline-Funktion verwendet wird. Es hat keinen anderen Zweck und kann daher wegoptimiert werden, um lokalen Stack-Platz (oder eine Registerzuordnung) zu sparen. Ein guter optimierender Compiler würde diesen ganzen Funktionsaufruf auf den Inhalt von inline reduzieren SYS_PORTS_PinRead.