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_PinRead
hay 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 u8pinstatus
la variable y siempre devuelve 0.
Pero si declaro u8pinstatus
como 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
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.
u8pinstatus
ya que no se usa.SYS_PORTS_PinRead
.
Cisne y
Bence Kaulics
Daniel
Cuchara