Qu'est-ce qui pourrait provoquer la réinitialisation inattendue d'un microcontrôleur?

26

Un bug particulièrement irritant dans un système contrôlé par microprocesseur consiste à réinitialiser le microprocesseur de manière inattendue. Un outil important pour déboguer ce type de problème est une liste de causes possibles. Qu'est-ce qui pourrait provoquer la réinitialisation inattendue d'un microcontrôleur?

Stephen Collings
la source
1
Certaines des réponses ici peuvent être utiles: electronics.stackexchange.com/questions/30430/… Quel type de microcontrôleur utilisez-vous?
Jon L
J'utilise généralement dsPIC. Mais je n'essaie pas de déboguer quoi que ce soit de particulier en ce moment, je compile simplement une liste de référence des problèmes potentiels.
Stephen Collings
2
Est-ce que c'est une question d'un devoir?
old_timer
1
@dwelch Probablement pour quelqu'un quelque part, mais pas pour moi ni pour aucun de mes étudiants.
Stephen Collings
1
@Vorac doit lire qu'Atmel ne peut pas s'engager à maintenir l'URL fiable.
Kaz

Réponses:

51

Sur les puces PIC et dsPIC, j'ai observé les causes suivantes de réinitialisation inattendue.

Matériel:

  • Réinitialiser la broche entraînée bas ou flottant. Vérifiez d'abord les choses évidentes!
  • Couplage ESD dans la broche de réinitialisation. J'ai vu cela se produire lorsque des équipements complètement indépendants sont allumés sur le même bureau. Assurez-vous qu'il y a suffisamment de capacité sur la broche de réinitialisation, peut-être jusqu'à 1 uF.
  • Couplage ESD dans d'autres broches du processeur. Les sondes de portée en particulier peuvent agir comme des antennes, coupler du bruit dans la puce et provoquer des réinitialisations étranges. J'ai entendu des rapports sur des codes de réinitialisation "opcode invalide".
  • Mauvais joint de soudure / pont intermittent. Peut être en train de perdre ou de court-circuiter un rail d'alimentation, soit sur le processeur, soit ailleurs sur la carte.
  • Glitch / bruit du rail d'alimentation. Pourrait être causé par un certain nombre de problèmes externes, y compris un régulateur endommagé ou une baisse de l'alimentation en amont. Assurez-vous que les rails d'alimentation alimentant le processeur sont stables. Peut nécessiter plus de capuchon quelque part, peut-être découpler le capuchon directement sur le processeur.
  • Certains microcontrôleurs ont une broche Vcap, qui ne doit pas être connectée au VDD et doit avoir son propre condensateur en commun. Le fait de ne pas connecter correctement cette broche peut avoir des résultats imprévisibles.
  • Le fait de conduire une entrée analogique négative au-delà d'une certaine limite provoque une réinitialisation qui signale en RCON comme une panne de courant. La même chose peut être vraie pour les entrées numériques.
  • Un dV / dt très élevé dans un convertisseur de puissance à proximité peut provoquer une réinitialisation de la panne de courant. (Voir cette question .) J'ai vu cela dans deux cas, et dans un, j'ai pu le suivre jusqu'au couplage capacitif. Un IGBT commutait de 100 à 200 ampères et, à l'arrêt, certains circuits de rétroaction voyaient quelques microsecondes de bruit, passant de 2 V à plus de 8 V sur un processeur de 3,3 V. L'augmentation du capuchon du filtre sur ce rail de rétroaction a entraîné l'arrêt des réinitialisations. On pourrait imaginer que l'ajout d'un filtre dV / dt à travers le transistor aurait pu avoir un effet similaire.

