Medindo a carga da CPU da rotina de interrupção

8

Eu tenho um isr que está atualizando uma exibição em uma frequência fixa. Gostaria de ajustar minha rotina para minimizar a sobrecarga e manter o tempo possível da CPU aberto para outro processamento, mas não tenho nenhuma maneira boa de coletar métricas para determinar minha carga de CPU.

Eu podia olhar para a montagem e analisar a rotina, mas não tenho paciência ou capacidade de fazer isso com precisão. Também não acho que preciso de resultados de granulação muito fina, apenas uma porcentagem simples do tempo de CPU ocupado pelo isr.

Eu poderia definir um pino alto somente quando o isr estiver ativo e medi-lo externamente. Isso tem um mínimo de sobrecarga no código, mas não sei com o que medir. Eu não tenho um osciloscópio ou algo assim. Existe uma maneira simples ou fácil de usar outro micro para medir o ciclo de trabalho? Ouvi falar de chips dedicados de contador de frequência, mas há algo para o ciclo de serviço?

captncraig
fonte

Respostas:

8

Apenas uma ideia incompleta, você pode usar temporizadores como esse (pseudo-có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);

}

e na sua tela ISR ...

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

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

Eu fiz algumas suposições aqui. 1 - que você não está usando seus cronômetros para mais nada e, 2 - a sobrecarga de iniciar e interromper um cronômetro é mínima (normalmente feita com uma única gravação de registro). EDIT: e uma terceira suposição, você pode capturar tudo isso antes que ocorra um estouro de timer, mas talvez você possa explicar isso também.

Haverá alguma sobrecarga de troca de contexto que você não poderá capturar, e isso também adiciona duas operações adicionais no seu ISR (certifique-se de usar macros para o start_timer / stop_timer para eliminar a sobrecarga da chamada de função). Se você pode obter o número total de ciclos usados ​​para macros do timer de início + parada, pode subtrair esses ticks do valor timer1_value para obter o valor dos ticks ISR com um pouco mais de precisão. Seu cálculo final para% do tempo de CPU usado seria simplesmente:

Usagecpu=(TicksisrTicksisr+Ticksidle)100
Jon L
fonte
1
+1 para uma solução que não requer hardware externo. Provavelmente é uma maneira mais complicada de fazer isso, mas se encaixa nas minhas restrições. Eu só preciso aprender sobre temporizadores agora. Obrigado.
captncraig
Eu usei isso em um AVR para um projeto semelhante. Funciona muito bem.
drxzcl
11

Defina um pino de saída ao inserir o ISR e limpe-o antes de retornar dele. Filtre a saída com um filtro RC. A tensão no capacitor deve fornecer o ciclo de serviço ISR.
Por exemplo, se sua fonte de alimentação é de 3,3V e você mede 33mV, passa 1% do tempo no ISR.

stevenvh
fonte
2
É exatamente isso que fazemos, exceto a parte do filtro RC. Definimos um pino de saída ao entrar no ISR e depois limpá-lo no retorno. Olhar para isso em um escopo o dará todos os tipos de informações úteis.
3
@ David - Eu também apenas assisto os pulsos em um osciloscópio, mas o OP diz que ele não tem um.
Stevenvh
1
Parece que preciso começar a economizar para um bom escopo.
Captncraig 07/11
@ stevenvh, exatamente o que eu ia sugerir quando vi a ausência de um escopo. É por isso que esses caras incorporados adoram alguns pinos extras de saída digital.
precisa saber é o seguinte
Filtrando para medir na ausência de um escopo, uma boa idéia. Vire LED on / off e medir o brilho eficaz: -.) (Muito difícil de ver, mesmo muito grandes variações - mas bonito).
Russell McMahon
7

A maneira mais fácil de fazer isso é executar o código no simulador e medir os ciclos realizados pela rotina de interrupção. O simulador Microchip MPLAB, por exemplo, possui um útil recurso de cronômetro que é muito útil para esse fim.

Caso contrário, elevar um alfinete no início da interrupção e abaixá-lo no final podem ajudar. A maneira mais fácil de ver isso é com um osciloscópio. Se você estiver realizando projetos de microcontroladores e eletrônicos, deverá adquirir um de qualquer maneira.

Sem um osciloscópio, você poderia simplesmente filtrar com baixa frequência a tensão do pino e medi-la com um voltímetro. Essa tensão dividida pela tensão de energia do processador fornecerá a fração do tempo em que o pino está alto. Por exemplo, se o processador estiver funcionando em 3,3V e a tensão do pino filtrado de passa-baixa for 800mV, o pino estará em 800mV / 3,3V = 24% do tempo.

Como você aparentemente está usando um compilador, precisa diminuir a resposta. O compilador provavelmente está adicionando algum código de entrada de interrupção antes da execução do código e interrompe o código de saída após a execução do código. O verdadeiro tempo de interrupção prolongará alguns ciclos em ambos os lados do pulso. Obviamente, se você se importa com o tempo de interrupção, não deve usar um compilador em primeiro lugar.

Olin Lathrop
fonte