XC32 optimiza la variable utilizada para la lectura de registros

Tengo un problema con la optimización del compilador XC32. Cada vez que escribo una función para leer algo del registro, XC32 optimiza (leer: elimina) la variable que contiene el valor de retorno.

Tengo una función contenedora que lee un pin particular de un puerto particular:

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;
}

Aquí SYS_PORTS_PinReadhay un código generado por armonía (herramienta de generación de código de PIC) y solo lee el pin del puerto. El código para eso es:

return( _SFR_BIT_READ( _PORTS_READ_B_VREG(index) + ((channel-1) * 0x40), bitPos ) );

Tenga en cuenta que es una función en línea.

Ahora, cuando configuro el nivel de optimización en 1, XC32 elimina u8pinstatusla variable y siempre devuelve 0.

Pero si declaro u8pinstatuscomo volatile, todo funciona bien (lo que se esperaba).

Pero luego necesito declarar todas las variables volátiles porque todas mis funciones contenedoras siempre devuelven 0. Esa no es una buena manera.

¿Es que XC32 se estropeó o estoy haciendo algo mal?

Información adicional:

Código ensamblador con optimización :

!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

Código ensamblador sin optimización :

!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 Esta es solo una función de ejemplo que estoy presentando ... Si quiero leer y procesar alguna información de registro, la variable que contiene el valor SFR se convierte en cero y todo el procesamiento sale mal
Hmm... Entonces tal vez debería pasar un parámetro para almacenar el valor del registro en lugar de devolver una variable local.
Bueno, esto claramente suena como un error del compilador. Asegúrese de que su entorno de desarrollo esté actualizado. Vea si puede degradar si es tan crítico. Debe ponerse en contacto con Microchip con un ejemplo claro del código que hace que se muestre el error, con una nota que muestre el comportamiento esperado y que muestre que se comporta de manera diferente en el nivel de optimización 0. Hasta que respondan, usted puede estar atascado declarando todos los titulares de datos del registro local como volátiles. Otra opción podría ser la palabra clave 'registrarse' para cosas realmente simples como esta.
¿Es importante aquí la palabra clave 'volátil'? Lo veo en el código que se usa para acceder a los registros todo el tiempo... algo sobre evitar que el compilador optimice la instrucción de lectura.

Respuestas (1)

Las optimizaciones del compilador generalmente asumen que nada más que el propio programa puede alterar el contenido de la memoria. Con esa suposición, las lecturas repetidas del mismo registro en un microcontrolador a menudo se optimizan, porque el compilador no ve nada en el código que pueda dar un resultado diferente con la ejecución repetida. ¿Por qué ejecutar las mismas instrucciones una y otra vez si el resultado siempre será el mismo?

Volátil es la solución. Le dice al compilador que algo más en el universo podría alterar esa dirección particular en la memoria, y que sus suposiciones sobre los valores futuros no son necesariamente ciertas. "No me optimices, hermano".

En resumen, creo que las cosas se están comportando exactamente como se esperaba.

+1 y el compilador aún sería libre de optimizar u8pinstatusya que no se usa.
@David ¿Por qué se le permite al compilador optimizar u8pinstatus?
@David, estoy devolviendo esa variable, ¿cómo puede no usarse?
@Swanand @le_top porque solo se usa para almacenar temporalmente y luego devolver el valor de una función en línea. No tiene otro propósito y, por lo tanto, se puede optimizar para ahorrar espacio de pila local (o una asignación de registro). Un buen compilador de optimización reduciría toda la llamada de función al contenido del archivo en línea SYS_PORTS_PinRead.