Logiciel:

  • Minuteur de surveillance. Assurez-vous que le temporisateur du chien de garde est effacé suffisamment souvent, en particulier dans les branches de votre code qui peuvent prendre un certain temps à s'exécuter, comme l'écrit l'EEPROM. Testez-le en désactivant le chien de garde pour voir si le problème disparaît.
  • Diviser par zéro. Si vous effectuez une opération de division dans votre code, assurez-vous que le diviseur ne peut jamais être égal à zéro. Ajoutez une vérification des limites avant la division. N'oubliez pas que cela s'applique également aux opérations modulo .
  • Débordement de pile. Trop d'appels de fonction imbriqués peuvent entraîner le système à manquer de mémoire dynamique pour la pile, ce qui peut entraîner des plantages à des points inhabituels dans l'exécution de code.
  • Dépassement de pile. Si vous programmez dans l'assembleur, vous pouvez accidentellement exécuter plus de RETOUR que vous n'avez exécuté d'appels.
  • Routine d'interruption inexistante. Si une interruption est activée, mais qu'aucune routine d'interruption n'est définie, le processeur peut se réinitialiser.
  • Routine de piège inexistante. Semblable à une routine d'interruption, mais suffisamment différent, je le répertorie séparément. J'ai vu deux projets distincts utilisant dsPIC 30F4013 qui se réinitialisaient de manière aléatoire, et la cause a été suivie dans un piège appelé mais non défini. Bien sûr, vous avez maintenant la question de savoir pourquoi un piège est appelé en premier lieu, ce qui pourrait être un certain nombre de choses, y compris une erreur de silicium. Mais la définition de tous les gestionnaires de pièges devrait probablement être une bonne première étape dans le diagnostic des réinitialisations inexpliquées.
  • Échec du pointeur de fonction. Si un pointeur de fonction ne pointe pas vers un emplacement valide, déréférencer le pointeur et appeler la fonction pointée peut provoquer une réinitialisation. Une cause amusante de ceci était quand j'initialisais une structure, avec des valeurs successives de NULL (pour un pointeur de fonction) et -1 (pour un int). La virgule a été typée, donc le pointeur de fonction a été initialisé à NULL-1. Donc, ne présumez pas que juste parce que c'est un CONST, il doit contenir une valeur valide!
  • Index de tableau invalide / négatif. Assurez-vous que vous effectuez une vérification des limites sur tous les indices de tableau, les limites supérieures et inférieures, le cas échéant.
  • Création d'un tableau de données dans la mémoire programme qui est plus grand que la plus grande section de la mémoire programme. Cela peut même ne pas générer d'erreur de compilation.
  • La conversion de l'adresse d'une structure en un pointeur vers un autre type, le déréférencement de ce pointeur et l'utilisation du pointeur déréférencé comme LVALUE dans une instruction peuvent provoquer un blocage. Voir cette question . Vraisemblablement, cela s'applique également à d'autres comportements non définis.

Sur certains dsPIC, le registre RCON stocke des bits indiquant la cause de la réinitialisation. Cela peut être très utile lors du débogage.

Stephen Collings
la source
1
@reset pin: une broche de réinitialisation flottante est connue pour les réinitialisations parasites. Attachez-le toujours à Vcc via une résistance.
jippie
4
Ceci est une liste incroyablement exhaustive. Je crois dans mon expérience avec les AVR que la plupart des situations, sinon toutes, entraîneront des résultats inattendus ou des réinitialisations.
HL-SDK
4
Permettez-moi d'en ajouter un autre pour la programmation en langage assembleur - Registre inégalé PUSH et POP de la pile.
Michael Karas
2
Un couple de plus: sous le matériel, réinitialisation du brownout. Sous logiciel, instruction de réinitialisation du logiciel. Les deux sont disponibles sur plusieurs microcontrôleurs.
tcrosley
2
Un autre pour la liste: les téléphones portables placés près d'un câble peuvent induire des quantités de tension étonnamment importantes sur les lignes faiblement entraînées. Si une ligne de réinitialisation passe par un câble (par exemple, si une carte peut forcer la réinitialisation de l'autre), un téléphone portable près du câble peut déclencher une réinitialisation si, par exemple, il reçoit un appel.
supercat
7

