Misurazione del carico della CPU della routine di interrupt


8

Ho un isr che sta aggiornando un display a frequenza fissa. Vorrei ottimizzare la mia routine per ridurre al minimo i costi generali e mantenere il più tempo possibile della CPU aperto per altre elaborazioni, ma non ho alcun buon modo per raccogliere le metriche per determinare il mio carico della CPU.

Potrei guardare l'assemblea e analizzare la routine, ma non ho la pazienza o la capacità di farlo con precisione. Non mi sento nemmeno di aver bisogno di risultati terribilmente raffinati, solo una semplice percentuale di tempo di CPU occupato dall'ISR.

Potrei impostare un pin alto solo quando l'ISR è attivo e misurarlo esternamente. Questo ha un minimo di sovraccarico nel codice, ma non so con cosa misurarlo. Non ho un oscilloscopio o niente del genere. Esiste un ic semplice o un modo semplice per usare un altro micro per misurare il duty cycle? Ho sentito parlare di chip del contatore di frequenza dedicati, ma c'è qualcosa per il duty cycle?

Risposte:


8

Solo un'idea a metà, potresti essere in grado di utilizzare i timer in questo modo (pseudo codice):

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 nel tuo display ISR ...

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

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

Ho assunto alcune ipotesi qui. 1 - che non stai usando i tuoi timer per nient'altro e che, 2 - il sovraccarico di avvio e arresto di un timer è minimo (in genere fatto con una sola scrittura del registro). EDIT: e un terzo presupposto, puoi catturare tutto questo prima che si verifichi un overflow del timer, ma forse puoi anche tenerne conto.

Ci saranno alcuni overhead di cambio di contesto che non sarai in grado di rilevare e questo aggiunge anche due ulteriori operazioni nel tuo ISR (assicurati di usare le macro per start_timer / stop_timer per eliminare l'overhead di chiamata di funzione). Se è possibile ottenere il numero totale di cicli utilizzati per le macro del timer di avvio + arresto, è possibile sottrarre tali tick dal valore timer1_ per ottenere un valore un po 'più accurato del valore dei tick ISR. Il calcolo finale per% del tempo di CPU utilizzato sarebbe semplicemente:

Usagecpu=(TicksisrTicksisr+Ticksidle)100

1
+1 per una soluzione che non richiede hardware esterno. Probabilmente un modo più ingombrante per farlo, ma si adatta ai miei vincoli. Ho solo bisogno di conoscere i timer ora. Grazie.
captncraig,

L'ho usato su un AVR per un progetto simile. Funziona molto bene
drxzcl,

11

Impostare un pin di uscita quando si immette l'ISR e lo cancella prima di tornare da esso. Filtra l'output con un filtro RC. La tensione attraverso il condensatore dovrebbe fornire il ciclo di lavoro ISR.
Ad esempio, se l'alimentazione è di 3,3 V e si misura 33 mV, si passa all'1% del tempo nell'ISR.


2
Questo è esattamente ciò che facciamo, ad eccezione della parte del filtro RC. Impostiamo un pin di uscita inserendo l'ISR, quindi cancellandolo al ritorno. Guardare questo su un o-scope fornirà tutti i tipi di informazioni utili.

3
@ David - Ho anche solo guardato gli impulsi su un ambito, ma OP dice che non ne ha uno.
Stevenvh,

1
Sembra che debba iniziare a risparmiare per un buon ambito.
captncraig,

@stevenvh, esattamente quello che stavo per suggerire quando ho visto l'assenza di un ambito. Questo è il motivo per cui quei ragazzi embedded adorano alcuni pin di uscita digitali extra.
Kortuk,

Filtrare per misurare in assenza di un ambito una buona idea. Accendi / spegni il LED e misura la luminosità effettiva: -). (Molto difficile vedere anche variazioni abbastanza grandi - ma carine.)
Russell McMahon

7

Il modo più semplice per farlo è eseguire il codice nel simulatore e misurare i cicli presi dalla routine di interrupt. Il simulatore MPLAB Microchip, ad esempio, ha una pratica funzione di cronometro che è molto utile per questo scopo.

In caso contrario, può essere utile sollevare un perno all'inizio dell'interruzione e abbassarlo alla fine. Il modo più semplice di osservarlo è con un oscilloscopio. Se stai realizzando progetti di microcontrollori ed elettronica, dovresti prenderne uno comunque.

Senza un ambito, è possibile semplicemente filtrare la tensione del pin con un filtro passa-basso, quindi misurarlo con un voltmetro. Quella tensione divisa per la tensione di alimentazione del processore ti darà la frazione del tempo in cui il pin è alto. Ad esempio, se il processore funziona a 3,3 V e la tensione del pin filtrata passa basso è 800 mV, il pin è alto 800 mV / 3,3 V = 24% del tempo.

Dal momento che apparentemente stai usando un compilatore, devi ridurre leggermente questa risposta. È probabile che il compilatore aggiunga un codice di ingresso di interruzione prima dell'esecuzione del codice e che interrompa il codice di uscita dopo l'esecuzione del codice. Il vero tempo di interruzione si prolungherà di alcuni cicli su entrambi i lati dell'impulso. Ovviamente se ti interessa il tempismo degli interrupt, non dovresti usare un compilatore in primo luogo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.