Función de retardo en la programación ARM

5

Acabo de comenzar a programar en ARM, tenía algo de experiencia en AVR pero no tanto. La pregunta es probablemente demasiado trivial, pero el material sobre ARM es muy poco en la red ... lo siento de todos modos.

Sé que por implementar retrasos en ARM podemos usar temporizadores o ciclos de ocupado. Probé esos métodos. Pero uno de mis amigos sugiere que hay un archivo de cabecera para el brazo "delay.h" que contiene todas las funciones de retardo necesarias, como avr, delay_ms y ....

En primer lugar, por tonta que parezca esta pregunta, ¿existe realmente una función de retardo incorporada en la programación ARM? ¿Está en retraso.h?

Si es así, ¿por qué es tan popular el uso de temporizadores para implementar retrasos? ¿Por qué no usan la función incorporada?

Estoy estudiando la serie LPC17xx.

    
pregunta kasra5004

4 respuestas

4

Muchos compiladores y bibliotecas admiten la familia ARM. No perdería tiempo buscando una única solución definida en un solo nombre de archivo. Eso ciertamente no es "la" solución para "ARM".

Al igual que con AVR y la mayoría de los otros procesadores, ciertamente los microcontroladores, tiene la opción de bloquear en un bucle de primer plano, ya sea utilizando un bucle calibrado, o sondeando un temporizador. También puede utilizar una interrupción basada en temporizador si es necesario. Depende de lo que necesite para realizar una demora y de qué otra cosa podría estar ocurriendo durante esa demora. Dependiendo del chip específico y de la cantidad de tiempo que desee retrasar, es posible que pueda dejar el chip dormido durante ese período de tiempo.

Si está utilizando una biblioteca para otras cosas como SPI, I2C, etc. para el procesador de destino y la cadena de herramientas, es probable que también tenga rutinas de temporizador y que pueda usarlas. Si está utilizando su propio dispositivo (el más portátil, pero también el más útil), mire los temporizadores, a la larga será más fácil mantener el código que se basa en un temporizador en lugar de basarse en un bucle calibrado (contar hasta N) .

Hay una serie de cadenas de herramientas y bibliotecas adaptadas a la familia NXP LPC, en particular, si esa es la ruta que desea tomar.

De ninguna manera, forma o forma. ¿Hay una solución única a la que debería limitarse? No para ARM no para AVR, no para ninguno de ellos.

    
respondido por el old_timer
2

Piense en una CPU ARM como una CPU completa que podría usar para un sistema operativo como Linux. Ahora imagine lo que sucedería si bloqueara la ejecución en todo el chip siempre que quisiera una funcionalidad de retardo de tiempo. Todo se bloquearía durante el retraso, lo que llevaría a una experiencia completamente inutilizable para cualquier tipo de sistema interactivo para el usuario. Es por eso que se prefieren los temporizadores.

Los temporizadores son útiles porque evitan la situación de bloqueo. La CPU continúa ejecutando el código y vuelve a la rutina del manejador una vez que el temporizador transcurre. Esto ofrece una forma de operación asíncrona que permite un código mucho más flexible.

En arquitecturas que no admiten directamente los temporizadores internos, pero sí admiten interrupciones externas, se puede utilizar un dispositivo de temporización externo. El temporizador se programa con un desplazamiento de tiempo (generalmente un escalar y un multiplicador) y un número de interrupción. Cuando el temporizador externo activa la interrupción, la CPU lee una tabla de interrupciones para encontrar el vector de interrupción , que es una dirección lineal a la que se transfiere la ejecución para manejar el evento del temporizador.

    
respondido por el Polynomial
2

En ocasiones, el código se ejecutará en un contexto en el que no sucederá nada más. Si el procesador establece un bit de E / S, luego ejecuta una serie de instrucciones que toman un total de 1 ms para ejecutarse, y luego borra el bit de E / S, entonces el cable controlado por ese bit pulsará alto durante 1 ms. Los métodos simples de retardo pueden ser útiles en tales contextos. Sin embargo, son mucho menos útiles en contextos donde otras cosas pueden estar sucediendo. Si mientras se estaba ejecutando el retraso mencionado anteriormente, se produjo una interrupción que requirió 100us para el servicio, el pin sería pulsado alto durante 1.1 ms en lugar de 1 ms. Y lo que es peor, si se intenta utilizar dicho retraso dentro de una rutina de servicio de interrupción, el código de la línea principal y todas las interrupciones de prioridad más baja se suspenderán hasta que se complete dicho retraso.

En general, el enfoque de implementación mencionado anteriormente es apropiado cuando (1) uno escribe algo como un cargador de arranque que debería poder funcionar sin interrupciones, y nada más ocurrirá mientras se está ejecutando; (2) uno necesita un retraso lo suficientemente corto, no tiene mucho sentido tratar de encontrar otra cosa que hacer. Por ejemplo, si uno está utilizando un procesador de 32 MHz para comunicarse con un dispositivo que requiere 1.6us de tiempo de inactividad entre los bytes de datos, insertar un código que invierta 52 ciclos sin hacer nada significaría que el ARM podría estar bien posicionado para enviar el siguiente byte de aproximadamente 1.6 nosotros despues Por el contrario, si la ARM intenta encontrar otra cosa que hacer, es probable que esté ocupado haciendo eso al final de las 1.6us, y que no envíe el siguiente byte hasta algún tiempo después.

    
respondido por el supercat
1

Por supuesto, es posible utilizar un procesador ARM para hacer un retraso simple. Ver mi código a continuación. Sin embargo, dependiendo de lo que necesite que haga su procesador, puede que no sea la mejor solución. Este código se ejecuta en un procesador de la serie LPC2000 de NXP.

/**********************************************************************/
/* Timer.c                                                            */
/* Implements a delay :                                               */
/*   TMR0 is a mcrosecond timer capable of timing events of upto      */
/*   4294.967295 seconds (1 hour 11 min 36.967295 sec)                */
/*   includes both delay and stop watch functions                     */
/*       void Delay(unsigned int delay); delay in microseconds        */
/*   Does not use interupts.  Note timer may rollover during delay    */
/*   so code checks for this                                          */
/*   Note: delay is minimum delay as interupts can slow it down       */
/**********************************************************************/
/*
 * Note: Assumes TMR0 is already setup with 1 microsecond tick
 */

#include <LPC2103.h>

#include "Timer.h"

void Delay(unsigned int delay){
    unsigned int start;
    unsigned int stop;
    unsigned int now;

    start = T0TC;
    stop = start + delay + 1;           /* +1 because call could arrive just
                                       before TOTC changes */
    if (stop > start){                /* usually is */
        do{
            now = T0TC;
        }while (now < stop && now >= start);  /* Catch timer roll-over as done */
    }else{                                    /* Need timer to roll over */
        do{
            now = T0TC;
        }while (now < stop || now >= start);  
    }
}

Incluso si está contento de simplemente sentarse en un bucle esperando un retardo, un temporizador puede mejorar, ya que es más difícil estimar los tiempos de retardo con un bucle simple como

for(i=1000; i >0; i--){
    ;
}

Porque un buen compilador optimizador puede optimizar esto.

Incluso si no se optimiza, es difícil saber exactamente cuánto tardará este retraso, ya que los procesadores de la serie NXP LPC tienen aceleradores de memoria y el procesador tiene revestimiento de tuberías.

    
respondido por el Warren Hill

Lea otras preguntas en las etiquetas