Mesure de la charge CPU de la routine d'interruption

8

J'ai un isr qui met à jour un affichage à une fréquence fixe. Je voudrais ajuster ma routine pour minimiser les frais généraux et garder autant de temps processeur possible que possible pour d'autres traitements, mais je n'ai pas de bon moyen de collecter des mesures pour déterminer ma charge processeur.

Je pourrais regarder l'assemblage et analyser la routine, mais je n'ai pas la patience ou la capacité de le faire avec précision. Je ne pense pas non plus avoir besoin de résultats extrêmement fins, juste un simple pourcentage de temps processeur occupé par l'isr.

Je pourrais placer une broche haute uniquement lorsque l'isr est actif et la mesurer à l'extérieur. Cela a un minimum de frais généraux dans le code, mais je ne sais pas avec quoi le mesurer. Je n'ai pas d'oscilloscope ou quelque chose comme ça. Existe-t-il un ic simple ou un moyen facile d'utiliser un autre micro pour mesurer le rapport cyclique? J'ai entendu parler de puces de compteur de fréquence dédiées, mais y a-t-il quelque chose pour le rapport cyclique?

captncraig
la source

Réponses:

8

Juste une idée à moitié cuite, vous pourriez peut-être utiliser des minuteries comme ça (pseudo code):

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);

}

et dans votre écran ISR ...

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

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

J'ai fait quelques hypothèses ici. 1 - que vous n'utilisez pas vos minuteries pour autre chose, et que, 2 - la surcharge de démarrage et d'arrêt d'une minuterie est minime (généralement effectuée avec une seule écriture de registre). EDIT: et une troisième hypothèse, vous pouvez capturer tout cela avant qu'un débordement de minuterie ne se produise, mais vous pouvez peut-être aussi en tenir compte.

Il y aura une surcharge de changement de contexte que vous ne pourrez pas intercepter, et cela ajoute également deux opérations supplémentaires dans votre ISR (assurez-vous d'utiliser des macros pour votre start_timer / stop_timer pour éliminer la surcharge d'appel de fonction). Si vous pouvez obtenir le nombre total de cycles utilisés pour les macros de temporisation de démarrage + arrêt, vous pouvez soustraire ces ticks de la valeur timer1_value pour obtenir la valeur des ticks ISR un peu plus précisément. Votre calcul final pour% du temps CPU utilisé serait simplement:

Usagecpu=(TicksisrTicksisr+Ticksidle)100
Jon L
la source
1
+1 pour une solution ne nécessitant aucun matériel externe. Probablement une façon plus lourde de le faire, mais cela correspond à mes contraintes. J'ai juste besoin d'en savoir plus sur les minuteries maintenant. Merci.
captncraig
Je l'ai utilisé sur un AVR pour un projet similaire. Il fonctionne très bien.
drxzcl
11

Définissez une broche de sortie lorsque vous entrez dans l'ISR et effacez-la avant de revenir. Filtrez la sortie avec un filtre RC. La tension aux bornes du condensateur devrait vous donner le rapport cyclique ISR.
Par exemple, si votre alimentation est de 3,3 V et que vous mesurez 33 mV, vous passez 1% du temps dans l'ISR.

Stevenvh
la source
2
C'est exactement ce que nous faisons, à l'exception de la partie filtre RC. Nous définissons une broche de sortie à l'entrée de l'ISR, puis l'effaçons au retour. Regarder cela sur un o-scope donnera toutes sortes d'informations utiles.
3
@David - Je regarde également les impulsions sur une lunette, mais OP dit qu'il n'en a pas.
stevenvh
1
Il semble que je dois commencer à économiser pour une bonne portée.
captncraig
@stevenvh, exactement ce que j'allais suggérer quand j'ai vu l'absence de portée. C'est pourquoi ces gars intégrés aiment quelques broches de sortie numérique supplémentaires.
Kortuk
Filtrer au mètre en l'absence de lunette une bonne idée. Allumez / éteignez la LED et mesurez la luminosité effective: -). (Très difficile à voir même des variations assez importantes - mais mignon.)
Russell McMahon
7

La façon la plus simple de procéder consiste à exécuter le code dans le simulateur et à mesurer les cycles pris par la routine d'interruption. Le simulateur Microchip MPLAB, par exemple, dispose d'une fonction chronomètre pratique qui est très utile à cet effet.

À défaut, lever une épingle au début de l'interruption et la baisser à la fin peut aider. La façon la plus simple de voir cela est avec un oscilloscope. Si vous faites des projets de microcontrôleur et d'électronique, vous devriez en obtenir un de toute façon.

Sans lunette, vous pouvez simplement filtrer passe-bas la tension des broches, puis la mesurer avec un voltmètre. Cette tension divisée par la tension d'alimentation du processeur vous donnera la fraction du temps où la broche est élevée. Par exemple, si le processeur fonctionne sur 3,3 V et que la tension de la broche filtrée passe-bas est de 800 mV, la broche est élevée à 800 mV / 3,3 V = 24% du temps.

Comme vous utilisez apparemment un compilateur, vous devez quelque peu déclasser cette réponse. Le compilateur ajoute probablement un code d'entrée d'interruption avant l'exécution de votre code et un code de sortie d'interruption après l'exécution de votre code. Le vrai temps d'interruption s'étendra sur quelques cycles de chaque côté de l'impulsion. Bien sûr, si vous vous souciez du timing des interruptions, vous ne devriez pas utiliser un compilateur en premier lieu.

Olin Lathrop
la source