Est-il possible de surveiller un bloc de code et de déterminer le nombre de cycles d'horloge du processeur que le code a pris sur un processeur atmel Arduino et / ou AVR? ou, dois-je plutôt surveiller les microsecondes passées avant et après l'exécution du code? Remarque: je ne m'inquiète pas autant du temps réel (comme dans, combien de secondes réelles se sont écoulées) que de "combien de cycles d'horloge ce code nécessite-t-il de la part du CPU"
La solution actuelle que je peux trouver est de time.c:
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
câblage.c ajoute:
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
Par ce compte, je pouvais calculer les cycles d'horloge passés en surveillant les microsecondes passées, puis les transmettre à microsecondsToClockCycles (). Ma question est, existe-t-il une meilleure façon?
sidenote: existe-t-il de bonnes ressources pour le contrôle des performances de l'AVR. lmgtfy.com et diverses recherches sur les forums ne fournissent aucun résultat évident, autre que l'exploration des minuteries
Merci
Qu'entendez-vous par «moniteur»?
Il ne devrait pas être difficile de compter les cycles d'horloge pour l'AVR pour les petits morceaux de code d'assemblage.
Vous pouvez également définir un port avant l'exécution du code et le réinitialiser par la suite, et le surveiller avec un analyseur logique ou un oszilloscope pour obtenir le timing.
Et vous pouvez également lire l'heure à partir d'une minuterie à fonctionnement rapide, comme vous le dites.
la source
Ceci est un exemple pour Arduino utilisant la fonction clockCyclesPerMicrosecond () pour calculer les horloges qui sont passées. Ce code attendra 4 secondes, puis imprimera le temps écoulé depuis le début du programme. Les 3 valeurs de gauche sont le temps total (microsecondes, millisecondes, cycles d'horloge totaux) et les 3 plus à droite sont les temps écoulés:
Production:
Je suis sûr qu'il y a une explication raisonnable pourquoi les premières boucles avaient également des cycles d'horloge écoulés plus courts que la plupart et pourquoi toutes les autres boucles basculent entre deux longueurs de cycles d'horloge.
Code:
Sidenote: si vous supprimez le délai de 4 secondes, vous commencerez à voir les effets de Serial.print () beaucoup plus clairement. Remarque, ici 2 exécutions sont comparées. Je n'ai inclus que 4 échantillons les uns à côté des autres à partir de leurs journaux respectifs.
Exécuter 1:
Exécuter 2:
Le temps écoulé augmente par rapport au temps d'exécution total. Après une seconde, les horloges augmentent en moyenne de 40k à 44k. Cela se produit régulièrement quelques millisecondes après 1 seconde et les horloges écoulées restent autour de 44k pendant au moins les 10 secondes suivantes (je ne l'ai pas testé plus loin). C'est pourquoi la surveillance est utile ou nécessaire. Peut-être que la baisse d'efficacité a à voir avec la configuration ou les bugs en série? Ou peut-être que le code n'utilise pas la mémoire correctement et a une fuite qui affecte les performances, etc.
la source
Étant donné que chaque ligne de code ajoutée à votre source aura un impact sur les performances et pourrait modifier les optimisations appliquées. Les modifications doivent être le minimum requis pour effectuer la tâche.
Je viens de trouver un plugin Atmel Studio appelé "Annotated Assembly File Debugger". http://www.atmel.com/webdoc/aafdebugger/pr01.html Il semble que passer à travers le langage d'assemblage généré alors que probablement fastidieux va vous montrer exactement ce qui se passe. Vous devrez peut-être encore décoder le nombre de cycles qu'il faut pour chaque instruction, mais cela serait beaucoup plus proche que certaines des autres options publiées.
Pour ceux qui ne connaissent pas dans le dossier de sortie de votre projet est un fichier avec une extension LSS. Ce fichier contient tout votre code source d'origine sous forme de commentaires et sous chaque ligne se trouve le langage d'assemblage qui a été généré sur la base de cette ligne de code. La génération du fichier LSS peut être désactivée, vérifiez donc le paramètre suivant.
Propriétés du projet | Chaîne d'outils | AVR / GNU Commun | Fichiers de sortie
Case à cocher ".lss (Générer un fichier lss)
la source
Vous pouvez utiliser l'un des minuteurs intégrés. Obtenez tout configuré pour prescaller = 1 et TCNT = 0 avant le bloc. Activez ensuite le temporisateur sur la ligne avant le bloc et désactivez-le sur la ligne après le bloc. Le TCNT conservera maintenant le nombre de cycles que le bloc a pris, moins les cycles fixes pour le code d'activation et de désactivation.
Notez que le TNCT débordera après 65535 cycles d'horloge sur une minuterie 16 bits. Vous pouvez utiliser l'indicateur de débordement pour doubler la durée d'exécution. Si vous avez encore besoin de plus de temps, vous pouvez utiliser un prédéfinisseur, mais vous obtiendrez moins de résolution.
la source