AVR asm wait loop explica

2

¿Puede alguien explicarme este código (es de la calculadora de ciclo de espera)? No puedo entender claramente el cálculo.

; Retraso 1 600 000 ciclos ; 100 ms a 16 MHz

ldi  r18, 9       ;1 clock cycle
ldi  r19, 30      ;1 clock cycle
ldi  r20, 229     ;1 clock cycle
L1: dec  r20      ;1 clock cycle
brne L1           ;2 clock cycle
dec  r19          ;1 clock cycle
brne L1           ;2 clock cycle
dec  r18          ;1 clock cycle
brne L1           ;2 clock cycle
nop               ;1 clock cycle
    
pregunta hudy

1 respuesta

3

El código carga 9, 30 y 229 en los registros r18, r19 y r20, respectivamente. Luego decrementa estos registros en un triple bucle anidado. El bucle más exterior se ejecuta 9 veces. Dec, ldi y nop siempre toman 1 ciclo. brne toma 1 ciclo más un ciclo adicional cuando se ramifica. En la primera iteración del bucle externo, el bucle central se ejecuta 30 veces. En la primera iteración del bucle medio, el bucle interno se ejecuta 229 veces. Las instrucciones de decrementan los registros y luego las instrucciones de brne comparan el resultado con cero: cada bucle se ejecutará hasta que el registro asociado sea cero, momento en el que la ejecución del punto "fracasará" en la siguiente instrucción. Si el registro es cero al ingresar al bucle, dec hará que se ajuste a 255. Por lo tanto, la primera vez que se ejecuta un bucle, se ejecutará hasta que el contador sea cero. Esto produce 256 iteraciones cuando se inicia un bucle con 0 en el registro correspondiente.

Las instrucciones ldi y nop toman 4 ciclos en total. El bucle interno requiere 3 ciclos para cada iteración, excepto la última que requiere 2, por lo que la primera vez es de 229 * 3-1 ciclos y las iteraciones siguientes son 256 * 3-1 ciclos. Los otros bucles siguen la misma secuencia, agregando 3 ciclos para cada iteración, excepto la última. Si tiene en cuenta todos los bucles, obtendrá:

3 + 229 * 3-1 + 3 + (256 * 3-1 + 3) * 29-1 + 3 + ((256 * 3-1 + 3) * 256-1 + 3) * 8-1 +1 = 1600000

3 para las instrucciones de ldi, 229 * 3-1 para el primer bucle interno, 3 para la primera iteración del bucle medio, (256 * 3-1 + 3) * 29-1 para el resto del primer bucle medio, 3 para el primer bucle externo, ((256 * 3-1 + 3) * 256-1 + 3) * 8-1 para el resto del bucle externo, y 1 para el nop final.

Esa ecuación se puede reescribir como:

6 + 229 * 3 + 770 * (30-1) + 197122 * (9-1) +1

donde 229, 30, 9 y 1 corresponden a las 3 constantes y al número de instrucciones nop finales. Puede calcular las tres constantes de conteo de bucle trabajando hacia atrás de mayor a menor, luego agregando 0, 1 o 2 instrucciones nop para obtener el número exacto de ciclos.

Por ejemplo, volver a calcular para un retraso de 50 ms (800000 ciclos) funcionaría de la siguiente manera: 800000/197122 = 4, resto 11512. 11512/770 = 14, resto 732. 732/3 = 244, resto 0. Así que usaría las constantes 4 + 1 = 5, 14 + 1 = 15, 244-6 / 3 = 244-2 = 242 y agregaría cero instrucciones extra nop. Para comprobar, computar

6 + 242 * 3 + 770 * (15-1) + 197122 * (5-1) +0 = 800000

.

    
respondido por el alex.forencich

Lea otras preguntas en las etiquetas