2009-06-06 10 views
23

Bien qu'il existe de nombreux frameworks de tests unitaires supportant C, je suis un peu perplexe sur la façon d'écrire des tests unitaires pour le code micro contrôleur (PIC dans mon cas, mais je pense que la question est plus général que cela).Modèles de tests unitaires pour le microcontrôleur C code

Une grande partie du code écrit pour les microcontrôleurs tourne autour de l'écriture des valeurs de configuration et de données dans les registres, de la lecture des données entrantes des registres et de la réponse aux événements d'interruption. Je me demande si quelqu'un peut fournir des indications sur la façon la plus efficace d'y arriver.

+0

Quelqu'un pourrait-il avec représentant suffisant s'il vous plaît ajouter le tag "intégré" à cette question? Merci. –

Répondre

29

Vous écrivez; «Une grande partie du code écrit pour les microcontrôleurs tourne autour de l'écriture des valeurs de configuration et de données dans les registres, de la lecture des données entrantes des registres et de la réponse aux événements d'interruption». Je suis d'accord que c'est souvent le cas en pratique, mais je ne pense pas que ce soit une bonne chose, et je pense que repenser un peu les choses vous aidera à atteindre vos objectifs de test. Peut-être parce que les programmeurs de microcontrôleurs peuvent atteindre et toucher le matériel quand ils le souhaitent, beaucoup (la plupart?) D'entre eux ont pris l'habitude de le faire, tout au long de leur code. Souvent, cette habitude est suivie sans discussion, peut-être parce que tant de gens qui font ce genre de travail ne sont pas des informaticiens par la formation et l'inclination. Je sais, j'ai commencé de cette façon moi-même. Le point que j'essaye de faire, c'est que les projets de microcontrôleurs peuvent et doivent être bien conçus comme n'importe quel autre projet de logiciel. Une partie importante de la bonne conception est de restreindre l'accès matériel aux pilotes matériels! Partitionnez tout le code qui écrit des registres, répond aux interruptions etc. dans des modules qui fournissent au reste de votre logiciel un accès agréable, net et abstrait au matériel. Testez ces modules pilotes sur la cible à l'aide d'analyseurs logiques, d'oscilloscopes, de bancs d'essai personnalisés ou de tout autre élément logique.

Un point vraiment important est que maintenant le reste de votre logiciel, avec un peu de chance la grande majorité de celui-ci, est maintenant juste du code C que vous pouvez exécuter et tester sur un système hôte. Sur le système hôte, les modules matériels sont écrasés d'une manière qui fournit une visibilité sur ce que fait le code testé. Vous pouvez utiliser les approches de test unitaire sur ce code. Cela nécessite des préparatifs et du travail, mais si vous êtes bien organisé, vous pouvez créer un système réutilisable qui peut s'appliquer à tous vos projets. Les avantages potentiels sont énormes. J'ai écrit un peu plus sur ces idées ici;

[http://discuss.joelonsoftware.com/default.asp?joel.3.530964.12][1]

+4

Bon point. Puis-je ajouter: s'habituer à utiliser uint16_t, uint8_t et ainsi de suite (au lieu de seulement int, char) afin que vos types soient plus prévisibles lors du passage de la plate-forme embarquée au PC, et aussi entre différentes plates-formes embarquées. –

+3

Problèmes avec cette réponse: l'abstraction du pilote matériel crée un surcoût important, souvent inacceptable, sauf s'il est écrit en assembleur. mais mixer C et assembleur est un énorme casse-tête - non seulement l'architecture PIC est-elle un PITA avec lequel travailler, mais le compilateur saute dans les cages jonglant avec les différentes banques de registres, ce qui est un énorme PITA pour écrire assembleur. – Jodes

0

Existe-t-il un mode de bouclage de sorte que vous pouvez utiliser le contrôleur lui-même pour générer des événements que vous pouvez tester?

3

Une approche peut être d'utiliser un émulateur. J'ai travaillé sur un émulateur AVR et l'une des idées pour l'utiliser est en effet le code de test unitaire. L'émulateur implémente le CPU et les registres, les interruptions et divers périphériques, et (dans mon cas) les octets écrits dans l'UART émulé vont au stdout normal de l'émulateur. De cette manière, le code de test unitaire peut s'exécuter dans l'émulateur et écrire ses résultats de test sur la console.

Bien sûr, il faut aussi s'assurer que l'émulateur est en train d'implémenter correctement le comportement de la CPU réelle, sinon les tests unitaires ne peuvent pas être approuvés.

2

Rédigez des versions fictives de vos fonctions/macros d'accès au registre. Notez que cela suppose que votre code utilise un ensemble commun de fonctions d'accès au registre, et non des éléments ad-hoc comme *(volatile int*)0xDEADBEEF = 0xBADF00D partout. Appelez vos gestionnaires d'interruption directement à partir de votre code de test (peut être problématique sur certaines architectures ¹), une "interruption logicielle" si disponible, ou à partir d'un gestionnaire d'interruption de minuterie si vous avez besoin de les exécuter de manière asynchrone. Cela peut nécessiter d'encapsuler votre code d'activation/désactivation d'interruption dans les fonctions/macros que vous pouvez mock up. 8051 vient à l'esprit: au moins avec le compilateur Keil 8051, vous ne pouvez pas appeler directement les fonctions d'interruption. Cela pourrait être élaboré avec le préprocesseur C cependant.