¿Por qué pasar el puntero para registrarse como volátil?

1

Estoy trabajando en el aprendizaje de TDD embebido en C creando un controlador LED para un AVR. En el libro de James Grenning , recomienda inyectar el PUERTO pasando un puntero al registrarse en la función.

Encontré el siguiente código en la documentación de AvrLibc, ¿Cómo puedo pasar un puerto IO como parámetro a un function? , y estoy confundido en cuanto a por qué el parámetro *port se declara como volátil.

void
set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
{
    *port |= mask;
}

¿Alguien puede explicar por qué lo pasan como volátil? Como alguien que es un principiante con C, estoy confundido y agradecería una explicación (si la hay).

    
pregunta RubberDuck

2 respuestas

2

Se pasa como volátil para que el compilador no optimice los accesos a dicho parámetro. Esto es necesario porque un compilador puede ver algo como esto:

port = 1;
port = 2;
port = 3;

O tal vez

while (port & 0x01) ...

Suponiendo que el estado final es todo lo que importa, que se puede optimizar para

port = 3;

Y

some_cpu_register = port;
while (some_cpu_register & 0x01) ...

Guardar en instrucciones, accesos a memoria y espacio de código. Sin embargo, dado que port realmente accede a los recursos físicos, estas lecturas y escrituras son realmente significativas y se debe indicar al compilador que el programador sabe mejor aquí y que el compilador no debe eliminar ninguna lectura o escritura para que el programa realice las operaciones previstas.

    
respondido por el alex.forencich
-1
  

Estoy trabajando en el aprendizaje de TDD embebido en C creando un controlador LED para un AVR. En el libro de James Grenning, recomienda inyectar el PUERTO pasando un puntero al registro en la función.

Este no es un buen consejo, por cierto. Me inclino a ignorarlo.

La CPU AVR tiene un conjunto de instrucciones dedicadas ( IN y OUT ) que se pueden usar para escribir directamente en el espacio de E / S (direcciones entre 0x0020 y 0x005F), pero solo Si la dirección es conocida en tiempo de compilación. Por ejemplo, escribir un valor del registro r1 a PORTB se puede ensamblar en una sola instrucción, utilizando una palabra de espacio de programa:

out 0x05, r1     ; I/O address of PORTB

pero una llamada a través de una función como la que se muestra en su ejemplo debe reunirse en una secuencia de cinco palabras:

mov r22, r1
ldi r24, 0x25    ; low word of PORTB address
ldi r25, 0x00    ; high word of PORTB address
call set_bits_func_correct

Esto aumentará significativamente el tamaño de su programa en la memoria flash. Usar una función como esta también hace que los modismos comunes como PORTB |= 0x01 sean mucho más difíciles de escribir, sin ningún beneficio en el tiempo de ejecución.

    
respondido por el duskwuff

Lea otras preguntas en las etiquetas