La broche RESET doit être correctement entraînée par un circuit de réinitialisation surveillant la sur / sous tension et créant un signal de réinitialisation suffisamment long. Dans cet esprit, mon expérience avec une réinitialisation matérielle incontrôlée vient alors de:

  • Diaphonie de commutation de lignes dans la broche / ligne RESET (les rendre courtes)
  • Décalages / boucle au sol provoqués par la mise sous / hors tension d'une charge de courant élevée externe
  • Pic de tension non filtré par l'alimentation et trop court pour activer la réinitialisation appropriée
  • Commutation de charges externes par le microcontrôleur qui provoque les problèmes ci-dessus (principalement sur des charges inductives comme le moteur en marche / arrêt, des relais ou une vieille lampe (courant d'appel)
  • La pointe de tension / courant sur l'une des broches du microcontrôleur (le pire est l'oscillateur) peut provoquer un courant inverse et peut commuter le registre interne (comme les pointes de tension sur la ligne d'alimentation). En général, lors de l'interfaçage avec une sorte d'environnement industriel, il faut faire preuve de prudence (pour plus d'informations, voir: http://www.ichaus.biz/wp1_mcu_interface ). Le décalage de niveau sur les E / S, le filtrage des entrées et les sorties de commutation logicielle doivent être pris en compte. Rendre les lignes d'alimentation propres a la première priorité du côté matériel. Puis RESET et broches d'oscillateur, puis lignes IO. -mm
user27465
la source
1
Les changements de terrain m'ont juste mordu. Dans mon cas, j'avais une partie particulière de mon filet commun portant ~ 100 ampères. Le microcontrôleur était référencé d'un côté de cette trace épaisse, mais une partie des circuits que le microcontrôleur pilotait était référencée à l'autre extrémité de la trace. La trace n'était que de 3 mOhm, mais à 100 ampères, cela suffit pour obtenir une différence de 300 mV entre le micro et les périphériques qu'il conduisait. Rerouté les périphériques pour qu'ils soient communs à la même extrémité de cette trace que le contrôleur, et tout va bien maintenant. Il n'y a pas de nœud à ces courants.
Stephen Collings
4

Une possibilité supplémentaire que je n'ai pas vue dans cette liste est un périphérique qui prend en charge ICSP. Si des tractions insuffisantes sont utilisées sur les lignes qui se déclenchent en mode de programmation série du circuit, il est parfois possible d'entrer dans ce mode de manière aléatoire. Cela conduit à une réinitialisation un court intervalle plus tard lorsqu'aucune mise à jour du programme n'est envoyée aux lignes de récepteur série désignées. Je soupçonne qu'un temporisateur de surveillance interne est réinitialisé si ICSP est démarré et qu'aucune donnée de programmation n'est envoyée. C'est une erreur que j'ai commise et j'ai passé beaucoup de temps à trouver un 16F876.

steverino
la source
3

Assurez-vous que si vous utilisez des puces logiques CMOS ou TTL dans votre circuit, elles disposent de condensateurs de découplage adéquats entre Vdd et la masse (généralement 0,1 uF). J'utilisais un CD4021 dans une conception et lorsqu'il était en cours d'utilisation, il provoquait apparemment une pointe qui provoquait le redémarrage du microprocesseur. Ensuite, le cycle se répétait. C'est aussi pourquoi c'est une bonne idée de mettre une séquence de test évidente (comme faire clignoter une LED plusieurs fois) au début de votre code afin que vous sachiez que le microprocesseur fonctionne et exécute du code.

Mark Jensen
la source
2

C'est l'une de ces rares choses qui pourraient apparaître:

J'avais un projet qui impliquait un microcontrôleur et il se réinitialisait sporadiquement. En bref, il s'est avéré que certaines options devaient être activées ou désactivées, sinon des réinitialisations pourraient se produire. Je n'ai découvert cela qu'en lisant les errata après avoir abandonné tout le reste.

Maintenant, je prends l'habitude de lire les errata avant même de décider d'utiliser une puce pour savoir dans quoi je me mets et si c'est quelque chose que je peux gérer. Malheureusement, après l'obtention du diplôme, je n'avais vraiment personne pour m'informer sur les pratiques courantes, alors une grande partie de mon apprentissage dans le monde réel s'est faite par échec et par frustration.

efox29
la source
Je ne savais même pas que cette question était ancienne et qu'une réponse avait déjà été fournie. Oops.
efox29