Medición de la carga de CPU de la rutina de interrupción

8

Tengo un ISR que está actualizando una pantalla a una frecuencia fija. Me gustaría ajustar mi rutina para minimizar la sobrecarga y mantener abierto el mayor tiempo posible de CPU para otro procesamiento, pero no tengo una buena manera de recopilar métricas para determinar mi carga de CPU.

Podría mirar la asamblea y analizar la rutina, pero no tengo la paciencia o la capacidad para hacerlo con precisión. Tampoco siento que necesito resultados extremadamente finos, solo un porcentaje simple de tiempo de CPU ocupado por el ISR.

Podría establecer un pin alto solo cuando el ISR está activo y medirlo externamente. Eso tiene un mínimo de sobrecarga en el código, pero no sé con qué medirlo. No tengo un osciloscopio ni nada de eso. ¿Existe un ic simple o una manera fácil de usar otro micro para medir el ciclo de trabajo? He oído hablar de chips de contador de frecuencia dedicados, pero ¿hay algo para el ciclo de trabajo?

captncraig
fuente

Respuestas:

8

Solo una idea a medias, es posible que pueda usar temporizadores como este (pseudocódigo):

int main(void)
{

    /* ... init timers and uart here, enable your interrupts ... */

    start_timer0();
    while (!timer1Started()){}
    stop_timer1();

    uart_puts("Idle ticks: %d, ISR ticks: %d", timer0_value, timer1_value);

}

y en su pantalla ISR ...

ISR_display()
{
    stop_timer0();
    start_timer1();

    /* ... your ISR routine ... */
}

He hecho algunas suposiciones aquí. 1: que no está utilizando sus temporizadores para nada más, y que 2: la sobrecarga de iniciar y detener un temporizador es mínima (generalmente se realiza con una sola escritura de registro). EDITAR: y una tercera suposición, puede capturar todo esto antes de que ocurra un desbordamiento del temporizador, pero tal vez también pueda dar cuenta de eso.

Habrá cierta sobrecarga de cambio de contexto que no podrá detectar, y esto también agrega dos operaciones adicionales en su ISR (asegúrese de usar macros para su start_timer / stop_timer para eliminar la sobrecarga de llamadas a funciones). Si puede obtener el número total de ciclos utilizados para las macros del temporizador de inicio + detención, puede restar esos ticks del timer1_value para obtener el valor de los ticks ISR con un poco más de precisión. Su cálculo final para el% de tiempo de CPU utilizado sería simplemente:

UsunasolmiCpagstu=(TyoCksyosrTyoCksyosr+TyoCksyorelmi)100
Jon L
fuente
1
+1 para una solución que no requiere hardware externo. Probablemente sea una forma más engorrosa de hacerlo, pero se ajusta a mis limitaciones. Solo necesito aprender sobre temporizadores ahora. Gracias.
captncraig
Usé esto en un AVR para un proyecto similar. Funciona muy bien.
drxzcl
11

Establezca un pin de salida cuando ingrese el ISR y bórrelo antes de regresar de él. Filtre la salida con un filtro RC. El voltaje a través del condensador debería darle el ciclo de trabajo ISR.
Por ejemplo, si su fuente de alimentación es de 3.3V y mide 33mV, entonces pasa el 1% del tiempo en el ISR.

stevenvh
fuente
2
Esto es exactamente lo que hacemos, excepto por la parte del filtro RC. Establecemos un pin de salida al ingresar al ISR, luego lo borramos al regresar. Mirar esto en un o-scope le dará todo tipo de información útil.
3
@David: también miro los pulsos en un telescopio, pero OP dice que no tiene uno.
stevenvh
1
Parece que necesito comenzar a ahorrar para tener un buen alcance.
captncraig
@stevenvh, exactamente lo que iba a sugerir cuando vi la ausencia de un alcance. Esta es la razón por la que a los chicos integrados les encantan algunos pines de salida digital adicionales.
Kortuk
Filtrar para medir en ausencia de un alcance una buena idea. Encienda / apague el LED y mida el brillo efectivo: -). (Muy difícil de ver incluso variaciones bastante grandes, pero lindo.)
Russell McMahon el
7

La forma más fácil de hacer esto es ejecutar el código en el simulador y medir los ciclos tomados por la rutina de interrupción. El simulador Microchip MPLAB, por ejemplo, tiene una práctica función de cronómetro que es muy útil para este propósito.

De lo contrario, levantar un alfiler al comienzo de la interrupción y bajarlo al final puede ayudar. La forma más fácil de ver eso es con un osciloscopio. Si está haciendo proyectos de microcontroladores y electrónica, debería obtener uno de todos modos.

Sin un osciloscopio, simplemente podría filtrar el voltaje del pin de paso bajo y luego medirlo con un voltímetro. Ese voltaje dividido por el voltaje de alimentación del procesador le dará la fracción del tiempo que el pin está alto. Por ejemplo, si el procesador funciona con 3.3V y el voltaje del pin filtrado de paso bajo es 800mV, entonces el pin es alto 800mV / 3.3V = 24% del tiempo.

Como aparentemente está utilizando un compilador, debe reducir un poco esta respuesta. Es probable que el compilador agregue algún código de entrada de interrupción antes de que se ejecute su código e interrumpa el código de salida después de que se ejecute su código. El verdadero tiempo de interrupción se extenderá unos pocos ciclos a cada lado del pulso. Por supuesto, si le preocupa el tiempo de interrupción, no debería usar un compilador en primer lugar.

Olin Lathrop
fuente