¿Cómo funciona __delay_cycles?

6

Estoy usando msp430g2553 y configurando el reloj a 1Mhz:

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

He cronometrado 5 millones de ciclos e inesperadamente toma alrededor de 6 segundos (esperaba 5). El bucle que he usado es:

int i;
for(i=0;i<5000;i++)
    __delay_cycles(1000);

He leído sobre el uso de interrupciones (probablemente basadas en Timer_A, etc.) pero me gustaría evitar eso por ahora.

Entonces mi pregunta es: ¿cómo puedo implementar un argumento constante sleep basado en __delay_cycles?

Edición posterior

Asamblea para:

void delay1000() {
        __delay_cycles(1000);
}

es:

delay1000:
    0c3b4: 04 12                     PUSH    R4
    0c3b6: 04 41                     MOV     SP,      R4
    0c3b8: 24 53                     INCD    R4
    0c3ba: 3f 40 4c 01               MOV     #0x014c, R15    // 332 decimal (1000/3 -> DEC, TST and JNZ)
    0c3be: 1f 83                     DEC     R15
    0c3c0: 0f 93                     TST     R15
    0c3c2: fd 23                     JNZ     delay1000+0xa
    0c3c4: 03 43                     NOP     
    0c3c6: 03 43                     NOP     
    0c3c8: 34 41                     POP     R4
    0c3ca: 30 41                     RET     
    
pregunta diciu

2 respuestas

7

Mire el desensamblaje del código, recuerde que el bucle for agrega algunas instrucciones que llevan unos pocos ciclos. Con un bucle 5000, estos ciclos adicionales se sumarán. Además, la forma en que se implementa delay_cycles() puede hacer una gran diferencia.
Puede contar los ciclos para cada bucle en el simulador, hacer los cálculos y compensar los ciclos agregados pasando el valor apropiado.

Por supuesto, la mejor manera de obtener una sincronización precisa es usar interrupciones, pero dices que quieres evitarlas por ahora.

    
respondido por el Oli Glaser
8

De la Guía del usuario de MSP430 Optimizing C / C ++ Compiler v 3.1 (SLAU132c.pdf) pp. 109:

  

El __delay_cycles intrínseco inserta código para consumir precisamente el número de ciclos especificados sin   efectos secundarios. El número de ciclos retrasados debe ser una constante de tiempo de compilación.

Es una función intrínseca, específicamente diseñada para usar ciclos. Debe ser bueno para al menos ese número de ciclos. Puedes cambiar 1000 a otra cosa (debe ser una constante, no puede ser una variable). Tanto el bucle for como la llamada de función aumentarán la demora.

Además:

  

sí, con el código habrá un pequeño error de "compensación" y "ganancia" en   el retraso real que obtiene. El código es bueno para garantizar una cierta   Retardo mínimo, con un error muy pequeño en la dirección positiva.   Es por eso que la demora dentro del bucle se eligió bastante grande ("ms").   Si necesita una demora, la mejor manera sería usar un temporizador. Pero   Si por alguna razón aún desea utilizar retrasos de SW, le recomendaría   codificar una función en un ensamblador en lugar de medir la función C.   Podría compensar en la propia función el "desplazamiento" y   Errores de "ganancia" de la sobrecarga de llamada y bucle. Además, nuestros IDEs tienen ciclo.   Contador funciones que podría utilizar para analizar la función de retardo.   Pero para demoras de SW, tenga en cuenta que las interrupciones pueden activarse (si están habilitadas)   y cambia tu retraso observable resultante.

Empleados de TI en sus foros de soporte.

    
respondido por el Passerby

Lea otras preguntas en las etiquetas