¿Cómo puedo vincular una variable local al registro rXX de AVR?

2

Necesito tener una pausa programable con la mayor precisión posible. Para lograr esto tengo el siguiente código GCC:

void delay(unsigned char d){
  volatile unsigned char i=d;
  while(i>0) i--;
}

Que se compila para:

1cc:    89 81           ldd r24, Y+1    ; 0x01
1ce:    81 50           subi    r24, 0x01   ; 1
1d0:    89 83           std Y+1, r24    ; 0x01
1d2:    89 81           ldd r24, Y+1    ; 0x01
1d4:    81 11           cpse    r24, r1
1d6:    fa cf           rjmp    .-12        ; 0x1cc <__vector_1+0x2c>

(Estoy mostrando solo el código del núcleo del bucle). Esto lleva al hecho de que la precisión es de 7 ciclos, lo cual no es muy aceptable. Sin embargo, veo que el compilador hizo su trabajo no lo más rápido posible: si la variable i fuera un registro r24, guardaré 3 operaciones y el código sería casi el doble de rápido.

Entonces, ¿cómo puedo decirle al compilador que quiero que esta variable esté en un registro?

PS. Consideraría hacer una pausa con el número programable en nop 's. Pero no puedo imaginar cómo se puede lograr esto. AVR no tiene instrucciones para derivar a la dirección calculada. Por lo que sé, no se puede acceder directamente a la pila en el AVR (si pudiera enviar el valor necesario a la pila y ejecutar la instrucción ret para saltar a la dirección del programa necesaria, también es un trabajo difícil, pero al menos sería considerable).

ACTUALIZACIÓN Después de cambiar la palabra clave de volatile a register (como se describe en una de las respuestas), tengo el siguiente código:

 14e:   81 50           subi    r24, 0x01   ; 1
 150:   f1 f7           brne    .-4         ; 0x14e <__vector_6+0x1c>

Así que reduje el ciclo de 7 a 2 ciclos. Lo cual es mucho mejor de lo que podía esperar.

    
pregunta Roman Matveev

2 respuestas

5

No declare su variable como volatile . Eso obliga al compilador a usar una ubicación de memoria y acceder a ella en cada iteración de bucle. Utilice register en su lugar.

    
respondido por el Dave Tweed
5

La forma convencional de lograr lo que desea es codificar manualmente la subrutina de retardo en el lenguaje ensamblador nativo. Casi todos los conjuntos de herramientas de desarrollo que son compiladores de C tendrán la capacidad de incluir módulos de lenguaje ensamblador en la compilación.

Un truco común usado por programadores experimentados es construir primero la rutina de retardo en código C, como lo ha hecho. Luego, al mirar el código de máquina compilado, obtiene una plantilla de cómo escribir la misma rutina en el código del ensamblador y luego le permite optimizar las secciones críticas. La ventaja de este enfoque es que el compilador "muestra cómo" configurar la entrada y la salida a / desde la subrutina para que sea compatible con el código C principal.

    
respondido por el Michael Karas

Lea otras preguntas en las etiquetas